Hiberante 持久化类

持久化类是 Hibernate 的核心内容之一。

持久类的最佳实践经验

Hibernate 持久化类理论上并没有明文要求,只要是 POJO 就可以了,这也是 Hibernate 低侵入式设计的一个体现。但有一些较好的实践方式:

1. 必须要有无参构造器,且属性建议为 public.

提供无参构造器,是为了 Hibernate 能使用 Constructor.newInstance() 构建实例。

类的访问控制属性设置为 public 是为了 Hibernate 在运行时能方便生成代理。如果不提供 public 级别的访问控制,至少也应该不低于 package.

2. 设置标识属性。

标识属性对应数据库主键,标识属性最好指定为单个无具体业务含义的属性。

理论上可以不设置主键,也可以设置联合主键,但实践上都不建议。

这里是本着简单实用的原则。

3. 在可使用 Java 基本数据类型时,如 int, double 一类,使用对应的封装类型,如 Integer, Double 一类。

4. 属性名称要避免两个大写字母连写的情况。

5. 属性的访问属性限定为 private, 但为每个属性都提供 getter, setter.

6. 持久类的属性不为 final.

如果用 final, 将导致 Hibernate 无法生成代理对象。如果该类需要被扩展,也不能使用 final 属性。

理论上,通过设置 lazy="false" 禁用代理后,可以使用 final.

7. 重写 equals() 和 hashCode()

因 Hibernate 只为持久态设置标志值,如果瞬态的对象要放到 Set 中,不重写这两个方法就可能带来问题。更多关于 equals() 和 hashCode() 重写的问题,可以参本站这里

三种状态

Hiberante 中对象状态,是一个非常基础和重要的主题。Hibernate 对象有如下三种状态:

1. transitive, 瞬时态,自由态,暂态

2. persistent, 持久态

3. detached, 游离态

刚刚通过 new 创建出来的对象,状态是 transitive, 一旦和 session 关联起来,在数据库中有记录后,就变成了 persistent 状态,当 session 关闭,状态就变成了游离态(detached)了,具体参如下状态图:

hibernate objects' status

持久态的对象可以即时保存,Hibernate 会自动检测到对象变化,并保存到数据库中,不需要显式执行 update() 方法。

一个持久态对象因为 session 关闭后,进入托管态,再和 session 关联后,又进入了持久态,但对象在托管态期间的改动是有效的,在重新进入持久态后,亦会自动保存到数据库中。

persist() 和 save()

都是 Session 中将瞬态对象转为持久态对象的方法。但:

persist() 无返回值, save() 返回主键。

因为上面的原因,save() 会立刻产生 sql 语句,并将值写入数据库,以获取标志属性的值。但 persist() 不会立刻这样处理,这段需要长会话流程,还是有一定必要性的。

save() 不开启事务也能保存,但不开启事务,就不能回滚了,persist() 只有开启事务时才能保存。

load() 和 get()

load() 支持延迟加载,当数据库中不存在该对象时,它会返回一个未经初始化的代理对象。无论数据库中是否有值,都不会返回空,它会 new 代理对象。

get() 不支持延迟加载,它直接访问数据库,如果要加载的记录不存在,则返回 null.

这两个方法对缓存对象的读取也是不一样的。TODO

merge() 和 save()

merge() 不会将要保存的对象和 session 关联,使其转为持久态,它可用于保存托管态的对象。