Hibernate学习笔记二:hibernate实体详解,主键生成策略、hibernate三种状态、一级缓存、事务操作等
文章目录
1. Hibernate学习笔记二:hibernate实体详解
1.1. 实体类创建的注意事项
- 持久化类必须提供无参构造函数,即Class类的newInstance方法 这个方法就是通过调用默认构造方法来创建实例对象的。如果没有无参构造函数,就无法创建实例对象。
- 成员变量私有,提供共有get/set方法访问.需提供属性。
- 持久化类中的属性应尽量使用 包装类型。
- 持久化类应提供OID,与数据库中的主键列对应.OID即类似于数据库表里的主键。
- 不要用final修饰class。hibernate框架的代理模式是用继承的方式实现的,这里User 类被final 修饰无法继承,那么就无法生成User的代理对象
1.2. hibernate框架中的主键类型
- 自然主键:即该表所有的属性中有一个属性可以能让一条记录表示唯一。
- 代理主键:就是所有属性都无法表示唯一,那只好创建一个喽。
1.3. 主键生成策略
- 主键生成策略:就是每条记录录入时,主键生成规则。有七种生成策略,前六个属于代理主键,最后一个适合自然主键
- sequence: Oracle中的主键生成策略.
- sequence: Oracle中的主键生成策略.
- increment(了解): 主键自增.由hibernate来维护.每次插入前会先查询表中id最大值.+1作为新主键值.
- hilo(了解): 高低位算法.主键自增.由hibernate来维护.开发时不使用.
- native:hilo+sequence+identity 自动三选一策略.
- uuid: 产生随机字符串作为主键. 主键类型必须为string 类型.
- assigned:自然主键生成策略. hibernate不会管理主键值.由开发人员自己录入.
1.4. hibernate的状态
- 分为三种状态:瞬时状态,持久化状态,游离托管状态
- 瞬时状态:没有oid,没有在session缓存中
- 持久化状态:有id,在session缓存中,特点:持久化状态对象的任何变化都会自动同步到数据库中。
- 游离|托管状态:有id,没有在session缓存中
- session的save()方法其实不能理解成保存,理解成瞬时状态转换成持久化状态的方法。
- 主键自增:在执行save方法时,为了将对象转化为持久化状态,必须生成id值,所以需要执行insert语句生成。
- increment:主键生成机制在执行save方法时,为了生成id,会先执行查询id最大值的sql语句。
1.5. hibernate进阶:一级缓存
- 缓存:提高效率.hibernate中的一级缓存也是为了提高操作数据库的效率.
- 提高效率手段1:提高查询效率
- 提高效率手段2:减少不必要的修改语句发送
1.6. hibernate事务操作
- 事务特性:
atomicity原子性
consistency一致性
isolation隔离性
durability持久性
- 事务并发问题
脏读:能读取了对方修改还未提交的数据,可能对方采取了回滚操作,应该读提交后的数据
不可重复读:在一次事务读取中,读取的内容应该相同,如果不同就是不可重复读。针对update操作
幻|虚读:在一次事务中读取的总量不一样,针对insert操作
事务并发问题可参考文章:事务并发问题
- 事务的隔离级别
读未提交:会产生脏读,不可重复读,虚读问题
读已提交:会产生不可重复读,虚读问题
可重复的:会产生虚读问题(mysql默认级别)
串行化:没有问题
- 在hibernate中指定隔离级别,在hibernate.cfg.xml中添加如下代码
<property name="hibernate.connection.isolation">4</property>
- 在项目如何管理事务
- 业务开始之前打开事务,业务执行之后提交事务. 执行过程中出现异常.回滚事务.
- 在dao层操作数据库需要用到session对象.在service控制事务也是使用session对象完成. 我们要确保dao层和service层使用的使用同一个session对象
- 在hibernate中,确保使用同一个session的问题,hibernate已经帮我们解决了. 我们开发人员只需要调用sf.getCurrentSession()方法即可获得与当前线程绑定的session对象,调用getCurrentSession()需要配置
<property name="hibernate.current_session_context_class">thread</property>
-
注意2:通过getCurrentSession方法获得的session对象.当事务提交时,session会自动关闭.不要手动调用close关闭.
-
一般事务调用写在service层,因为service层可以在调用dao层之前绑定事务,这样也能保证dao层和service层是同一个session.
1.7. Hibernate 的hql查询
- hql查询时独家查询,属于面向对象的查询语言,即hql语句都是面向实体类里的属性的不是面向数据库的。
- hibernate的占位符有:?号占位符,命名占位符: :name命名占位符的好处是赋值时不需要写数字了。
- hibernate的分页查询:setFirstResult(),setMaxResult();
1.8. Hibernate的criteria查询
- criteria是无语句查询
- 查询所有内容
//只写一个对象的加载类
Criteria criteria=session.createCriteria(Customer.class);
List<Customer> list=criteria.list();
- 条件查询
- 创建Criteria查询对象
- 添加查询参数
- 执行查询获得结果
Criteria criteria=session.createCriteria(Customer.class);
//添加查询参数
criteria.add(Restrictions.eq("fieldName",参数));
//执行查询获得结果
Customer c=(Customer)criteria.uniqueResult();
- Criteria有对应各种字符例如> = !=等运算符的字符,太多不再展示。太麻烦,不建议学。适合单表条件查询
- 原生sql语句查询,执行复杂的查询业务
- 书写sql语句
- 创建原生的sql查询对象
- 将结果封装到对象中,也可以返回到一个Object[]数组中,通过for循环打印。
- 打印出结果
- 如果是条件查询,占位符仍然从0开始,因为仍是hibernate体系
String sql="select * from tableName";
SQLQuery query=session.createSQLQuery(sql);
//将结果集封装到对象当中,需要添加一个对象
query.addEntity(Customer.class);
List<Customer> list=query.list();
System.out.println(list);
2. 小知识
- 实体中的属性认识:没有生成get()、set()方法不叫属性,叫成员变量。
- jdbc的sql?占位符是从1开始的,而hibernate的占位符是从0开始的