由于以下异常,我目前遇到延迟加载无法处理双向实体关系的问题:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: sample.Person.sent, no session or session was closed
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:394)
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:386)
at org.hibernate.collection.internal.AbstractPersistentCollection.readElementExistence(AbstractPersistentCollection.java:161)
at org.hibernate.collection.internal.PersistentBag.contains(PersistentBag.java:256)
at sample.EmailTest.testTest(EmailTest.java:47)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80)
at org.testng.internal.MethodInvocationHelper$1.runTestMethod(MethodInvocationHelper.java:169)
at org.springframework.test.context.testng.AbstractTestNGSpringContextTests.run(AbstractTestNGSpringContextTests.java:158)
我有以下示例实体类:
电子邮件
@Entity
public class Email {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String subject;
@ManyToOne(fetch = FetchType.EAGER)
private Person sender;
@ManyToMany(fetch = FetchType.EAGER)
private List<Person> recipients;
... setters/getters/constructors/equals/hashcode
人
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(unique = true)
private String name;
@OneToMany(mappedBy = "sender")
private List<Email> sent;
@ManyToMany(mappedBy = "recipients")
private List<Email> received;
... setters/getters/constructors/equals/hashcode
以下存储库:
电子邮件存储库
import org.springframework.data.repository.CrudRepository;
public interface EmailRepository extends CrudRepository<Email, Long> {
}
个人资料库
import org.springframework.data.repository.CrudRepository;
public interface PersonRepository extends CrudRepository<Person, Long> {
}
持久性.xml:
<persistence-unit name="unit_test">
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
<property name="hibernate.connection.url" value="jdbc:hsqldb:mem:spring" />
<property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver" />
<property name="hibernate.connection.username" value="sa" />
<property name="hibernate.connection.password" value="" />
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.use_sql_comments" value="true" />
<property name="hibernate.cache.use_second_level_cache" value="false"/>
<property name="hibernate.cache.use_query_cache" value="false"/>
</properties>
</persistence-unit>
Spring application_context.xml
<jpa:repositories base-package="sample" />
<jdbc:embedded-database id="dataSource" type="HSQL" />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="true" />
<property name="database" value="HSQL" />
</bean>
</property>
<property name="persistenceUnitName" value="unit_test" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
这是产生异常的测试代码:
@ContextConfiguration(locations={"/application_context.xml"})
public class EmailTest extends AbstractTestNGSpringContextTests{
@Autowired
private EmailRepository emailRespository;
@Autowired
private PersonRepository personRepository;
private Long fredId;
@BeforeMethod
public void setUp() {
Person john = new Person("John");
john = personRepository.save(john);
Person fred = new Person("Fred");
fred = personRepository.save(fred);
Person julio = new Person("Julio");
julio = personRepository.save(julio);
Email mail = new Email("subject", john, Lists.newArrayList(john, fred, julio));
emailRespository.save(mail);
fredId = fred.getId();
}
@Test
@Transactional
public void testTest() throws Exception{
Person fred = personRepository.findOne(fredId);
List<Email> sent = fred.getSent();
List<Email> received = fred.getReceived();
sent.contains(null);
received.contains(null);
int i = 0;
}
}
保存和查找似乎工作正常,但延迟加载的集合不起作用,似乎是因为会话已关闭,即使方法是@Transactional。显然我错过了一些东西,因为我看到了其他几乎相同的样本。
编辑:将 fetch = FetchType.EAGER 添加到电子邮件实体,没有变化。