【发布时间】:2013-12-31 01:24:10
【问题描述】:
我们有 Hibernate 拦截器(扩展 EmptyInterceptor),它根据传入的 entityName 在实例化时加载 Spring 类:
@Override
public Object instantiate(String entityName, EntityMode entityMode, Serializable id) {
Object bean = null;
String className = entityName.substring(entityName.lastIndexOf(".") + 1);
StringBuffer entity = new StringBuffer(className.substring(0, 1).toLowerCase());
entity.append(className.substring(1));
String beanName = entity.toString();
// Place any modified bean names here
if ("policyType".equalsIgnoreCase(entity.toString())) {
beanName = "policyTypeEntity";
}
if (this.applicationContext.containsBean(beanName)) {
bean = this.applicationContext.getBean(beanName);
}
return bean;
}
基于此设置,当运行 createCriteria 查询时,
this.policyInfo = (PolicyInfo) session.createCriteria(PolicyInfo.class).createAlias("quote", "q").add(Restrictions.eq("q.id", quoteId)).uniqueResult();
Hibernate 正在生成如下所有 SQL(删节)(这只是急切初始化的子查询之一):
/* load one-to-many com.ipacc.onelink.model.entitybeans.PolicyInfo.persons */ select
persons0_.POLICY_INFO_ID as POLICY_I5_35_1_,
persons0_.ID as ID1_27_1_,
persons0_.ID as ID1_27_0_,
persons0_.WORK_ADDRESS_ID as WORK_ADD2_27_0_,
persons0_.HOME_ADDRESS_ID as HOME_ADD3_27_0_,
persons0_.MAIL_ADDRESS_ID as MAIL_ADD4_27_0_,
persons0_.POLICY_INFO_ID as POLICY_I5_27_0_,
persons0_.HOMEOWNER_VERIFIED as HOMEOWN26_27_0_
from
COMBO21_OWNER.PERSON_INFO persons0_
where
persons0_.POLICY_INFO_ID=?
如果您注意到,ID 列重复了两次,导致实际的类属性设置为 null。
PersonInfo 实体的开头如下所示: 包 com.ipacc.onelink.model.entitybeans;
import javax.persistence.Transient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@SuppressWarnings("serial")
@Component
@Scope("prototype")
public class PersonInfo extends DomainObject implements Comparable<PersonInfo> {
private Address workAddress;
private Address homeAddress;
private Address mailAddress;
private PolicyInfo policyInfo;
private String firstName;
private String lastName;
private String middleName;
private String titlePrefix;
private String priorLastName;
private String ssn;
private Date birthDate;
private String ethnicGroup;
private String language;
and so on...
这继承了如下所示的 DomainObject: 包 com.ipacc.onelink.model;
import java.io.Serializable;
@SuppressWarnings("serial")
public class DomainObject implements Serializable {
protected Integer id;
public void setId(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
}
添加删减的映射文件:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.ipacc.onelink.model.entitybeans.PersonInfo" table="PERSON_INFO" schema="COMBO21_OWNER" dynamic-update="true" select-before-update="true">
<id name="id" type="integer">
<column name="ID" precision="10" scale="0" />
<generator class="sequence">
<param name="sequence">PERSON_INFO_SEQ</param>
</generator>
</id>
<many-to-one name="workAddress" class="com.ipacc.onelink.model.entitybeans.Address" fetch="select"
cascade="all">
<column name="WORK_ADDRESS_ID" precision="10" scale="0" />
</many-to-one>
关于为什么会发生这种情况的任何想法?
谢谢
更新: 我展平了类以向下推 id 列并删除了上面提到的 DomainObject 但仍然没有取得任何进展。所以我们可以排除 Hibernate 继承映射策略的问题(因为我不再使用祖先类)。 我也在 Hibernate 4.2.7.SP1 上试过这个,所以我可以确认这也是以前版本中的一个问题。我不认为这是 Hibernate 问题,而是使用实例化拦截器时 Spring 和 Hibernate 之间的握手问题。
这是我得到的重复 ID: 休眠: /* 加载一对多的 com.ipacc.onelink.model.entitybeans.PolicyInfo.installments */ select installmen0_.POLICY_INFO_ID 为 POLICY_I2_35_1_, installmen0_.ID 为 ID1_18_1_, installmen0_.ID 为 ID1_18_0_, installmen0_.POLICY_INFO_ID 为 POLICY_I2_18_0_, 休眠: /* 加载一对多的 com.ipacc.onelink.model.entitybeans.PolicyInfo.policyQuestionAnswers */ select policyques0_.POLICY_INFO_ID 为 POLICY_I2_35_2_, policyques0_.ID 为 ID1_37_2_, policyques0_.ID 为 ID1_37_1_,
有没有人用Hibernate EmptyInterceptor的instantiate方法实例化Spring bean并且成功了?
【问题讨论】:
-
在初始化 Hibernate Session 和 Spring 上下文创建期间是否有任何线程问题=。此外,请提供您的 Person 实体。
-
在 Hibernate Session 或 Spring Context 创建期间看不到任何线程异常。我已经更新了原始版本以包含实体信息的删减版本。
-
你的实体的所有映射注解在哪里?
-
JB,我已经从 hbm.xml 文件中添加了删减的映射信息。
-
您是否使用不同的休眠会话并行执行查询。在这种情况下,可能是一些休眠缓存问题。在一个线程中,人员实体已经附加到会话,而在另一个线程中则没有。这种情况下不能抛出异常。