Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用。
对象关系映射(英语:Object Relation Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。
对象-关系映射,是随着面向对象的软件开发方法发展而产生的。面向对象的开发方法是当今企业级应用开发环境中的主流开发方法,关系数据库是企业级应用环境中永久存放数据的主流数据存储系统。对象和关系数据是业务实体的两种表现形式,业务实体在内存中表现为对象,在数据库中表现为关系数据。内存中的对象之间存在关联和继承关系,而在数据库中,关系数据无法直接表达多对多关联和继承关系。因此,对象-关系映射(ORM)系统一般以中间件的形式存在,主要实现程序对象到关系数据库数据的映射。
ORM模型的简单性简化了数据库查询过程。使用ORM查询工具,用户可以访问期望数据,而不必理解数据库的底层结构
com.mysql.jdbc.Driver
jdbc:mysql:///hibernatetest
root
1234
org.hibernate.connection.C3P0ConnectionProvider
20
5
100
3000
true
true
org.hibernate.dialect.MySQLDialect
update
true
//插入数据
@Test
public void addCustomer(){
Customer c=new Customer();
c.setName("薛仁贵");
c.setAddress("高丽都护府");
c.setSex("男");
Configuration configure = new Configuration().configure();// 加载hibernate.cfg.xml
//configure.addResource("com/itheima/domain/Customer.hbm.xml");手动加载映射
configure.addClass(Customer.class);
SessionFactory sessionFactory = configure.buildSessionFactory();
//configure.addClass(Customer.class);
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
session.save(c);
transaction.commit();
session.close();
sessionFactory.close();
1、通过Configuration().configure();读取并解析hibernate.cfg.xml配置文件。
2、由hibernate.cfg.xml中的
3、通过config.buildSessionFactory();//得到sessionFactory。
4、sessionFactory.openSession();//得到session。
5、session.beginTransaction();//开启事务。
6、persistent operate;
7、session.getTransaction().commit();//提交事务
8、关闭session;
9、关闭sessionFactory;
使用HQL
、Query接口让你方便地对数据库及持久对象进行查询,它可以有两种表达方式:HQL语言或本地数据库的SQL语句。Query经常被用来绑定查询参数、限制查询记录数量,并最终执行查询操作。
无名称参数 from Customer where name=?
对其进行赋值 query.setParameter(0,”张三”)
有名称参数 from Customer where name=:myname;
对其进行赋值 query.setParameter(“myname”,”李四”);
如果查询结果可以保证就是唯一 的,我们可以使用
query. uniqueResult()来得到一个单独对象.
SQLQuery
要想执行本地sql SQLQuery sqlQuery=session.createSqlQuery(String sql);
使用addEntity方法来将结果封装到指定的对象中,如果不封装,得到的是List
如果sql中有参数,我们使用setParameter方法完成参数传递。如果结果就是一个可以使用uniqueResult()来得到一个单独对象。
Criteria
Criteria接口与Query接口非常类似,允许创建并执行面向对象的标准化查询。值得注意的是Criteria接口也是轻量级的,它不能在Session之外使用。
首先我想使用Criteria,必须得到Criteria Criteria criteria=Session.createCriteria()
Session session =HibernateUtils.getSession();
session.beginTransaction();
Criteria criteria = session.createCriteria(Customer.class);
//查询所有
List list = criteria.list();
System.out.println(list);
session.getTransaction().commit();
session.close();
//分页查询
criteria.setFirstResult(10);
criteria.setMaxResults(10);
List list = criteria.list();
System.out.println(list);
//多条件查询
criteria.add(Restrictions.eq("name", "李孝恭"));
session.getTransaction().commit();
session.close();
瞬时态:也叫做临时态或自由态,它一般指我们new出来的对象,它不存在OID,与hibernate session无关联,在数据库中也无记录。它使用完成后,会被jvm直接回收掉,它只是用于信息携带。
简单说:无OID 与数据库中的信息无关联,不在session管理范围内。
持久态:在hibernate session管理范围内,它具有持久化标识OID它的特点,在事务未提交前一直是持久态,当它发生改变时,hibernate是可以检测到的。
简单说:有OID 由session管理,在数据库中有可能有,也有可有没有。
托管态:也叫做游离态或离线态,它是指持久态对象失去了与session的关联,托管态对象它存在OID,在数据库中有可能存在,也有可能不存在。
对于托管态对象,它发生改变时hibernet不能检测到。
三种状态切换
瞬时态(new 出来的)
瞬时------à持久 save saveOrUpdate
瞬时-----à脱管(游离) 手动设置oid
.持久态 它是由session管理
持久-------à瞬时 delete() 被删除后持久化对象不在建议使用
持久-----à脱管 注意:session它的缓存就是所说的一级缓存
evict(清除一级缓存 中指定的一个对象)
clear(清空一级缓存)
close(关闭,清空一级缓存)
.脱管态 (它是无法直接获取)
脱管-----à瞬时 直接将oid删除
脱管----à持久 update saveOrUpdate lock(过时)
Hibernate的一级缓存就是指session缓存。
actionQueue它是一个行列队列,它主要记录crud操作的相关信息
persistenceContext它是持久化上下文,它其实是真正缓存。
在session中定义了一系列的集合来存储数据,它们构成session缓存。只要session没有关闭,它就会一直存在。
当我们通过hibernate中的session提供的一些API例如 save get update等进行操作时,就会将持久化对象保存到session中,当下一次在去查询缓存中具有的对象(OID值来判断),就不会去从数据库查询,而是直接从缓存中获取。
Hibernate的一级缓存存在的目的就是为了减少对数据库访问。
一级缓存特点:
clear 清空一级缓存.
evict 清空一级缓存中指定的一个对象。
refresh重新查询数据库,用数据库中信息来更新一级缓存与快照
public void test5() {
// 1.得到session
Session session = HibernateUtils.openSession();
session.beginTransaction();
// 操作
List list = session.createQuery("from Customer").list(); // 会存储数据到一级缓存
session.clear(); // 清空一级缓存
Customer c = session.get(Customer.class, 1); // 会先从session一级缓存
// 中获取,如果不存在,才会从数据库获取
session.evict(c); // 从一级缓存 中删除一个指定的对象
Customer cc = session.get(Customer.class, 1);
cc.setName("kkkk");
session.refresh(cc); // 重新查询数据库,用数据库中信息来更新一级缓存与快照
// 2.事务提供,关闭
session.getTransaction().commit();
session.close();
}
Hibernate框架基于ORM设计思想,它将关系型数据库中的表与我们java中的类进行映射,一个对象就对应着表中的一条记录,而表中的字段对应着类中的属性。
数据库中表与表之间存在着三种关系,也就是系统设计中的三种实体关系。
Inverse它的值如果为true代表,由对方来维护外键。
Inverse它的值如果为false代表,由本方来维护外键。
关于inverse的取值: 外键在哪一个表中,我们就让哪一方来维护外键。
使用cascade可以完成级联操作
它可常用取值:
none这是一个默认值
save-update,当我们配置它时,底层使用save update或save-update完成操作,级联保存临时对象,如果是游离对象,会执行update.
delete 级联删除
delete-ophan 删除与当前对象解除关系的对象。
all 它包含了save-update delete操作
all-delete-orphan 它包信了delete-orphan与all操作
@Entity 声明一个实体
@Table来描述类与表对应
@Id来声明一个主键
@GenerateValue 用它来声明一个主键生成策略 默认情况下相当于native 可以选择的主键生成策略 AUTO IDENTITY SEQUENCE
@Column来定义列
@Temporal来声明日期类型
@Transient声明不生成在表中
@OneToMany一对多
@ManyToOne多对一
@Joinclum添加列
@Cascade级联操作
mappedBy主键由哪一方维护
我们在Customer中配置了mappedBy=”c”它代表的是外键的维护由Order方来维护,而Customer不维护,这时你在保存客户时,级联保存订单,是可以的,但是不能维护外键
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
@ManyToMany(targetEntity = Teacher.class)
// 使用JoinTabl来描述中间表,并描述中间表中外键与Student,Teacher的映射关系
// joinColumns它是用来描述Student与中间表中的映射关系
// inverseJoinColums它是用来描述Teacher与中间表中的映射关系
@JoinTable(name = "s_t", joinColumns = {
@JoinColumn(name = "c_student_id", referencedColumnName = "id") }, inverseJoinColumns = {
@JoinColumn(name = "c_teacher_id", referencedColumnName = "id") })
@Cascade(CascadeType.ALL)
private Set teachers = new HashSet();
HQL是我们在hibernate中是常用的一种检索方式。
HQL(Hibernate Query Language)提供更加丰富灵活、更为强大的查询能力
因此Hibernate将HQL查询方式立为官方推荐的标准查询方式,HQL查询在涵盖Criteria查询的所有功能的前提下,提供了类似标准SQL语 句的查询方式,同时也提供了更加面向对象的封装。完整的HQL语句形式如下: Select/update/delete…… from …… where …… group by …… having …… order by …… asc/desc 其中的update/delete为Hibernate3中所新添加的功能,可见HQL查询非常类似于标准SQL查询。
基本步骤:
public class HQLTest {
// 命名查询
@Test
public void test9() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
// 1.我要查询张龙这个客户的订单
Customer c = session.get(Customer.class, 1);
Query query = session.getNamedQuery("findOrderByCustomer"); // from Order where c=:c
// 2.现在hql它的参数是一个实体
List list = query.setEntity("c", c).list();
System.out.println(list);
session.getTransaction().commit();
session.close();
}
// 命名查询
@Test
public void test8() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
Query query = session.getNamedQuery("myHql");
List list = query.list();
System.out.println(list);
session.getTransaction().commit();
session.close();
}
// 投影查询
@Test
public void test7() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
// 1.查询出所有的Customer的name
// String hql = "select name from Customer";
// List list = session.createQuery(hql).list();
// System.out.println(list); // [张龙, 张三丰]
// 如果只查询一个列,得到的结果List
QBC(query by criteria),它是一种更加面向对象的检索方式。
QBC步骤:
1.通过Session得到一个Criteria对象 session.createCriteria()
2.设定条件 Criterion实例 它的获取可以通过Restrictions类提供静态。Criteria的add方法用于添加查询条件
3.调用list进行查询 criterfia.list.
public class QBCTest {
// 离线的检索
@Test
public void test6() {
// 1.得到一个DetachedCriteria
DetachedCriteria dc = DetachedCriteria.forClass(Customer.class);
dc.add(Restrictions.like("name", "张_"));
// 2.生成Criteria执行操作
Session session = HibernateUtils.openSession();
session.beginTransaction();
Criteria criteria = dc.getExecutableCriteria(session);
List list = criteria.list();
System.out.println(list);
session.getTransaction().commit();
session.close();
}
// 统计检索
@Test
public void test5() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
// 1.统计订单总数
Criteria criteria = session.createCriteria(Order.class);
// Object obj =
// criteria.setProjection(Projections.rowCount()).uniqueResult();
// //统计总行数 count(id)
// System.out.println(obj);
// 2.订单的总价格----分组统计根据客户
// criteria.setProjection(Projections.sum("money")); //统计总金额
criteria.setProjection(
Projections.projectionList().add(Projections.sum("money")).add(Projections.groupProperty("c")));
List list = criteria.list(); // 在这个集合中保存的是Object[money的统计信息,客户信息]
for (Object[] objs : list) {
for (Object obj : objs) {
System.out.println(obj);
}
}
session.getTransaction().commit();
session.close();
}
// 分页检索
@Test
public void test4() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
Criteria criteria = session.createCriteria(Order.class);
criteria.setFirstResult((2 - 1) * 6);
criteria.setMaxResults(6);
List list = criteria.list();
System.out.println(list);
session.getTransaction().commit();
session.close();
}
// 条件检索
@Test
public void test3() {
Session session = HibernateUtils.openSession();
session.beginTransaction();
// 1.查询名称叫张某客户 张_
Criteria criteria = session.createCriteria(Customer.class);
Criterion like = Restrictions.like("name", "张_"); // 其它的条件 lt < gt > le
// <= ge>= eq==
criteria.add(like);// 添加条件
Customer c = (Customer) criteria.uniqueResult();
System.out.println(c);
// 2.查询订单价格在1050以上的,并且它的客户是张某
Criteria cri = session.createCriteria(Order.class);
SimpleExpression lt = Restrictions.gt("money", 1050d); // >1050
SimpleExpression eq = Restrictions.eq("c", c); // 与c客户相同
LogicalExpression and = Restrictions.and(lt, eq);
cri.add(and);
// List orders =
// cri.add(Restrictions.and(Restrictions.gt("money", 1050d),
// Restrictions.eq("c", c))).list();
List orders = cri.list();
System.out.println(orders);
session.getTransaction().commit();
session.close();
}
// 排序检索
@Test
public void test2() {
// 查询订单信息 根据订单的价格进行排序
Session session = HibernateUtils.openSession();
session.beginTransaction();
Criteria criteria = session.createCriteria(Order.class);
// 指定排序
// criteria.addOrder(org.hibernate.criterion.Order.desc("money")); // 降序
criteria.addOrder(org.hibernate.criterion.Order.asc("money")); // 升序
List list = criteria.list();
System.out.println(list);
session.getTransaction().commit();
session.close();
}
// 基本检索
@Test
public void test1() {
// 查询所有Customer
Session session = HibernateUtils.openSession();
session.beginTransaction();
// 1.得到一个Criteria对象
Criteria criteria = session.createCriteria(Customer.class);
// 2.调用list方法
List list = criteria.list();
System.out.println(list);
session.getTransaction().commit();
session.close();
}
}
Hibernate中设置事务隔离级别
它可取的值有 1 2 4 8
1代表的事务隔离级别为READ UNCOMMITTED
2代表的事务隔离级别为READ COMMITTED
4.代表的事务隔离级别为 REPEATABLE READ
8代表的事务隔离级别为 SERIALIZABLE
4
HQL优化
1.使用参数绑定
1.使用绑定参数的原因是让数据库一次解析SQL,对后续的重复请求可以使用用生成好的执行计划,这样做节省CPU时间和内存。
2.避免SQL注入
2.尽量少全长NOT
如果where子句中包含not关键字,那么执行时该字段的索引失效。
3.尽量使用where来替换having
Having在检索出所有记录后才对结果集进行过滤,这个处理需要一定的开销,而where子句限制记录的数目,能减少这方面的开销
4.减少对表的查询
在含有子查询的HQL中,尽量减少对表的查询,降低开销
5.使用表的别名
当在HQL语句中连接多个表时,使用别名,提高程序阅读性,并把别名前缀与每个列上,这样一来,可以减少解析时间并减少列歧义引起的语法错误。
6.实体的更新与删除
在hibernate3以后支持hql的update与delete操作
一级缓存也叫做session缓存,在一个hibernate session有效,这级缓存的可干预性不强,大多于hibernate自动管理,但它提供清除缓存的方法,这在大批量增加(更新)操作是有效果的,例如,同时增加十万条记录,按常规进行,很可能会出现异常,这时可能需要手动清除一级缓存,session.evict以及session.clear.
检索策略
延迟加载
延迟加载 是hibernate为提高程序执行的效率而提供的一种机制,即只有真正使用该对象的数据时才会创建。
load方法采用的策略延迟加载.
get方法采用的策略立即加载。
检索策略分为两种:
set上的fetch与lazy它主要是用于设置关联的集合信息的抓取策略。
Fetch可取值有:
lazy可取值有: