我有一个用@Transactional
注释的服务类调用DAO层方法来返回一个对象,其中包含一个延迟加载的集合。当我尝试使用Hibernate.inititialize(..)
在服务层初始化此集合时,hibernate不会加载集合。 DAO配置为使用实体管理器,对象类使用JPA注释进行注释。我有以下spring应用程序上下文..
<beans xmlns="http://www.springframework.org/schema/beans"...">
<orcl:pooling-datasource id="dataSource" url="..." username="..." password="..."/>
<context:annotation-config/>
<!-- Hibernate entity manager -->
<bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="org.gmp.webapp.model" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="myEmf" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="persistenceExceptionTranslationPostProcessor"
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<bean id="dao" class="org.gmp.webapp.dao.impl.HibDAOImpl" />
</beans>
我的DAO界面和实现......
package org.gmp.webapp.dao;
import java.util.List;
import org.gmp.webapp.model.Crime;
public interface DAO {
public Crime getCrime(String crimeNo);
}
import org.gmp.webapp.dao.DAO;
import org.gmp.webapp.model.Crime;
public class HibDAOImpl implements DAO {
@PersistenceContext
protected EntityManager em;
public Crime getCrime(String crimeNo) {
return this.em.find(Crime.class, crimeNo);
}
}
我的对象看起来像这样..
@Entity
@Table(name="CRIME_TABLE")
public class Crime {
@Id
@Column(name = "CRIME_NO")
private String crimeNo;
@OneToMany
@JoinColumn(name="PER_CRIME_NO", referencedColumnName="CRIME_NO")
private List<PersonCrimeLink> personLinks;
....
public List<PersonCrimeLink> getPersonLinks() {
return personLinks;
}
}
服务类用transactional(spring)注释,所以我认为对DAO的调用和初始化是在同一个事务中,这应该有效。 我的服务..
@Service
@Transactional(readOnly=true)
public class CrimeServiceImpl implements CrimeService {
@Autowired private CrimeDAO crimeDAO;
public Crime getCrime(String crimeNo) {
Crime crime = crimeDAO.getCrime(crimeNo);
Hibernate.initialize(crime.getPersonLinks());
return crime;
}
}
当我对DAO方法进行测试时,在调用集合的getter时会加载该集合。我用@Transactional
注释了测试方法。 personLinks
对象被省略,但就像我说它返回测试中的记录。我认为我不理解我正在使用的事务管理器,因为当我使用会话工厂和HibernateTransactionManager
时此过程有效。
非常感谢您提供任何指导。
答案 0 :(得分:1)
这是一个快速提示,因为您决定使用JPA的EntityManagerFactory而不是Hibernate的SessionFactory作为您的orm API,那么我会在应用程序的其他层上坚持使用该API。
也就是说,使用EntityManager获取数据然后切换到使用实现API(Hibernate.initialize)并不是一致/可维护的方法。
就像你在帖子中所说的那样,如果你坚持使用JPA规范,这是第一次访问时初始化集合,那么你不会收到任何错误并加载列表:
LAZY策略是对持久性提供程序运行时的暗示 首次访问时应该懒洋洋地获取数据
从JPA规范开始,您只需要这样做:
public Crime getCrime(String crimeNo) {
Crime crime = crimeDAO.getCrime(crimeNo);
crime.getPersonLinks().size(); // any access method
return crime;
}