天天看點

Hibernate 攔截器的使用--動态表名

前言

最近公司的核心業務的資料要進行分庫分表,我們代碼中ORM采用的是jpa的方式,但是目前面臨的一個問題就是,在原先的實體和表的映射關系是固定的情況下,如何用一種優雅的方式在系統運作的過程中,根據實際的業務需要動态的将實體的表名進行更改。           

内容摘要

jpa有多種實作的方式,但是最常見的還是采用Hibernate的方式實作,是以為了實作上述的業務,就必須得用到Hibernate的相關特性,在這裡,我們使用Hibernate的攔截器Interceptor,通過Interceptor,将即将執行的sql語句中的表名進行替換。           

方式一:在代碼中進行替換

1.建立攔截器

public class AutoTableName extends EmptyInterceptor {
    private String targetName;// 目标表名
    private String tableName;// 操作表名

    public AutoTableName() {}

    public AutoTableName(String targetName,String tableName) {
        this.targetName= targetName;
        this.tableName= tableName;
    }

    @Override
    public String onPrepareStatement(String sql) {
        sql = sql.replaceAll(targetName, tableName);
        return sql;
    }

}           

2.重新建立session

Session session= this.em.unwrap(Session.class);
        AutoTableName autoTableName = new AutoTableName("table","table_1");  //替換表名
        session=session.getSessionFactory().withOptions().interceptor(autoTableName).openSession();//#注意
        Transaction tx = null;
        try{
            Model model=new Model ();
            model.setInfo("test");
            tx = session.beginTransaction();
            session.save(gd);
            tx.commit();
        }catch (Exception rbe) {
            rbe.printStackTrace();

        }finally {
            if (session != null) {
                session.close();
            }
        }           

3.注意

上述代碼注釋#符号的地方會因為Hibernate的版本的不同而有不同的寫法,我這裡用的是Hibernate4.x以上的版本,如果用的是Hibernate3.x的讀者,直接session.getSessionFactory().openSession(new Interceptor())即可。