如何为hibernate实体获取方言特定的sql?

时间:2014-01-24 07:42:08

标签: java sql hibernate

我们可以在保存或更新时看到hibenate generated sql。 现在我的要求是,我有一个已经持久化的对象(实体)。 现在我想要根据dialect而不需要手动生成对象的插入脚本。

有可能吗?

1 个答案:

答案 0 :(得分:2)

这有点棘手,但可能。

在休眠中,EntityPersister负责生成sql。但是它从sql中抽象出来,所以没有API方法来获取sql。

然而,实现AbstractEntityPersister的{​​{1}}生成了sql。但这也是一个问题:sql生成方法是EntityPersister

但我们仍然可以访问它们。通过反射或者我们只是在同一个包中创建一个类。

所以我在与protected相同的包中创建了一个名为EntityPersisterAccess的类,但当然是在我的项目中。 (基于hibernate 3.6.7.Final的示例)

AbstractEntityPersister

您可以在代码中执行类似的操作

package org.hibernate.persister.entity;

import org.hibernate.SessionFactory;
import org.hibernate.engine.SessionFactoryImplementor;

public class EntityPersisterAccess {

    private SessionFactoryImplementor sessionFactoryImplementor;

    public EntityPersisterAccess(SessionFactory sessionFactory) {
        if (!(sessionFactory instanceof SessionFactoryImplementor)) {
            throw new IllegalArgumentException(
                     "EntityPersisterAccess only works with a "
                     + SessionFactoryImplementor.class);
        }
        this.sessionFactoryImplementor = (SessionFactoryImplementor) sessionFactory;
    }

    public String getInsertSql(Class<?> entityClass) {
        return getInsertSql(entityClass.getCanonicalName())
    }

    public String getInsertSql(String entityName) {
        String insertSql = null;
        EntityPersister ep = sessionFactoryImplementor.getEntityPersister(entityName);
        if(entityPersister instanceof AbstractEntityPersister ){
            AbstractEntityPersister aep = (AbstractEntityPersister) entityPersister;
            boolean[] includeProperty = aep.getPropertyInsertability();
            insertSql = aep.generateInsertString(true, includeProperty);
        }
        return insertSql ;
    }
}

在我的测试中,输出是

SessionFactory sessionFactory = ....;
EntityPersisterAccess epa = new EntityPersisterAccess(sessionFactory);
String insertSql = epa.getInsertSql(Person.class); // some entity class
System.out.println(insertSql);

此方法的好处insert into PERSON (FIRSTNAME, LASTNAME, BIRTHDAY, ADDRESS_ID_FK, ID) values (?, ?, ?, ?, null) 完全封装了使用它的客户端代码中的hibernate内部。因此,您只需要在迁移到新的hibernate版本时更改此类 - 希望如此:)

PS:EntityPersisterAccess中可能需要考虑和实施更多内容,但这个示例应该是一个很好的起点。