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. 主键生成策略

  • 主键生成策略:就是每条记录录入时,主键生成规则。有七种生成策略,前六个属于代理主键,最后一个适合自然主键
  1. sequence: Oracle中的主键生成策略.
  2. sequence: Oracle中的主键生成策略.
  3. increment(了解): 主键自增.由hibernate来维护.每次插入前会先查询表中id最大值.+1作为新主键值.
  4. hilo(了解): 高低位算法.主键自增.由hibernate来维护.开发时不使用.
  5. native:hilo+sequence+identity 自动三选一策略.
  6. uuid: 产生随机字符串作为主键. 主键类型必须为string 类型.
  7. assigned:自然主键生成策略. hibernate不会管理主键值.由开发人员自己录入.

1.4. hibernate的状态

  • 分为三种状态:瞬时状态,持久化状态,游离托管状态

Hibernate学习笔记二:hibernate实体详解,主键生成策略、hibernate三种状态、一级缓存、事务操作等

  1. 瞬时状态:没有oid,没有在session缓存中
  2. 持久化状态:有id,在session缓存中,特点:持久化状态对象的任何变化都会自动同步到数据库中。
  3. 游离|托管状态:有id,没有在session缓存中

Hibernate学习笔记二:hibernate实体详解,主键生成策略、hibernate三种状态、一级缓存、事务操作等

  • session的save()方法其实不能理解成保存,理解成瞬时状态转换成持久化状态的方法。
  • 主键自增:在执行save方法时,为了将对象转化为持久化状态,必须生成id值,所以需要执行insert语句生成。
  • increment:主键生成机制在执行save方法时,为了生成id,会先执行查询id最大值的sql语句。

1.5. hibernate进阶:一级缓存

  • 缓存:提高效率.hibernate中的一级缓存也是为了提高操作数据库的效率.
  • 提高效率手段1:提高查询效率

Hibernate学习笔记二:hibernate实体详解,主键生成策略、hibernate三种状态、一级缓存、事务操作等

  • 提高效率手段2:减少不必要的修改语句发送

Hibernate学习笔记二:hibernate实体详解,主键生成策略、hibernate三种状态、一级缓存、事务操作等

1.6. hibernate事务操作

  1. 事务特性:

atomicity原子性

consistency一致性

isolation隔离性

durability持久性

  1. 事务并发问题

脏读:能读取了对方修改还未提交的数据,可能对方采取了回滚操作,应该读提交后的数据

不可重复读:在一次事务读取中,读取的内容应该相同,如果不同就是不可重复读。针对update操作

幻|虚读:在一次事务中读取的总量不一样,针对insert操作

事务并发问题可参考文章:事务并发问题

  1. 事务的隔离级别

读未提交:会产生脏读,不可重复读,虚读问题

读已提交:会产生不可重复读,虚读问题

可重复的:会产生虚读问题(mysql默认级别)

串行化:没有问题

  1. 在hibernate中指定隔离级别,在hibernate.cfg.xml中添加如下代码
<property name="hibernate.connection.isolation">4</property>
  1. 在项目如何管理事务
  • 业务开始之前打开事务,业务执行之后提交事务. 执行过程中出现异常.回滚事务.
  • 在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查询

  1. hql查询时独家查询,属于面向对象的查询语言,即hql语句都是面向实体类里的属性的不是面向数据库的。
  2. hibernate的占位符有:?号占位符,命名占位符: :name命名占位符的好处是赋值时不需要写数字了。
  3. hibernate的分页查询:setFirstResult(),setMaxResult();

1.8. Hibernate的criteria查询

  1. criteria是无语句查询
  2. 查询所有内容
//只写一个对象的加载类
Criteria criteria=session.createCriteria(Customer.class);
List<Customer> list=criteria.list();
  1. 条件查询
  • 创建Criteria查询对象
  • 添加查询参数
  • 执行查询获得结果
Criteria criteria=session.createCriteria(Customer.class);
//添加查询参数
criteria.add(Restrictions.eq("fieldName",参数))//执行查询获得结果
Customer c=(Customer)criteria.uniqueResult();
  • Criteria有对应各种字符例如> = !=等运算符的字符,太多不再展示。太麻烦,不建议学。适合单表条件查询
  1. 原生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. 小知识

  1. 实体中的属性认识:没有生成get()、set()方法不叫属性,叫成员变量。
  2. jdbc的sql?占位符是从1开始的,而hibernate的占位符是从0开始的