我对 Hibernate3 和 Spring3 都很陌生,我遇到了一个与初始化休眠对象的惰性引用有关的问题。
我有一个完全包含的道和服务。域对象是使用 hbm2java 和逆向工程文件创建的。我遵循了一些在我的服务对象上使用注释 (@Transactional) 时发现的最佳实践。(本指南对我非常有帮助http://carinae.net/2009/11/layered-architecture-with-hibernate-and-spring-3/)
我遇到的问题是我的 service.jar 中有以下 spring 配置,用于注释处理和事务管理:
<context:annotation-config />
<context:component-scan base-package="com.barlingbay.dodmerb.persistence" />
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
</bean>
<tx:annotation-driven/>
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
我的 hibernate.cfg.xml 只是我的数据源详细信息和域对象的注释映射的列表。
我正在使用服务层和 dao 层。
@Service
public class ApplicantEventServiceImpl implements ApplicantEventService {
@Autowired(required = true)
private ApplicantEventDao appEventDao;
@Transactional
public List<ApplicantEvent> getEvents() {
return this.appEventDao.getPendingEvents();
}
和一个道层
@Repository
public class ApplicantEventDaoImpl implements ApplicantEventDao {
@Autowired(required = true)
private SessionFactory sessionFactory;
public List<ApplicantEvent> getPendingEvents() {
sessionFactory.getCurrentSession().beginTransaction(); // (If I don't have this, my junit test fails because of no active transaction, but that's a different issue)
return sessionFactory.getCurrentSession()
.createQuery("from ApplicantEvent").list();
}
此代码集合被打包为 maven 模块,并作为依赖项包含在另一个 spring 项目中,该项目是我正在开发的调度和工作流模块。相关 applicationContext.xml 信息
<bean id="workflowStepper" class="com.barlingbay.merb.scheduler.WorkflowStepper" />
<bean id="jobDetailWorkflowStepper"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"
p:targetObject-ref="workflowStepper" p:targetMethod="execute" />
<bean id="triggerJobDetailTicketRegistryCleaner" class="org.springframework.scheduling.quartz.SimpleTriggerBean"
p:jobDetail-ref="jobDetailWorkflowStepper" p:startDelay="2000"
p:repeatInterval="5000" />
<bean id="scheduler"
class="com.barlingbay.merb.scheduler.AutowiringSchedulerFactoryBean" />
还有一个基本的 Workflow.java:
public class WorkflowStepper implements IWorkflowStepper,
ApplicationContextAware {
private final Logger LOG = Logger.getLogger(this.getClass());
private ApplicationContext applicationContext;
// @Transactional
public void execute() {
ApplicantEventService appEvent = (ApplicantEventService) applicationContext
.getBean("applicantEventServiceImpl");
List<ApplicantEvent> events = appEvent.getEvents();
for (ApplicantEvent event : events) {
try {
LOG.info(event.getApplicant().getUsername() + "[" + event.getName()
+ "]");
....
在 LOG.info 语句期间,我得到(并且我理解为什么会得到)一个 LazyInitializationException。事务由包含的服务 maven 依赖项中的 spring-hibernate 上下文管理,在此上下文中不可用。我不明白将事务管理包含到这一层(及更高层)以防止 LazyInitializationException 的正确方法。我试着简单地添加
<bean id="txInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor" />
到业务层的应用程序上下文,它抱怨它看不到服务依赖项中定义的事务管理器。但是,如果我确实将 @Transactional 添加到 Workflow 步进器的 .execute() 中,它会“继承”依赖项的配置。
我错过了什么?