Hibernate不要求持久化类实现Serializable(可序列化)。然而,当对象被存储在一个HttpSession中,或者用RMI按值传递时,就需要序列化。(这可能发生在Hibernate应用程序中。)类可以是抽象的,必要时,可以扩展非持久化的类。
Hibernate脏检查
Hibernate自动侦测对象状态的改变,以便使更新过的状态与数据库同步。从获取方法返回一个不同的对象,通常比由Hibernate传递到设置方法的对象来得安全。Hibernate按值比较对象——不是按对象同一性——来确定一个属性的持久化状态是否需要被更新。
这有个重要的例外:集合是按同一性比较的!对于一个被映射为持久化集合的属性,你应该从获取方法中返回与Hibernate传递到设置方法中完全相同的集合实例。如果没有,Hiberntae将更新数据库,即使不需要更新,保存在内存中的状态每次也都会与数据库同步。
全局的注解元数据
注解天生就被织入一个特定类的Java源代码中。虽然可能把全局的注解放在类的源文件中(在顶部),我们还是喜欢把全局的元数据放在一个单独的文件中。这称作包元数据(package metadata),它被特定包目录中具名package-info.java的文件所启用。
Hibernate其他实体表示法
Hibernate中有3种内建的实体模式:
POJO——基于POJO、持久化类的一种领域模型实现。这是目前为止你所见到的,是默认的实体模式。
MAP——不需要Java类:用HashMap在Java应用程序中表示实体。这个模式允许完全动态应用程序的快速原型。
DOM4J——不需要Java类:实体被表示为XML元素,基于dom4j API。这种模式对于导出或者导入数据,或者通过XSLT处理来渲染和转换数据时特别有用。
可以在动态模式中映射一个Set(集)吗?基于set集合不适用于动态的实体模式。Set在它的元素中检查重复元素,因此当你调用add(item1)和add(item2)时,这些对象中的equals方法也被调用,然而,item1和item2是Java Map实例,一个映射的equals()实现基于映射的键组。因此,由于item1和item2是带有相同键的映射,因此当他们被添加给一个Set时,并没有明显的区别。只有当你在动态的实体模式中需要集合时才使用bag或者list。
有时需要把POJO模型与动态Map混合。为什么要把领域没模型的静态实现与动态映射表示法混合起来,有两个原因:
一、你要默认使用基于POJO类的静态模型,但有时候要把数据轻松地表示为映射的映射。这在生成报表时,或者必须实现一个可以动态地表示不同实体的普通用户界面时,特别有用。
二、要把模型的单个POJO类映射到几张表,然后通过指定一个逻辑的实体名称在运行时选择表。
表示XML中的数据
Hibernate没有内建的功能 来存储XML格式的数据:它依赖于关系表示和SQL,这种策略的好处应该很清楚。另一方面,Hibernate能够以XML格式把数据加载和呈现给应用程序的开发人员。它允许你使用一组复杂的工具,而无需任何额外的转换步骤。
假设你在默认的POJO模式下工作,并且很快想要获得一些以XML表示的数据。用EntityMode.DOM4J打开一个临时的Session:
Session dom4jSession = session.getSession(EntityMode.DOM4J);
Element userXML = (Element) dom4jSession.load(User.class, storedUserId);
此处返回的是一个dom4j Element,可以用这个dom4j API来读取和操作它。例如,可以用下列片段把它很漂亮地打印到控制台:
try {
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWriter writer = new XMLWriter(System.out, format);
writer.write(userXML);
} catch (IOException ex) {
throw new RuntimeException(ex)
}