`
micc010
  • 浏览: 71649 次
  • 性别: Icon_minigender_1
  • 来自: 广西
社区版块
存档分类
最新评论

hibernate any

    博客分类:
  • java
阅读更多
Hibernate中any元素的应用体会


关联(Associations)是Hibernate核心概念之一,比较常用的有:

many-to-one, one-to-one, one-to-many, many-to-many

Hibernate还提供了另外一种关联——异类关联(Heterogeneous Associations)

在Hibernate Reference (cn) 2.1.6中是这样说明的:

引用
6.10. 异类关联(Heterogeneous Associations)
<many-to-any>和<index-many-to-any>元素提供真正的异类关联。这些元素和<any>元素工作方式是同样的,他们都应该很少用到。


下面针对<any>元素,谈一些自己的体会。

一、什么时候需要<any>元素

持久类中“一个属性”关联“另外一个指定的持久类”(几乎每个应用都有这种情况),多半会使用many-to-one, one-to-one这样的关联。映射到关系数据库中,也多半使用外键约束。

可能会遇到有这么一种特殊的情况,需要:持久类中“一个属性”关联“另外一些持久类”。

举个例子:Log类中使用logEntity属性关联一组业务持久类。(也就是说,在Log中记录不同业务类的实例对象)

如果使用many-to-one,则有很大的限制。首先,需要这些业务类都要继承一个超类,而且在数据库中必须有这个超类对应的表。在Hibernate提供的三种继承映射策略中,只能使用前两种:
1、“每棵类继承树使用一个表(table per class hierarchy) ”
2、“每个子类一个表(table per subclass)”

第1种通常不大合适:所有的业务类映射为一张表,冗余过多,限制也多,增加一个业务类就需要修改表结构,不易扩展。

第2种的情况是:表的数量=业务表数量 + 一个超类表,子类表通过主键和超类表关联(所以实际上关系模型是一对一关联)。业务表数量比较多的时候,这种结构的性能和灵活性都有问题。

这时<any>元素就派上用场啦。


二、<any>元素的应用

1、类:

业务类:
public class BizOne {   
    private Long    id;   
    private String  bizOneDescription;   
    //Getters and Setters 省略   
}   
public class BizTwo {   
    private Long    id;   
    private String  bizTwoDescription;   
    private Date    createDate;   
    //Getters and Setters 省略   
}  


日志类:
public class MyLog {   
    private Long    id;   
    private Date    logDate;   
    private Object  logEntity;  //这就是<any>元素对应的属性。   
    //Getters and Setter 省略   
}  



2、hbm.xml 和 表结构:
这里只给出MyLog的hbm.xml(BizOne, BizTwo很简单,不提了):

<hibernate-mapping>   
     <class name="com.test.entity.MyLog" table="MyLog">   
        <id name="id" column="id">   
            <generator class="native"/>   
        </id>   
        <property name="logDate"/>   
        <any name="logEntity" meta-type="string" id-type="long">   
            <meta-value value="One" class="com.test.entity.BizOne"/>   
            <meta-value value="Two" class="com.test.entity.BizTwo"/>   
            <column name="entityMetaValue" length="20" />   
            <column name="entityId"/>   
        </any>   
    </class>   
</hibernate-mapping>  


表结构(MySQL): 
create table MyLog (   
   id BIGINT NOT NULL AUTO_INCREMENT,   
   logDate datetime,   
   entityMetaValue VARCHAR(20);,   
   entityId BIGINT,   
   primary key (id);   
);  


对<any>元素中子元素和属性的理解,可以结合生成的表结构,及其表中的数据(见3):
name: 是持久类中属性名称。
meta-type: 是下面meta-value元素中value的类型,如"string","character"等。
id-type: 是引用类的主键类型。
meta-value元素中value: 该值将保存到数据库表中,用来标识其后的class,即引用的持久类。请参考下面的数据。
meta-value元素中class: 引用持久类的类全称。
第一个column: 保存上面value值的字段。
第二个column: 保存引用持久类的主键值的字段,它的类型是id-type对应到数据库中的字段类型。


3、记录日志的方法:
public MyLog recordLog(Object biz);{   
    MyLog log = new MyLog();;   
    log.setLogDate(new Date(););;   
    log.setLogEntity(biz);; //引用了传递过来的业务对象   
  
    return getLogService();.save(log);; //保存log。我习惯用Spring+Hibernate。   
} 



Hibernate所保存的数据是这样:

引用

--  ---------------------------------  ---------------   --------
id  logDate           entityMetaValue entityId
--  ---------------------------------  ---------------   --------
1  2004-11-15 20:48:52.211  One        1
2  2004-11-15 20:57:25.385  Two        2
3  2004-11-15 21:48:52.211  One        15
4  2004-11-15 22:51:15.185  Two        26
5  2004-11-15 23:27:55.123  Two        36


4、读取Log
public MyLog readLog(Long id);{   
    MyLog log = getLogService();.getLog(id);;   
  
    Object biz = log.getLogEntity();;   
    //...   
  
    return log;   
}  


用<any>所实现的关联,与<many-to-one>等关联的效果是相同的。例如,如果BizOne, BizTwo的lazy="true",则biz是个代理。

5、BizThree如果增加了一个业务类BizThree,在MyLog.hbm.xml中只需增加一行:

Java代码
<meta-value value="Three" class="com.test.entity.BizThree"/> 

          <meta-value value="Three" class="com.test.entity.BizThree"/>

6、限制
在<any>元素中需要指定id-type,这可能是<any>对所关联类的唯一限制了:所关联的类的主键类型必须相同。

三、再谈继承映射策略问题
上面提到了:如果为了让Log能够关联业务类,就要求业务类都要继承同一个超类,是不大合适的。不过,不合适的理由在于这个超类需要在数据库有相应的表。不能说,业务类不能继承一个超类。实际上,很多应用中的业务类都有超类,而且根据情况实现一些接口。此时的继承映射策略是Hibernate Reference中的第三种:每个具体类一个表(table per concrete class)。上面MyLog中的logEntity的类型可以是更有意义的超类,如Entity,当然也可以是接口,不必是Object。这样,即使超类在数据库中没有对应的表,照样可以实现关联。

四、彩票
Hibernate Reference中提到<any>元素的地方不是很多,但提到时,总不忘记说“应该很少用到”,“应该在非常特殊的情况下使用它”。可能从全世界的角度看,使用<any>是低概率事件,但是如果遇到了,就是100%的概率了。因此,当你应用<any>的时候,别忘了购买彩票。因为,与中奖同样的低概率事件——使用<any>——你已经碰到了,你的运气就来了,赶快买彩票吧,准能中奖!

五、感谢
感谢这个论坛!
感谢Hibernate相关资料的译作者,尤其是Hibernate Reference!

如果我所写的有不对的地方,请指出来。感谢!
分享到:
评论

相关推荐

    Hibernate不同数据库的连接及SQL方言

    * Oracle (any version):org.hibernate.dialect.OracleDialect * Oracle 9i/10g:org.hibernate.dialect.Oracle9Dialect * Sybase:org.hibernate.dialect.SybaseDialect * Sybase Anywhere:org.hibernate.dialect...

    hibernate-shards.jar

    any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any ...

    Hibernate+中文文档

    5.1.22. any 5.2. Hibernate 的类型 5.2.1. 实体(Entities)和值(values) 5.2.2. 基本值类型 5.2.3. 自定义值类型 5.3. 多次映射同一个类 5.4. SQL中引号包围的标识符 5.5. 其他元数据(Metadata) 5.5.1. 使用...

    hibernate 教程

    映射到"任意"(any)类型 5.3. SQL中引号包围的标识符 5.4. 映射文件的模块化(Modular mapping files) 6. 集合类(Collections)映射 6.1. 持久化集合类(Persistent Collections) 6.2. 映射集合...

    hibernate3.2中文文档(chm格式)

    5.1.22. any 5.2. Hibernate 的类型 5.2.1. 实体(Entities)和值(values) 5.2.2. 基本值类型 5.2.3. 自定义值类型 5.3. 多次映射同一个类 5.4. SQL中引号包围的标识符 5.5. 其他元数据(Metadata) 5.5.1. 使用...

    HibernateAPI中文版.chm

    5.1.22. any 5.2. Hibernate 的类型 5.2.1. 实体(Entities)和值(values) 5.2.2. 基本值类型 5.2.3. 自定义值类型 5.3. 多次映射同一个类 5.4. SQL中引号包围的标识符 5.5. 其他元数据(Metadata) 5.5.1. 使用...

    @hibernate Tag Reference

    @hibernate.any(column="userId", class=User.class) private List&lt;Order&gt; orders; ``` ##### 2.2 @hibernate.array (0..1) **功能描述**:声明一个数组类型的属性。 **参数**: - **type**: 数组元素的类型。 -...

    Beginning Hibernate, 3rd Edition

    Experienced authors Joseph Ottinger with Dave Minter and Jeff Linwood provide more in-depth examples than any other book for Hibernate beginners. The authors also present material in a lively, ...

    Hibernate中文详细学习文档

    5.1.22. any 5.2. Hibernate 的类型 5.2.1. 实体(Entities)和值(values) 5.2.2. 基本值类型 5.2.3. 自定义值类型 5.3. 多次映射同一个类 5.4. SQL中引号包围的标识符 5.5. 其他元数据(Metadata) 5.5.1. 使用...

    Hibernate 中文 html 帮助文档

    5.1.22. any 5.2. Hibernate 的类型 5.2.1. 实体(Entities)和值(values) 5.2.2. 基本值类型 5.2.3. 自定义值类型 5.3. 多次映射同一个类 5.4. SQL中引号包围的标识符 5.5. 其他元数据(Metadata) 5.5.1. 使用 XDoclet...

    最全Hibernate 参考文档

    5.1.21. any 5.2. Hibernate 的类型 5.2.1. 实体(Entities)和值(values) 5.2.2. 基本值类型 5.2.3. 自定义值类型 5.3. SQL中引号包围的标识符 5.4. 其他元数据(Metadata) 5.4.1. 使用 XDoclet 标记 5.4.2. 使用 JDK ...

    hibernate-entitymanager-3.2.1.GA

    THIS RELEASE OF HIBERNATE ENTITYMANAGER REQUIRES HIBERNATE CORE 3.2.0.GA (and above) AND DOES NOT WORK WITH HIBERNATE 3.1.x OR ANY OLDER VERSION OF HIBERNAT

    hibernate详解

    此外,通过“any”映射,可以将一个属性映射到任何Java类型,增加了灵活性。 6. **SQL与DDL**:Hibernate允许开发者自定义SQL语句和DDL(Data Definition Language),用于创建、更新和删除数据库表结构。通过使用...

    hibernate中文官方文档3.6

    - **Any**:特殊映射类型,用于处理非标准数据类型。 - **属性(Properties)**:实体类中属性的具体映射规则。 以上内容覆盖了Hibernate中文官方文档3.6的核心知识点,有助于读者深入理解和掌握Hibernate框架的...

    Hibernate 参考文档

    - **映射到"任意"(any)类型**:一种特殊的数据类型映射方式,用于存储任意类型的对象。 - **SQL中引号包围的标识符**:如何在映射文件中引用数据库中的标识符。 - **映射文件的模块化**:将大型映射文件拆分为更小...

    hibernate 体系结构与配置 参考文档(html)

    any 5.2. Hibernate 的类型 5.2.1. 实体(Entities)和值(values) 5.2.2. 基本值类型 5.2.3. 自定义值类型 5.3. 多次映射同一个类 5.4. SQL中引号包围的标识符 5.5. 其他元数据(Metadata) 5.5.1. 使用 ...

    Hibernate教程

    6.1.21. any 6.2. Hibernate 的类型 6.2.1. 实体(Entities)和值(values) 6.2.2. 基本值类型 6.2.3. 自定义值类型 6.3. SQL中引号包围的标识符 6.4. 其他元数据(Metadata) 6.4.1. 使用 XDoclet 标记 6.4.2. ...

Global site tag (gtag.js) - Google Analytics