简体   繁体   English

Spring需要@Transactional才能使用getter服务吗?

[英]Spring requires @Transactional to be on getter services?

My understanding is @Transactional should only be applied to service methods that need to occur within a transaction (such as setters). 我的理解是@Transactional应该只应用于需要在事务中发生的服务方法(例如setter)。 Say I have the following two classes (DAO layer and Service layer respectively)... 假设我有以下两个类(分别是DAO层和服务层)...

@Service("playerService")
public class PlayerServiceImpl implements PlayerService {
    @Autowired
    private PlayerDao playerDao;

    @Override
    public List<Player> getAll() {
        return playerDao.getAll();
    }


    @Override
    @Transactional
    public void addAllPlayers(final List<Player> players) {
        playerDao.addAllPlayers(players);
    }
}

@Repository("playerDao")
public class PlayerDaoImpl implements PlayerDao {

    @Autowired
    private SessionFactory sessionFactory;

    @SuppressWarnings("unchecked")
    @Override
    public List<Player> getAll() {
        return (List<Player>) sessionFactory.getCurrentSession()
                .createQuery("FROM Player").list();
    }
    @Override
    public void addPlayer(final Player player) {
        sessionFactory.getCurrentSession().save(player);
    }
}

Now if I called addAllPlayers() this works fine, no problems at all. 现在,如果我调用addAllPlayers()这个工作正常,没有任何问题。 But when I use getAll() , sessionFactory.getCurrentSession throws a HibernateException, no session found for current thread. 但是当我使用getAll() ,sessionFactory.getCurrentSession会抛出一个HibernateException,找不到当前线程的会话。

If I add @Transactional to the service layer for getAll(), this will now work "fine". 如果我将@Transactional添加到getAll()的服务层,现在这将“正常”。 The problem with this is I shouldn't have to open a transaction just to call a getter. 这个问题是我不应该只是为了调用getter而打开一个事务。

Can anyone think of any reason why my I need to add @Transactional on a getter method to get the sessionFactory to have a current session? 任何人都可以想到为什么我需要在getter方法上添加@Transactional以使sessionFactory拥有当前会话? My servlet-context.xml and persistance-context.xml are shown below (these are both referenced in my web.xml in contextConfigLocation) 我的servlet-context.xml和persistance-context.xml如下所示(这些都在我的web.xml中的contextConfigLocation中引用)

servlet-context.xml servlet的context.xml中

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

    <!-- DispatcherServlet Context: defines this servlet's request-processing 
        infrastructure -->

    <!-- Enables the Spring MVC @Controller programming model -->
    <tx:annotation-driven transaction-manager="hibernateTransactionManager" />

    <mvc:annotation-driven />
    <!-- Handles HTTP GET requests for /resources/** by efficiently serving 
        up static resources in the ${webappRoot}/resources directory -->
    <mvc:resources location="/resources/css/" mapping="/css/**" />
    <mvc:resources location="/resources/js/" mapping="/js/**" />
    <mvc:resources location="/resources/images/" mapping="/images/**" />
    <mvc:resources location="/resources/img/" mapping="/img/**" />
    <mvc:resources location="/favicon.ico" mapping="/favicon.ico" />
    <!-- Resolves views selected for rendering by @Controllers to .jsp resources 
        in the /WEB-INF/views directory -->
    <beans:bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>



    <context:component-scan base-package="com.footieview.app" />
    <beans:bean
        class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <beans:property name="mediaTypes">
            <beans:map>
                <beans:entry key="html" value="text/html" />
                <beans:entry key="json" value="application/json" />
            </beans:map>
        </beans:property>
        <beans:property name="defaultViews">
            <beans:list>
                <beans:bean
                    class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
                    <beans:property name="prefixJson" value="true" />
                </beans:bean>
            </beans:list>
        </beans:property>
    </beans:bean>
    <beans:bean id="PlayerImportDaoImpl"
        class="com.footieview.app.importer.dao.PlayerImportDaoImpl" />
    <beans:bean id="hibernateTransactionManager"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <beans:property name="sessionFactory" ref="sessionFactory" />
    </beans:bean>

</beans:beans>

persistance-context.xml 持久性-的context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
        <beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <beans:property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <beans:property name="url"
            value="jdbc:mysql://localhost/db" />
        <beans:property name="username" value="username" />
        <beans:property name="password" value="password" />
    </beans:bean>

    <beans:bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <beans:property name="annotatedClasses">
            <beans:list>
                <beans:value>com.footieview.app.entity.Player</beans:value>
            </beans:list>
        </beans:property>
        <beans:property name="dataSource" ref="dataSource" />
        <beans:property name="packagesToScan" value="com.footieview.app.entity.*" />
        <beans:property name="hibernateProperties">
            <beans:props>
                <beans:prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect
                </beans:prop>
                <beans:prop key="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory
                </beans:prop>
                <beans:prop key="hibernate.show_sql">false</beans:prop>
                <beans:prop key="hibernate.hbm2ddl.auto">create</beans:prop>
                <beans:prop key="hibernate.cache.use_second_level_cache">
                    true
                </beans:prop>
                <beans:prop key="hibernate.cache.provider_class">
                    org.hibernate.cache.EhCacheProvider
                </beans:prop>
                <beans:prop key="hibernate.cache.use_query_cache">
                    true
                </beans:prop>
                <beans:prop key="hibernate.cache.region.factory_class">
                    org.hibernate.cache.ehcache.EhCacheRegionFactory
                </beans:prop>
                <beans:prop key="hibernate.cglib.use_reflection_optimizer">
                    true
                </beans:prop>
            </beans:props>
        </beans:property>
    </beans:bean>
</beans:beans>

@Transactional does not only open a DB transaction but in case of Hibernate it also creates a hibernate session if there is none. @Transactional不仅打开数据库事务,而且在Hibernate的情况下,如果没有,它还会创建一个hibernate会话。 A typical approach is to use OpenSessionInViewFilter which creates one Hibernate session for each http request. 一种典型的方法是使用OpenSessionInViewFilter ,它为每个http请求创建一个Hibernate会话。

If you don't want to use this filter you need to annotate getters with @Transactional as well. 如果您不想使用此过滤器,则还需要使用@Transactional注释getter。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 了解交易服务-春季 - Understanding of Transactional services - spring @transactional 服务在 spring 中应该是单例还是原型? - Should @transactional services be singleton or prototype in spring? @交易服务 - @Transactional Services 关于服务和@Transactional - On services and @Transactional 休眠/春季-JUnit失败,出现事务性错误(REQUIRES_NEW) - Hibernate/Spring - JUnit fails with Transactional(REQUIRES_NEW) EJB 调用的 Spring 事务:当 Try 的事务方法出现 RuntimeException 时,Catch 中的事务方法需要 REQUIRES_NEW - Spring transaction called by EJB: REQUIRES_NEW needed for transactional method in Catch, when Try's transactional method has RuntimeException 使用 @Transactional(propagation = Propagation.REQUIRES_NEW) 注释的服务方法的 Spring Boot 集成测试 - Spring Boot Integration Test for Service method annotated with @Transactional(propagation = Propagation.REQUIRES_NEW) Spring 引导:保存到存储库不适用于@Transactional(传播 = Propagation.REQUIRES_NEW) - Spring Boot: save to repository doesnt work with @Transactional(propagation = Propagation.REQUIRES_NEW) Vert.x是否支持Spring Data的@Transactional(Propagation.REQUIRES_NEW)? - Is Spring Data's @Transactional(Propagation.REQUIRES_NEW) supported in Vert.x? 如何在春季使用@Transactional - How to use @Transactional in spring
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM