【发布时间】:2015-01-31 20:58:09
【问题描述】:
我在 Tomcat 7 中运行的 Web 应用程序中使用带有 JPA 和 Hibernate 4 的 Spring 3.2。该应用程序分为控制器、服务和 DAO 类。服务类在类和方法级别具有带注释的事务配置。 DAO 是普通的 JPA,带有由 @PersistenceContext 注释注入的实体管理器。
@Service("galleryService")
@Transactional(propagation=Propagation.SUPPORTS, readOnly=true)
public class GalleryServiceImpl implements GalleryService {
@Override
public Picture getPicture(Long pictureId) {
return pictureDao.find(pictureId);
}
@Override
public List<PictureComment> getComments(Picture picture) {
List<PictureComment> comments = commentDao.findVisibleByPicture(picture);
Collections.sort(comments, new Comment.ByCreatedOnComparator(Comment.ByCreatedOnComparator.SORT_DESCENDING));
return comments;
}
...
}
@Controller
@RequestMapping("/gallery/displayPicture.html")
public class DisplayPictureController extends AbstractGalleryController {
@RequestMapping(method = RequestMethod.GET)
public String doGet(ModelMap model, @RequestParam(REQUEST_PARAM_PICTURE_ID) Long pictureId) {
Picture picture = galleryService.getPicture(pictureId);
if (picture != null) {
model.addAttribute("picture", picture);
// Add comments
model.addAttribute("comments", galleryService.getComments(picture));
} else {
LOGGER.warn(MessageFormat.format("Picture {0} not found.", pictureId));
return ViewConstants.CONTENT_NOT_FOUND;
}
return ViewConstants.GALLERY_DISPLAY_PICTURE;
}
...
}
我打开了 org.springframework.transaction 的调试日志记录,并注意到“创建新事务”、“打开新 EntityManager”、“正在获取...”、“正在关闭...”和“提交事务”已完成对于我的服务类中的方法的每次调用。即使这些方法由我的控制器类中的一个方法调用。这是我的日志输出示例:
2014-12-03 10:53:00,448 org.springframework.transaction.support.AbstractPlatformTransactionManager getTransaction
DEBUG: Creating new transaction with name [de.domain.webapp.gallery.service.GalleryServiceImpl.getPicture]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly
2014-12-03 10:53:00,448 org.springframework.orm.jpa.JpaTransactionManager doBegin
DEBUG: Opened new EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@6133a72f] for JPA transaction
2014-12-03 10:53:00,468 org.springframework.orm.jpa.JpaTransactionManager doBegin
DEBUG: Exposing JPA transaction as JDBC transaction [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@5182c1b7]
2014-12-03 10:53:00,468 org.springframework.transaction.interceptor.TransactionAspectSupport prepareTransactionInfo
TRACE: Getting transaction for [de.domain.webapp.gallery.service.GalleryServiceImpl.getPicture]
2014-12-03 10:53:00,489 org.springframework.transaction.interceptor.TransactionAspectSupport commitTransactionAfterReturning
TRACE: Completing transaction for [de.domain.webapp.gallery.service.GalleryServiceImpl.getPicture]
2014-12-03 10:53:00,489 org.springframework.transaction.support.AbstractPlatformTransactionManager processCommit
DEBUG: Initiating transaction commit
2014-12-03 10:53:00,489 org.springframework.orm.jpa.JpaTransactionManager doCommit
DEBUG: Committing JPA transaction on EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@6133a72f]
2014-12-03 10:53:00,489 org.springframework.orm.jpa.JpaTransactionManager doCleanupAfterCompletion
DEBUG: Closing JPA EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@6133a72f] after transaction
2014-12-03 10:53:00,489 org.springframework.orm.jpa.EntityManagerFactoryUtils closeEntityManager
DEBUG: Closing JPA EntityManager
我知道我可以使用 OpenSessionInView 来保持休眠会话以获得完整的请求,但有人说,OSIV 是一种反模式。相反,我使用的是 SpringOpenEntityManagerInViewFilter。但没有成功。我怎样才能实现,Spring 使用单个事务来调用我的控制器的多个服务层方法?还是我误会了什么?
这是我的 Spring 配置的一部分:
<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="database" value="MYSQL" />
<property name="showSql" value="false" />
</bean>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/tikron" />
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="jpaTemplate" class="org.springframework.orm.jpa.JpaTemplate">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<context:component-scan base-package="de.domain.webapp">
<context:include-filter type="regex" expression=".*Service"/>
</context:component-scan>
我的持久化单元:
<persistence-unit name="tikron-data" transaction-type="RESOURCE_LOCAL">
<!-- Entities located in external project tikron-data -->
<jar-file>/WEB-INF/lib/tikron-data-2.0.1-SNAPSHOT.jar</jar-file>
<!-- Enable JPA 2 second level cache -->
<shared-cache-mode>ALL</shared-cache-mode>
<properties>
<property name="hibernate.hbm2ddl.auto" value="validate" />
<property name="hibernate.cache.use_second_level_cache" value="true" />
<property name="hibernate.cache.use_query_cache" value="true" />
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory"/>
<property name="hibernate.generate_statistics" value="false" />
</properties>
</persistence-unit>
应用程序启动的更多日志输出:
2014-12-03 10:46:48,428 org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean createNativeEntityManagerFactory
INFO: Building JPA container EntityManagerFactory for persistence unit 'tikron-data'
2014-12-03 10:46:48,428 org.hibernate.ejb.HibernatePersistence logDeprecation
WARN: HHH015016: Encountered a deprecated javax.persistence.spi.PersistenceProvider [org.hibernate.ejb.HibernatePersistence]; use [org.hibernate.jpa.HibernatePersistenceProvider] instead.
2014-12-03 10:46:48,448 org.hibernate.jpa.internal.util.LogHelper logPersistenceUnitInformation
INFO: HHH000204: Processing PersistenceUnitInfo [
name: tikron-data
...]
...
2014-12-03 10:46:51,101 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@6cccf90d: defining beans [propertyConfigurer,messageSource,entityManagerFactory,dataSource]; root of factory hierarchy
2014-12-03 10:46:51,111 org.springframework.web.context.ContextLoader initWebApplicationContext
INFO: Root WebApplicationContext: initialization completed in 3374 ms
提前致谢。
【问题讨论】:
标签: spring jpa transactions