现在对于Hibernate的基本配置还不熟悉的请移步到
本篇介绍一下Hibernate的实体规则和对象状态等信息。
一.Hibernate中的实体规则
1.实体类创建注意事项
1.1 持久化类提供无参数构造 ------hibernate底层是通过反射技术调用实体的无参的构造函数来创建对象。
1.2 成员变量私有 提供get/set方法 需要提供属性
1.3 持久化类中的类型应尽量使用包装类型----------可赋值为null ,基本数据类型不具有
1.4 持久化类需要提供oid,与数据库中的主键列对应
1.5 不要用final修饰class ------ hibernate使用cglib代理生成代理对象,代理对象是继承被代理对象,使用final将无法生成代理
2.主键类型
2.1 自然主键(少见) ----表的业务列中,有某业务列符合,必须有,并且不重复的特征时,该列可以作为主键使用.
2.2 代理主键(常见) ------ 表的业务列中,没有某业务列符合,必须有,并且不重复的特征时,创建一个没有业务意义的列作为主键
3.主键生成策略
3.1 自然主键 -----assigned:自然主键生成策略. hibernate不会管理主键值.由开发人员自己录入.
3.2 代理主键 -------- generator:主键生成策略.就是每条记录录入时,主键的生成规则.(7个)
identity : 主键自增.由数据库来维护主键值.录入时不需要指定主键.
sequence: Oracle中的主键生成策略.
increment(了解): 主键自增.由hibernate来维护.每次插入前会先查询表中id最大值.+1作为新主键值.
hilo(了解): 高低位算法.主键自增.由hibernate来维护.开发时不使用.
native:hilo+sequence+identity 自动三选一策略.
uuid: 产生随机字符串作为主键. 主键类型必须为string 类型.
二.Hibernate中的对象状态
1.对象状态分类
1.1 瞬时状态 ----没有id,没有在session缓存中
1.2 持久化状态-----有id,在session缓存中
1.3 游离/托管状态-----有id ,没有在session缓存中
2.三种状态的转化
三.Hibernate进阶----一级缓存
1.缓存技术是为了提高数据库的操作效率。
1.1 缓存原理
1.2 快照技术 ----减少不必要的修改语句的发送
四.Hibernate中的事务
1.事务的特性
a.原子性 (Atomicity)原子性是指事务是一个不可分割的工作单位,事务中的操作 要么都发生,要么都不发生。
b.一致性 (Consistency)一个事务中,事务前后数据的完整性必须保持一致。
c.隔离性 (Isolation)是指多个用户并发访问数据库时,一个用户的 事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。
d.持久性(Durability)是指一个事务一旦被提交,它对数据库中数据的改变 就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
2.事务的并发问题
a.脏读: B事务读取到了A事务尚未提交的数据
b.不可重复读 :一个事务中 两次读取的数据的内容不一致(updata)
c.虚读/幻读:一个事务中 两次读取的数据的数量不一致 (insert /delete)
3.事务的隔离级别
a.读未提交 :读取尚未提交的数据 :哪个问题都不能解决
b.读已提交:读取已经提交的数据 :可以解决脏读 ---- oracle默认的
c.可重复读:重读读取:可以解决脏读 和 不可重复读 ---mysql默认的
d.串行化:可以解决 脏读 不可重复读 和 虚读---相当于锁表
4.如何在hibernate中设置数据库的隔离级别
5.在项目中如何管理事务 ----一般姿势如下
5.1 在业务开始之前打开事务,业务执行之后提交事务,执行过程中出现异常,回滚事务。
5.2 在dao层操作数据库要用到session对象,在Service层操作数据库也要用到session对象,要确保两处使用的是同一个对象。
5.3 使用hibernate时只需要调用sf.getCurrentSession()方法即可获得与当前线程绑定的session对象。
5.3.1 调用getCurrentSession()方法需要在主配置中添加如下配置
5.3.2 通过getCurentSession()方法获得的session对象,当事务提交时,session会自动关闭,不需要手动close。
五.hibernate中的批量查询
1.HQL查询(Hibernate query language)(适合不复杂的多表查询)
1.1基本查询
//1> 书写HQL语句
// String hql = " from com.auicyh.domain.Customer ";
String hql = " from Customer "; // 查询所有Customer对象
//2> 根据HQL语句创建查询对象
Query query = session.createQuery(hql);
//3> 根据查询对象获得查询结果
List<Customer> list = query.list(); // 返回list结果
//query.uniqueResult();//接收唯一的查询结果
System.out.println(list);
1.2条件查询
//1> 书写HQL语句
//String hql = " from Customer where cust_id = 1 ";
String hql = " from Customer where cust_id = 2 ";
//2> 根据HQL语句创建查询对象
Query query = session.createQuery(hql);
//3> 根据查询对象获得查询结果
Customer c = (Customer) query.uniqueResult();
System.out.println(c);
1.3带占位符的条件查询
//1> 书写HQL语句
String hql = " from Customer where cust_id = ? ";
//2> 根据HQL语句创建查询对象
Query query = session.createQuery(hql);
//设置参数
//query.setLong(0, 1l);
query.setParameter(0, 3l);//索引序号从0开始表示第一个?号,第二个参数表示类型
//3> 根据查询对象获得查询结果
Customer c = (Customer) query.uniqueResult();
System.out.println(c);
1.4命名占位符条件查询
//1> 书写HQL语句
String hql = " from Customer where cust_id = :cust_id ";
//2> 根据HQL语句创建查询对象
Query query = session.createQuery(hql);
//设置参数
query.setParameter("cust_id", 1l);
//3> 根据查询对象获得查询结果
Customer c = (Customer) query.uniqueResult();
System.out.println(c);
1.5 分页查询
//1> 书写HQL语句
String hql = " from Customer "; // 查询所有Customer对象
//2> 根据HQL语句创建查询对象
Query query = session.createQuery(hql);
//设置分页信息 limit ?,?
query.setFirstResult(1);//索引页对应第一个?
query.setMaxResults(2);//每页显示的个数对应第二个?
//3> 根据查询对象获得查询结果
List<Customer> list = query.list();
System.out.println(list);
2.Criteria查询(单表条件查询)
2.1基本查询
//查询所有的Customer对象
Criteria criteria = session.createCriteria(Customer.class);
List<Customer> list = criteria.list();
System.out.println(list)
2.2条件查询
//创建criteria查询对象
Criteria criteria = session.createCriteria(Customer.class);
//添加查询参数 => 查询cust_id为3的Customer对象
criteria.add(Restrictions.eq("cust_id", 3l));
//执行查询获得结果
Customer c = (Customer) criteria.uniqueResult();
System.out.println(c);
2.3分页查询
//创建criteria查询对象
Criteria criteria = session.createCriteria(Customer.class);
//设置分页信息 limit ?,?
criteria.setFirstResult(1);//对应第一个? 索引
criteria.setMaxResults(2);//对应第二个? 个数
//执行查询
List<Customer> list = criteria.list();
System.out.println(list);
2.4设置查询总记录
//创建criteria查询对象
Criteria criteria = session.createCriteria(Customer.class);
//设置查询的聚合函数 => 总行数
criteria.setProjection(Projections.rowCount());
//执行查询
Long count = (Long) criteria.uniqueResult();
System.out.println(count);
3.原生SQL查询
3.1基本查询
3.1.1 返回数组list
//1 书写sql语句
String sql = "select * from cst_customer";
//2 创建sql查询对象
SQLQuery query = session.createSQLQuery(sql);
//3 调用方法查询结果
List<Object[]> list = query.list();
//query.uniqueResult();
for(Object[] objs : list){
System.out.println(Arrays.toString(objs));
}
3.1.2 返回对象list
//1 书写sql语句
String sql = "select * from cst_customer";
//2 创建sql查询对象
SQLQuery query = session.createSQLQuery(sql);
//指定将结果集封装到哪个对象中
query.addEntity(Customer.class);
//3 调用方法查询结果
List<Customer> list = query.list();
System.out.println(list);
3.2条件查询
//1 书写sql语句
String sql = "select * from cst_customer where cust_id = ? ";
//2 创建sql查询对象
SQLQuery query = session.createSQLQuery(sql);
query.setParameter(0, 2l);
//指定将结果集封装到哪个对象中
query.addEntity(Customer.class);
//3 调用方法查询结果
List<Customer> list = query.list();
System.out.println(list);
3.3分页查询
//1 书写sql语句
String sql = "select * from cst_customer limit ?,? ";
//2 创建sql查询对象
SQLQuery query = session.createSQLQuery(sql);
query.setParameter(0, 0);//注意第一个参数对应第一个?是从0开始
query.setParameter(1, 1);
//指定将结果集封装到哪个对象中
query.addEntity(Customer.class);
//3 调用方法查询结果
List<Customer> list = query.list();
System.out.println(list);