打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Hibernate 4 持久化类
4.1 简单的POJO例子
我们将会在下面的章节中详细的描述持久化类的四个重要规则

4.1.1实现一个无参构造方法
Cat 类有一个无参的构造方法。所以的持久化类必须有一个默认的构造器(可以不是public的)因此,Hibernate可以通过反射(java.lang.reflect.Constructor.newInstance())来实例化他们。 推荐定义这个构造器的可见性至少为package  以便让运行时代理能够正常的工作。

4.1.2 提供一个唯一标示属性
注意:这个是推荐的,但是到现在都没有强制要求。这一条将会弃用,因为在将来的版本中将会强制要求提供一个唯一标示属性。

Cat 有一个id属性。 这个属性对应底层数据库重的主键列。 唯一标示的数据类型可以是任意的“基本”数据类型。 更多的复合主键参照9.4 联合标示主键。

注意:不需要在数据表中单独为主键创建一个列, 他们只要是可以唯一的标示这行数据在基本表中的唯一性即可。

我们推荐在持久化类中使用命名一致的标示属性, 可以把它定义为一个可以为Null的类型(例如, 非原始数据类型)

4.1.3推荐使用非final的类(可选)
Hibernate的一个重要的特性 ,代理(懒加载),依赖于非final的或者是一些实现了最只定义了public方法的接口的持久化类。你可以使用hibernate持久化一个没有继承任何借口的类,但是这就导致你不能使用延迟关联抓取的代理,这最终会限制了你在性能调优方面的选择。如果要持久化一个只实现了一个接口部分方法的类, 你必须禁用代理生成。参考示例4.2, 4.3

Example 4.2 通过hbm.xml 禁用代理应该避免声明public final 方法, 否则将会限制你使用该类来产生代理。如果你想要使用一个带有public final方法的类, 你必须明确的禁止使用代理。 参考示例4.2 和4.3。

4.1.4 为持久化字段声明函数(可选)
Cat 类为他的每一个持久化字段都声明了存取方法。 许多其他的ORM工具直接持久化实例变量。 比较好的做法是在关系模式和类的内部数据结构之间提供一个桥梁。默认情况下, Hibernate 持久化JavaBean 识别格式为getFoo, isFoo和setFoo 的方法和属性。 如果有需要, 一些特别的属性你可以直接访问字段。
属性字段不需要一定是public的。Hibernate可以一样持久化可见性为package,protected, 或者private的字段。

4.2 实现继承
一个子类也必须遵守第一和第二规则。它从父类继承唯一标示属性。 如Cat.你必须复写equals() 和hashCode() 方法如果你想:
意图把持久化类的实例存放在Set中(描述多值关联的推荐的方式); 并且
意图使用游离的实例。

Hibernate只在特定的session范围保证持久化身份和Java身份的一致性。当你在不同的session中混合检索实例,如果你希望保证Sets是有意义的,那么你必须实现equals()和hashCode()方法。

最简单的方法是实现equals()和hashCode()方法来比较来比较两个对象间的标示符的值。如果值相同,那么这两个对象在一定在数据库中对应相同的数据行, 因为他们是相同的。 如果两个都加入了Set集合,那么set集合中只会包含一个实例。不幸的是,对于自动生成的标示符不可以使用这种方法,因为Hibernate只会为持久化的对象分配标示符, 对于一个新产生的实例不会包含标示符值。如果equals()和hashCode()基于标示符,哈希码将会改变, 打破了Set集合的约束。可以在Hibernate的网站中查看针对该问题的更多的讨论内容, 这不是Hibernate的问题, 而是普通的对象的一致性与相等行的Java语义问题。

推荐使用业务键值的相等性来实现equals()和hashCode()方法。业务键值相等意思是在equals方法中之比较有关业务的属性值。 这个关键值可以在现实世界中唯一标示一个实例(一个自然的候选关键字):

public class Cat {    ...    public boolean equals(Object other) {        if (this == other) return true;        if ( !(other instanceof Cat) ) return false;        final Cat cat = (Cat) other;        if ( !cat.getLitterId().equals( getLitterId() ) ) return false;        if ( !cat.getMother().equals( getMother() ) ) return false;        return true;    }    public int hashCode() {        int result;        result = getMother().hashCode();        result = 29 * result + getLitterId();        return result;    }}
一个业务关键字不一定是固定的候选主键(参考13.1.3章节)。不变的或者独一无二的属性都是很好的业务关键字的候选。

 4.4 动态模型
注意: 下面的特性是实验性的,在将来会有所改变。

在运行时持久化实体不是必须要被表示为一个POJO类或者JavaBean对象。Hibernate也支持动态模型。 使用这种方法,你不需要写持久化类,只需要映射文件。

默认情况下, Hibernate在普通的POJO模式下工作。你可以使用default_entity_mode配置选项,为特定的SessionFactory设置 默认的实体表示模型(参考3.3 “Hibernate 配置属性”, default_entity_mode选项可以不用配置,session可以自己判断 )。

下面的示例演示了使用MapS表示模型。首先, 在映射文件中需要声明entity-name来替换类名, 或者除了类名之外还要声明entity-name:
<hibernate-mapping>    <class entity-name="Customer">        <id name="id"            type="long"            column="ID">            <generator class="sequence"/>        </id>        <property name="name"            column="NAME"            type="string"/>        <property name="address"            column="ADDRESS"            type="string"/>        <many-to-one name="organization"            column="ORGANIZATION_ID"            class="Organization"/>        <bag name="orders"            inverse="true"            lazy="false"            cascade="all">            <key column="CUSTOMER_ID"/>            <one-to-many class="Order"/>        </bag>    </class>    </hibernate-mapping>
虽然是用目标类名来声明冠梁的,但是关联的目标类型除了是POJO之外,也可以是一个动态的实体。

在你给SessionFactory设置默认的实体模型为dynamic-map之后, 在运行时你可以使用Maps:
Session s = openSession();Transaction tx = s.beginTransaction();// Create a customerMap david = new HashMap();david.put("name", "David");// Create an organizationMap foobar = new HashMap();foobar.put("name", "Foobar Inc.");// Link bothdavid.put("organization", foobar);// Save boths.save("Customer", david);s.save("Organization", foobar);tx.commit();s.close();
动态映射的好处是,变化所需要的时间少了, 因为圆形不需要实现实体类, 然而, 你无法进行编译期的类型检查, 并可能由此会处理很多的运行期异常。 幸亏有了Hibernate映射, 他使得数据库的schema可以容易的规格化和合理化, 并允许稍后再此之上添加合适的领域模型实现。
 
实体表示模式也能在每个Session的基础上设置:
Session dynamicSession = pojoSession.getSession(EntityMode.MAP);//getSession(EntityMode mode)方法没找到。// Create a customerMap david = new HashMap();david.put("name", "David");dynamicSession.save("Customer", david);...dynamicSession.flush();dynamicSession.close()...// Continue on pojoSession
注意:使用的EntityModel调用getSession()是在Session的API中,而不是SessionFactory。 这样新的额Session共享底层的JDBC链接, 事务,和其他的上下文信息。这意味着你不需要再第二个Session中调用flush()和close(),同样的, 把事务和链接的处理交给原来的工作单元。

4.5 元组片段映射













本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
hibernate中一对多关系的映射
hibernate 关联主键映射 composite-id - hacker0825的日志...
Hibernate的SQLQuery
c#中的多态
Hibernate入门之实作equals和hashCode
myeclipse使用hibernate正向工程和逆向工程
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服