`
还有也许
  • 浏览: 164349 次
  • 性别: Icon_minigender_1
  • 来自: 郑州
社区版块
存档分类
最新评论

Hibernate 动态映射表的两种策略

阅读更多

通过Hibernate去处理一个配置文件对应多张表的情况,我整理了一下大概有两种方式

一、通过实现命名策略接口NamingStrategy

  以下是一个示例:

1、自定义一个类MyNamingStrategy来实现NamingStrategy。(这样你要实现10个方法,如果其他方法
不需要,我们可以通过继承它的一个适配器类DefaultNamingStrategy来只实现我们需要的方法)好了,我
们就继承DefaultNamingStrategy 吧。
2、实现public String classToTableName(String className)方法来实现自己命名策略。
我这的业务需要是每隔一个月就要换一个表。比如1月用biz_1,那么2月就用biz_2....但是这些表的结构是相同的。我们要做的就是通过获得月份来动态的选择表。我们从这个方法中这样写:
public class MyNamingStrategy extends DefaultNamingStrategy {
public static final MyNamingStrategy INSTANCE = new MyNamingStrategy();
public String classToTableName(String className) {
return "biz_" + Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
}
}

好了,这样就可以根据月份来动态的选择表名了。
3、使用命名策略。
要使用这个命名策略可以这样:
Configuration cfg = new Configuration()
.setNamingStrategy(MyNamingStrategy.INSTANCE)
.configure("hibernate.cfg.xml")
.addFile("biz.hbm.xml");
ok,这样就可以实现我们的动态表名映射啦!

二、通过SQLQuery实现要得到的效果

 

例如我有一个 pojo 是 ReadInfo,用来记录阅读信息的。由于数据量宠大,所以我的思路是按月划分,每个月一张表。所以只是表名不同,而字段是完全相同的。
 
ReadInfo.java 是这样的,其中 userId, year, month, day 是联合主键:
private Integer userId;
    private Integer year;
    private Integer month;
    private Integer day;
    private Integer point;
 

那么相应的 ReadInfo.hbm.xml 的片段是

  

<class name="ReadInfo" table="tblReadInfo" mutable="false">
        <composite-id>
            <key-property name="userId" column="userId" type="integer"/>
            <key-property name="year" column="year" type="integer"/>
            <key-property name="month" column="month" type="integer"/>
            <key-property name="day" column="day" type="integer"/>
        </composite-id>
        <property name="point" column="point" type="integer"/>
    </class>

 

上面的xml,注意 2 个细节

1. pojo 所映射的 table tblReadInfo 实际上是不存在的。实际的表是 tblRead200710 之类的;

2. mutable 要设置为 false,即是说,关闭 hibernate 对这个 pojo 的任何持久化操作,以避免 hibernate 把数据写到 tblReadInfo 中(这个表是不存在的嘛)。因此,所有的持久化操作,都是需要自己通过 SQLQuery 来处理。

现在可以看一下 ado 中的操作了,先看一个 select 操作

public ReadInfo selectReadInfo(Integer userId, Integer year,
            Integer month, Integer day) throws HibernateException
    {
        ReadInfo readInfo = null;

        Session session = getSession();
        Transaction tx = session.beginTransaction();

        try
        {
            String sql = "select * from tblRead"
                + Misc.formatMoon(year, month)
                + " where userId=? and day=?";

            SQLQuery query = session.createSQLQuery(sql);
            query.addEntity(ReadInfo.class);

            query.setLong(0, userId);
            query.setInteger(1, day);

            readInfo = (ReadInfo) query.uniqueResult();

            tx.commit();
        }
        catch (HibernateException e)
        {
            log.error("catch exception:", e);

            if (tx != null)
            {
                tx.rollback();
            }

            throw e;
        }
        return readInfo;
    }

 

上面的代码,关键是以下几点:

1. 通过函数参数的 year, month 来确定要操作的表名,我自己写了一个 Misc.formatMoon(year, month) 来生成 "yyyyMM" 格式的字串;

2. 使用了 SQLQuery ,再通过 query.addEntity(ReadInfo.class); 建立与 ReadInfo 的映射关系;

3. query.setXxx() 与 PreparedStatement 的类似,不过索引是从 0 开始;

4. 其它的就跟一般的 Query 操作类似的了。

再看一个 insert 操作

 

public void insertReadInfo(ReadInfo readInfo) throws HibernateException
    {
        Session session = getSession();
        Transaction tx = session.beginTransaction();

        try
        {
            String sql = "insert into tblRead"
                + Misc.formatMoon(readInfo.getYear(), readInfo.getMonth())
                + " (userId, year, month, day, point) values (?, ?, ?, ?, ?)";

            SQLQuery query = session.createSQLQuery(sql);

            query.setLong(0, readInfo.getUserId());
            query.setInteger(1, readInfo.getYear());
            query.setInteger(2, readInfo.getMonth());
            query.setInteger(3, readInfo.getDay());
            query.setInteger(4, readInfo.getPoint());

            query.executeUpdate();

            tx.commit();
        }
        catch (HibernateException e)
        {
            log.error("catch exception:", e);

            if (tx != null)
            {
                tx.rollback();
            }

            throw e;
        }
    }

 

同理,update, delete 等操作也是这样实现的。

hmm.. 这种处理方式的麻烦的地方是需要手工写 sql ,因此要尽量写通用的标准 sql,不然在数据库兼容方面会有问题。当然,有时是会出现无法兼容的情况,那么可以考虑把 sql 写到配置文件中,根据不同的数据库,装载相应的配置文件。

 

参考文档:

http://www.cublog.cn/u1/50766/showart_400410.html

http://lorry1113.iteye.com/blog/430843

 

分享到:
评论
1 楼 lku1314 2012-09-03  
好文  标记下! 但是还是有点犹豫 要不要这么做

相关推荐

    Hibernate+中文文档

    9.1. 三种策略 9.1.1. 每个类分层结构一张表(Table per class hierarchy) 9.1.2. 每个子类一张表(Table per subclass) 9.1.3. 每个子类一张表(Table per subclass),使用辨别标志(Discriminator) 9.1.4. 混合...

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

    9.1. 三种策略 9.1.1. 每个类分层结构一张表(Table per class hierarchy) 9.1.2. 每个子类一张表(Table per subclass) 9.1.3. 每个子类一张表(Table per subclass),使用辨别标志(Discriminator) 9.1.4. 混合...

    HibernateAPI中文版.chm

    9.1. 三种策略 9.1.1. 每个类分层结构一张表(Table per class hierarchy) 9.1.2. 每个子类一张表(Table per subclass) 9.1.3. 每个子类一张表(Table per subclass),使用辨别标志(Discriminator) 9.1.4. 混合...

    Hibernate中文详细学习文档

    9.1. 三种策略 9.1.1. 每个类分层结构一张表(Table per class hierarchy) 9.1.2. 每个子类一张表(Table per subclass) 9.1.3. 每个子类一张表(Table per subclass),使用辨别标志(Discriminator) 9.1.4. 混合...

    Hibernate 中文 html 帮助文档

    9.1. 三种策略 9.1.1. 每个类分层结构一张表(Table per class hierarchy) 9.1.2. 每个子类一张表(Table per subclass) 9.1.3. 每个子类一张表(Table per subclass),使用辨别标志(Discriminator) 9.1.4. 混合使用...

    最全Hibernate 参考文档

    9.1. 三种策略 9.1.1. 每个类分层结构一张表(Table per class hierarchy) 9.1.2. 每个子类一张表(Table per subclass) 9.1.3. 每个子类一张表(Table per subclass),使用辨别标志(Discriminator) 9.1.4. 混合使用...

    Hibernate注释大全收藏

    这种策略支持双向的一对多关联,但不支持 IDENTIFY 生成器策略,因为ID必须在多个表间共享。一旦使用就不能使用AUTO和IDENTIFY生成器。 每个类层次结构一张表 @Entity @Inheritance(strategy=InheritanceType....

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

    三种策略 9.1.1. 每个类分层结构一张表(Table per class hierarchy) 9.1.2. 每个子类一张表(Table per subclass) 9.1.3. 每个子类一张表(Table per subclass),使用辨别标志(Discriminator) 9.1.4. 混合使用...

    Hibernate教程

    10.1. 三种策略 10.1.1. 每个类分层结构一张表(Table per class hierarchy) 10.1.2. 每个子类一张表(Table per subclass) 10.1.3. 每个子类一张表(Table per subclass),使用辨别标志(Discriminator) 10.1.4. ...

    Hibernate_3.2.0_符合Java习惯的关系数据库持久化

    9.1. 三种策略 9.1.1. 每个类分层结构一张表(Table per class hierarchy) 9.1.2. 每个子类一张表(Table per subclass) 9.1.3. 每个子类一张表(Table per subclass),使用辨别标志(Discriminator) 9.1.4. 混合...

    精通hibernate:对象持久化技术孙卫琴第二版part2

    2.4.3 Hibernate映射类型接口 41 2.4.4 可供扩展的接口 42 2.5 小结 43 2.6 思考题 45 第3章 第一个Hibernate应用 47 本章通过简单的helloapp应用例子,演示如何利用Hibernate来持久化Java对象。 3.1 创建...

    hibernate总结

    Hibernate映射多对多(两个一对多实现多对多) 表:材料表和产品表多对多,在数据库中有中间表即产品材料表用来存放两个表之间的关系 Java类:材料PO,产品PO,中间PO,中间PO的复合主键类(由于是两个一对多形成的多对...

    Hibernate3+中文参考文档

    9.1. 三种策略 9.1.1. 每个类分层结构一张表(Table per class hierarchy) 9.1.2. 每个子类一张表(Table per subclass) 9.1.3. 每个子类一张表(Table per subclass),使用辨别标志(Discriminator) 9.1.4. 混合使用...

    hibernate3.04中文文档.chm

    10.1. 三种策略 10.1.1. 每个类分层结构一张表(Table per class hierarchy) 10.1.2. 每个子类一张表(Table per subclass) 10.1.3. 每个子类一张表(Table per subclass),使用辨别标志(Discriminator) 10.1.4. ...

    hibernate 框架详解

    三种策略 10.1.1. 每个类分层结构一张表(Table per class hierarchy) 10.1.2. 每个子类一张表(Table per subclass) 10.1.3. 每个子类一张表(Table per subclass),使用辨别标志(Discriminator) 10.1.4. 混合...

    Hibernate3的帮助文档

    10.1. 三种策略 10.1.1. 每个类分层结构一张表(Table per class hierarchy) 10.1.2. 每个子类一张表(Table per subclass) 10.1.3. 每个子类一张表(Table per subclass),使用辨别标志(Discriminator) 10.1.4. ...

    Hibernate参考文档

    9.1. 三种策略 9.1.1. 每个类分层结构一张表(Table per class hierarchy) 9.1.2. 每个子类一张表(Table per subclass) 9.1.3. 每个子类一张表(Table per subclass),使用辨别标志(Discriminator) 9.1.4. 混合使用...

    精通Hibernate:对象持久化技术第二版part3

    2.4.3 Hibernate映射类型接口 41 2.4.4 可供扩展的接口 42 2.5 小结 43 2.6 思考题 45 第3章 第一个Hibernate应用 47 本章通过简单的helloapp应用例子,演示如何利用Hibernate来持久化Java对象。 3.1 创建...

    hibernate_reference中文文档.pdf

    3.8.1. 事务策略配置 ................................................... 46HIBERNATE - Relational Persis... iv 3.8.2. JNDI 绑定的 SessionFactory ..................................... 47 3.8.3. 在 JTA ...

    jdbc基础和参考

    Component:数据库中采用一张表的设计,java中采用两个类的设计 ----------------------------------- Employee: id name salary award amount table id name salary award formula: --------------------------...

Global site tag (gtag.js) - Google Analytics