加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 资源网站 > 资源 > 正文

对于web MVC Spring应用程序应该@Transactional去控制器或服务?

发布时间:2020-12-14 21:32:17 所属栏目:资源 来源:网络整理
导读:对于WebApplicationContext,我应该将@Transactional注释放在控制器或服务中吗? Spring文档让我有些困惑。 这是我的web.xml: ?xml version="1.0" encoding="UTF-8"?web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun
对于WebApplicationContext,我应该将@Transactional注释放在控制器或服务中吗? Spring文档让我有些困惑。

这是我的web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>Alpha v0.02</display-name>
  <servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>*.htm</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>*.json</url-pattern>
  </servlet-mapping>

  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

这是我的application-context.xml定义一个spring调度程序servlet:

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

    <context:annotation-config />
    <mvc:annotation-driven />
    <tx:annotation-driven />

    <context:component-scan base-package="com.visitrend" />

    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

     <bean id="dataSource"  class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <property name="driverClass" value="org.postgresql.Driver" />
        <property name="jdbcUrl" value="jdbc:postgresql://localhost:5432/postgres" />
        <property name="user" value="someuser" />
        <property name="password" value="somepasswd" />
    </bean>

    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation" value="classpath:test.hibernate.cfg.xml" />
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
      <property name="dataSource" ref="dataSource" />
      <property name="sessionFactory" ref="sessionFactory" />
    </bean>    
</beans>

这是一个服务界面:

public interface LayerService {
    public void createLayer(Integer layerListID,Layer layer);
}

这是一个服务实现:

@Service
public class LayerServiceImpl implements LayerService {

    @Autowired
    public LayerDAO layerDAO;

    @Transactional
    @Override
    public void createLayer(Integer layerListID,Layer layer) {
        layerDAO.createLayer(layerListID,layer);
    }
}

这是我的控制器:

@Controller
public class MainController {

    @Autowired
    private LayerService layerService;

    @RequestMapping(value = "/addLayer.json",method = RequestMethod.POST)
    public @ResponseBody
    LayerListSetGroup addLayer(@RequestBody JSONLayerFactory request) {
        layerService.createLayer(request.getListId(),request.buildLayer());
        return layerService.readLayerListSetGroup(llsgID);
    }
}

Spring文档让我有点困惑。似乎表明使用WebApplicationContext意味着只有控制器将被调查@Transactional注释而不是服务。同时我看到了许多建议,使服务交易而不是控制器。我在考虑使用< context:component-scan base-package =“com ...”/>在我们上面的spring-servlet.xml中,它包括服务包意味着服务是上下文的一部分,因此将被“调查”用于事务注释。这是准确吗?

这是Spring文档blurb让我困惑:

@EnableTransactionManagement and only looks
for @Transactional on beans in the same application context they are
defined in. This means that,if you put annotation driven
configuration in a WebApplicationContext for a DispatcherServlet,it
only checks for @Transactional beans in your controllers,and not your
services.

此外,如果我将控制器方法定义为事务性,是否有任何性能影响或“坏”,并且在另一个类中调用事务方法?我的希望是没有,基于文档,但会喜欢验证。

解决方法

不需要@Transactional注释是应该在控制器还是服务上,但是通常它将继续执行一个服务,该服务将在一个ACID事务中逻辑地执行一个请求的逻辑。

在一个典型的Spring MVC应用程序中,最少可以有两个上下文:应用程序上下文和servlet上下文。上下文是一种配置。应用程序上下文保存与整个应用程序相关的配置,而servlet上下文只保留与您的servlet相关的配置。因此,servlet上下文是应用程序上下文的子代,并且可以引用应用程序上下文中的任何实体。反之亦然。

在你的报价中,

@EnableTransactionManagement and only looks for @Transactional on beans in the same application context they are defined in. This means that,if you put annotation driven configuration in a WebApplicationContext for a DispatcherServlet,it only checks for @Transactional beans in your controllers,and not your services.

@EnableTransactionManagement在@ComponentScan注释中声明的包中的bean中查找@Transactional,但仅在它们定义的上下文(@Configuration)中。因此,如果您的DispatcherServlet具有WebApplicationContext(这是一个servlet上下文),则@EnableTransactionManagement将在您在该上下文(@Configuration类)中告诉组件扫描的类中寻找@Transactional。

@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages = "my.servlet.package")
public class ServletContextConfiguration {
    // this will only find @Transactional annotations on classes in my.servlet.package package
}

由于您的@Service类是应用程序上下文的一部分,因此如果要使这些事务处理事务,则需要使用@EnableTransactionManagement为应用程序上下文注释@Configuration类。

@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages = "my.package.services")
public class ApplicationContextConfiguration {
    // now this will scan your my.package.services package for @Transactional
}

在实例化DispatcherServlet时,使用ContextLoaderListener和您的Servlet Context配置。 (See the javadoc为完整的基于java的配置,而不是xml,如果你还没有这样做)。

附录:@EnableTransactionManagement与< tx:annotation-driven />具有相同的行为。在java配置中。 Check here使用ContextLoaderListener与XML。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读