我们可以在保存或更新时看到hibenate generated sql
。
现在我的要求是,我有一个已经持久化的对象(实体)。
现在我想要根据dialect
而不需要手动生成对象的插入脚本。
有可能吗?
答案 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
中可能需要考虑和实施更多内容,但这个示例应该是一个很好的起点。