jta atomikos_带有Atomikos示例的Tomcat中的Spring JTA多个资源事务

jta atomikos

在本教程中,我们将向您展示如何使用Atomikos Transaction Manager在Tomcat服务器中实现JTA多个资源事务。 Atomicos事务管理器为分布式事务提供支持。 这些是多阶段事务,通常使用多个数据库,必须以协调的方式提交。 分布式事务由XA standard描述。 XA控制事务管理器(例如Atomikos)如何告知数据库作为什么事务的一部分正在进行的工作,以及如何在每个事务结束时执行两阶段提交(2PC)协议。

在这里,我们将创建映射到两个不同数据库的简单实体类,并尝试使用一个分布式事务将这些类的对象持久保存到数据库中。 我们还将看到当基础事务之一回滚时会发生什么。

我们首选的开发环境是Eclipse 。 我们正在使用Eclipse Juno(4.2)版本以及Maven Integration插件版本3.1.0。 您可以从Eclipse的这里从和Maven Eclipse插件这里 。 用于Eclipse的Maven插件的安装不在本教程的讨论范围之内,因此不再讨论。 我们还使用Spring 3.2.3和JDK 7_u_21。

Tomcat 7是使用的应用程序服务器。 Hibernate版本为4.1.9,示例中使用的数据库为MySQL Database Server 5.6。

让我们开始,

1.创建一个新的Maven项目

转到文件->项目-> Maven-> Maven项目。

新人项目

在向导的“选择项目名称和位置”页面中,确保未选中 “创建简单项目(跳过原型选择)”选项,单击“下一步”以继续使用默认值。

新项目

在这里,必须添加用于创建Web应用程序的Maven原型。 单击“添加原型”并添加原型。 将“ Archetype组ID”变量设置为"org.apache.maven.archetypes" ,将“ Archetype构件ID”变量设置为"maven-archetype-webapp" ,将“ Archetype版本”设置为"1.0" 。 点击“确定”继续。

Maven的原型Web应用程序

在向导的“输入工件ID”页面中,您可以定义项目的名称和主程序包。 将“ Group Id”变量设置为"com.javacodegeeks.snippets.enterprise" ,将“ Artifact Id”变量设置为"springexample" 。 前面提到的选择将主项目程序包组成为"com.javacodegeeks.snippets.enterprise.springexample" ,项目名称为"springexample" 。 将“ Package”变量设置为"war" ,以便创建一个war文件以部署到tomcat服务器。 点击“完成”退出向导并创建您的项目。

战争

Maven项目结构如下所示:

网络项目浏览器

  • 它由以下文件夹组成:
  • / src / main / java文件夹,其中包含应用程序动态内容的源文件,
  • / src / test / java文件夹包含用于单元测试的所有源文件,
  • / src / main / resources文件夹包含配置文件,
  • / target文件夹包含已编译和打包的可交付成果,
  • / src / main / resources / webapp / WEB-INF文件夹包含Web应用程序的部署描述符,
  • pom.xml是项目对象模型(POM)文件。 包含所有项目相关配置的单个文件。

2.添加Spring 3.2.3依赖项

  • 在POM编辑器的“概述”页面上找到“属性”部分,然后执行以下更改:
    创建一个新属性,名称为org.springframework.version ,值3.2.3RELEASE
  • 导航到POM编辑器的“依赖关系”页面,并创建以下依赖关系(您应在该页面的“依赖关系详细信息”部分的“ GroupId”,“工件ID”和“版本”字段中进行填充):
    组ID: org.springframework工件ID: spring-web版本: $ {org.springframework.version}

另外,您可以在Maven的pom.xml文件中添加Spring依赖项,方法是直接在POM编辑器的“ Pom.xml”页面上对其进行编辑,如下所示:

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0"; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.javacodegeeks.snippets.enterprise</groupId><artifactId>springexample</artifactId><version>0.0.1-SNAPSHOT</version><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency></dependencies><properties><spring.version>3.2.3.RELEASE</spring.version></properties>
</project>

如您所见,Maven以声明方式管理库依赖关系。 创建本地存储库(默认情况下,位于{user_home} /。m2文件夹下),所有必需的库都从公共存储库下载并放置在该库中。 此外,库内的依赖关系会自动解决和处理。

3.添加所有必需的依赖项

此处设置了设置atomosos事务管理器所需的所有依赖项。
pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.javacodegeeks.snippets.enterprise</groupId><artifactId>springexample</artifactId><packaging>war</packaging><version>0.0.1</version><name>springexample Maven Webapp</name><url>http://maven.apache.org</url><build><finalName>springexample</finalName></build><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-orm</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-entitymanager</artifactId><version>${hibernate.version}</version><exclusions><exclusion><groupId>cglib</groupId><artifactId>cglib</artifactId></exclusion><exclusion><groupId>dom4j</groupId><artifactId>dom4j</artifactId></exclusion></exclusions></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.0.1</version><scope>provided</scope></dependency><dependency><groupId>com.atomikos</groupId><artifactId>transactions-jta</artifactId><version>${atomikos.version}</version></dependency><dependency><groupId>com.atomikos</groupId><artifactId>transactions-jdbc</artifactId><version>${atomikos.version}</version></dependency><dependency><groupId>com.atomikos</groupId><artifactId>transactions-hibernate3</artifactId><version>${atomikos.version}</version><exclusions><exclusion><artifactId>hibernate</artifactId><groupId>org.hibernate</groupId></exclusion></exclusions></dependency><dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6.1</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.25</version></dependency></dependencies><properties><spring.version>3.2.3.RELEASE</spring.version><hibernate.version>4.1.9.Final</hibernate.version><atomikos.version>3.8.0</atomikos.version>
</properties></project>

4.创建实体类

EmployeeA.javaEmployeeB.java是Entity类。 他们使用javax.persistence批注映射到不同数据库中的表EMPLOYEEAEMPLOYEEB 。 特别地, @Entity注释指定每个类是一个实体。 @Table注释指定带注释的实体的主表。 @Column批注用于为持久字段指定一个映射列,而@Id批注指定每个实体的主键字段。

EmployeeA.java

package com.javacodegeeks.snippets.enterprise.model;import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;@Entity
@Table(name = "EMPLOYEEA")
public class EmployeeA {@Id@Column(name = "ID", nullable = false)private String id;@Column(name = "NAME", nullable = false)private String name;@Column(name = "AGE", nullable = false)private long age;public EmployeeA() {}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public long getAge() {return age;}public void setAge(long age) {this.age = age;}}

EmployeeB.java

package com.javacodegeeks.snippets.enterprise.model;import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;@Entity
@Table(name = "EMPLOYEEB")
public class EmployeeB {@Id@Column(name = "ID", nullable = false)private String id;@Column(name = "NAME", nullable = false)private String name;@Column(name = "AGE", nullable = false)private long age;public EmployeeB() {}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public long getAge() {return age;}public void setAge(long age) {this.age = age;}}

5.创建DAO类

实现的数据访问对象是EmployeeADAOImpl.javaEmployeeBDAOImpl.java类。 它们使用@Service注释进行注释,表明它们是Spring Bean,因此允许Spring自动检测它们。 它们都使用javax.persistence.EntityManager与数据库进行交互。

EntityManager实例与持久性上下文关联。 持久性上下文是一组实体实例,其中对于任何持久性实体标识,都有一个唯一的实体实例。 在持久性上下文中,管理实体实例及其生命周期。 EntityManager API用于创建和删除持久实体实例,通过其主键查找实体以及查询实体。 在persistence.xml文件中配置了EntityManager ,对此进行了描述
在第8.1段中。
可以由给定EntityManager实例管理的实体集由持久性单元定义。 持久性单元定义了与应用程序相关或分组的所有类的集合,这些类必须在它们到单个数据库的映射中共置。

EntityManager通过@PersistenceContext注释注入到每个DAO中,在该注释中设置了每个持久性单元的名称,如persistence.xml文件中所定义。
在两个DAO中都实现了一种基本的持久方法,即使用EntityManagerpersist(Object entity) API方法来创建数据库的对象。

DAO及其接口如下所示:

雇员ADAO.java

package com.javacodegeeks.snippets.enterprise.dao;import com.javacodegeeks.snippets.enterprise.model.EmployeeA;public interface EmployeeADAO {void persistEmployee(EmployeeA employee);		  
}

雇员ADAO Impl.java

package com.javacodegeeks.snippets.enterprise.dao;import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;import org.springframework.stereotype.Service;import com.javacodegeeks.snippets.enterprise.model.EmployeeA;@Service
public class EmployeeADAOImpl implements EmployeeADAO {@PersistenceContext(unitName="PersistenceUnitA")private EntityManager entityManager;public void persistEmployee(EmployeeA employee) {entityManager.persist(employee);}}

雇员BDAO .java

package com.javacodegeeks.snippets.enterprise.dao;import com.javacodegeeks.snippets.enterprise.model.EmployeeB;public interface EmployeeBDAO {void persistEmployee(EmployeeB employee) throws Exception;}

雇员BDAO Impl.java

package com.javacodegeeks.snippets.enterprise.dao;import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;import org.springframework.stereotype.Service;import com.javacodegeeks.snippets.enterprise.model.EmployeeB;@Service
public class EmployeeBDAOImpl implements EmployeeBDAO {@PersistenceContext(unitName="PersistenceUnitB")private EntityManager entityManager;public void persistEmployee(EmployeeB employee) throws Exception {entityManager.persist(employee);
//		throw new Exception();}
}

6.创建服务类

EmployeeADAOImpl.javaEmployeeBDAOImpl.java类被注入EmployeeServiceImpl.java类。 因此,在此处实现的persistEmployees(EmployeeA employeeA, EmployeeB employeeB)方法中,将调用DAO的方法来执行与数据库的基本交互。 EmployeeServiceImpl.java类也带有@Service注释,表明它是一个Spring Bean,因此允许Spring自动检测到它。

@Transactional批注放置在方法之前,以表示在调用该方法时创建了一个事务。 该事务是全局容器管理的事务,将在Spring配置文件中进行配置。
EmployeeService.java

package com.javacodegeeks.snippets.enterprise.service;import com.javacodegeeks.snippets.enterprise.model.EmployeeA;
import com.javacodegeeks.snippets.enterprise.model.EmployeeB;public interface EmployeeService {void persistEmployees(EmployeeA employeeA, EmployeeB employeeB) throws Exception;}

EmployeeServiceImpl.java

package com.javacodegeeks.snippets.enterprise.service;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import com.javacodegeeks.snippets.enterprise.dao.EmployeeADAO;
import com.javacodegeeks.snippets.enterprise.dao.EmployeeBDAO;
import com.javacodegeeks.snippets.enterprise.model.EmployeeA;
import com.javacodegeeks.snippets.enterprise.model.EmployeeB;@Service("employeeService")
public class EmployeeServiceImpl implements EmployeeService{@AutowiredEmployeeADAO employeeADAO;@AutowiredEmployeeBDAO employeeBDAO;@Transactional(rollbackFor=Exception.class)public void persistEmployees(EmployeeA employeeA, EmployeeB employeeB) throws Exception {System.out.println("Persist A");employeeADAO.persistEmployee(employeeA);System.out.println("Persist A OK - persist B");employeeBDAO.persistEmployee(employeeB);System.out.println("Persist B okk");}}

7.创建一个servlet以运行该应用程序

AppServlet.java类是一个简单的servlet,它实现org.springframework.web.HttpRequestHandler并覆盖其handleRequest(HttpServletRequest req, HttpServletResponse resp) API方法。 EmployeeService通过@Autowire注释注入到此处。 在handleRequest(HttpServletRequest req, HttpServletResponse resp) API方法中使用它来持久存储新的EmployeeA和新的EmployeeB对象。 如果该方法成功返回,则该方法还返回一条成功消息,如果该方法抛出异常,则返回回滚消息。

AppServlet.java

package com.javacodegeeks.snippets.enterprise.servlet;import java.io.IOException;
import java.io.PrintWriter;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.HttpRequestHandler;import com.javacodegeeks.snippets.enterprise.model.EmployeeA;
import com.javacodegeeks.snippets.enterprise.model.EmployeeB;
import com.javacodegeeks.snippets.enterprise.service.EmployeeService;@Component("appServlet")
public class AppServlet implements HttpRequestHandler {@Autowiredprivate EmployeeService employeeService;public void handleRequest(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {EmployeeA em1 = new EmployeeA();em1.setId("123");em1.setName("John");em1.setAge(35);EmployeeB em2 = new EmployeeB();em2.setId("123");em2.setName("Mary");em2.setAge(31);try {employeeService.persistEmployees(em1, em2);resp.setContentType("text/html");PrintWriter out = resp.getWriter();out.println("<html>");out.println("<head>");out.println("<title>Hello World!</title>");out.println("</head>");out.println("<body>");out.println("<h1>Java Code Geeks </h1>");out.println("<h2>Both employees are inserted!</h2>");out.println("</body>");out.println("</html>");} catch (Exception e) {resp.setContentType("text/html");PrintWriter out = resp.getWriter();out.println("<html>");out.println("<head>");out.println("<title>Hello World!</title>");out.println("</head>");out.println("<body>");out.println("<h1>Java Code Geeks </h1>");out.println("<h2>Transaction Rollback!</h2>");out.println("</body>");out.println("</html>");e.printStackTrace();}}
}

8.配置应用程序

8.1配置持久性单元

如上所述,在persistence.xml文件中配置了每个数据库的entityManager和与其关联的持久性单元。 在这里,我们定义了两个持久性单元。 在每个persistence-unit元素中,我们定义与持久性单元关联的实体类。 hibernate.transaction.manager_lookup_class属性设置为com.atomikos.icatch.jta.hibernate3.TransactionManagerLookuphibernate.transaction.factory_class属性设置为org.hibernate.transaction.CMTTransactionFactory
persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"><persistence-unit name="PersistenceUnitA" transaction-type="JTA"><class>com.javacodegeeks.snippets.enterprise.model.EmployeeA</class><properties><property name="hibernate.transaction.manager_lookup_class"value="com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup" /><property name="hibernate.transaction.factory_class"value="org.hibernate.transaction.CMTTransactionFactory" /></properties></persistence-unit><persistence-unit name="PersistenceUnitB" transaction-type="JTA"><class>com.javacodegeeks.snippets.enterprise.model.EmployeeB</class><properties><property name="hibernate.transaction.manager_lookup_class"value="com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup" /><property name="hibernate.transaction.factory_class"value="org.hibernate.transaction.CMTTransactionFactory" /></properties></persistence-unit></persistence>

8.2配置Spring容器

applicationContext.xml文件是Spring的配置文件。

<context:component-scan/>元素用于设置包含容器必须扫描以检测Spring Bean的所有类的包。
还使用<tx:annotation-driven/>元素,以便Spring具有@Transactional感知,并可以检测@Transactional注释以配置具有事务行为的适当bean。
<jta-transaction-manager/>元素用于检测基础服务器并选择可用于平台的事务管理器。

dataSourceAdataSourceB bean中,我们定义了数据源。 com.atomikos.jdbc.AtomikosDataSourceBean是此处设置的类。 它使用支持Atomikos JTA的连接池。 它具有两个要配置的属性。 com.mysql.jdbc.jdbc2.optional.MysqlXADataSource类设置为xaDataSourceClass属性,而在xaProperties我们可以设置属性(名称,值对)以配置XADataSource

entityManagerFactoryAentityManagerFactoryB bean中,我们设置了org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean类。 它是一个FactoryBean ,可根据JPA的标准容器引导合同创建JPA EntityManagerFactory 。 我们可以在其persistenceXmlLocation属性中设置persistence.xml位置。 我们可以在persistenceUnitName属性中设置用于创建此EntityManagerFactory的持久性单元的名称。 datasource属性是对适当的dataSource bean的引用。 jpaVendorAdapter属性设置为org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter ,它是Hibernate EntityManager的实现。

最后,使用org.springframework.transaction.jta.JtaTransactionManager定义transactionManager bean。 它包含两个要配置的属性。 transactionManageratomikosTransactionManager 。 它们分别引用了com.atomikos.icatch.jta.UserTransactionManager类和com.atomikos.icatch.jta.J2eeUserTransaction类的两个bean。
applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"xmlns:task="http://www.springframework.org/schema/task"xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd"><context:component-scan base-package="com.javacodegeeks.snippets.enterprise.*" /><tx:annotation-driven /><tx:jta-transaction-manager /><bean id="dataSourceA" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close"><property name="uniqueResourceName"><value>DataSourceA</value></property><property name="xaDataSourceClassName"><value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</value></property><property name="xaProperties"><props><prop key="databaseName">companyA</prop><prop key="serverName">localhost</prop><prop key="port">3306</prop><prop key="user">root</prop><prop key="password">root</prop><prop key="url">jdbc:mysql://localhost:3306/companyA</prop></props></property><property name="minPoolSize"><value>1</value></property>
</bean><bean id="dataSourceB" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close"><property name="uniqueResourceName"><value>DataSourceB</value></property><property name="xaDataSourceClassName"><value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</value></property><property name="xaProperties"><props><prop key="databaseName">companyB</prop><prop key="serverName">localhost</prop><prop key="port">3306</prop><prop key="user">root</prop><prop key="password">root</prop><prop key="url">jdbc:mysql://localhost:3306/companyB</prop></props></property><property name="minPoolSize"><value>1</value></property>
</bean><bean id="entityManagerFactoryA" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"><property name="persistenceXmlLocation"><value>classpath*:persistence.xml</value></property><property name="persistenceUnitName" value="PersistenceUnitA" /><property name="dataSource" ref="dataSourceA" /><property name="jpaVendorAdapter"><bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"><property name="showSql" value="true" /><property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect" /></bean></property></bean><bean id="entityManagerFactoryB" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"><property name="persistenceXmlLocation"><value>classpath*:persistence.xml</value></property><property name="persistenceUnitName" value="PersistenceUnitB" /><property name="dataSource" ref="dataSourceB" /><property name="jpaVendorAdapter"><bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"><property name="showSql" value="true" /><property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect" /></bean></property></bean><bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close"><property name="forceShutdown" value="false" /></bean><bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.J2eeUserTransaction"><property name="transactionTimeout" value="300" /></bean><bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"depends-on="atomikosTransactionManager,atomikosUserTransaction"><property name="transactionManager" ref="atomikosTransactionManager" /><property name="userTransaction" ref="atomikosUserTransaction" /><property name="allowCustomIsolationLevels" value="true" /></bean></beans>

8.3配置Web应用程序部署描述符

web.xml文件是定义服务器需要了解的有关应用程序的所有内容的文件。 此处设置了Servlet和其他组件,例如过滤器或侦听器,初始化参数,容器管理的安全性约束,资源,欢迎页面等。

servlet元素声明AppServlet ,并声明实现它的org.springframework.web.context.support.HttpRequestHandlerServlet类。 servlet-mapping元素指定在浏览器中调用servlet的/appServlet URL模式。 在context-param元素中,我们设置了contextConfigLocation参数,其中定义了applicationContext.xml文件位置。 在listener元素中,将Bootstrap侦听器设置为启动Spring的applicationContext.xml 。 在两个数据源中都设置了resource-ref元素,以定义对资源的引用查找名称。 这允许Servlet代码通过在部署时映射到实际位置的“虚拟”名称来查找资源。

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_3_0.xsd"id="WebApp_ID" version="3.0"><display-name>javacodegeeks</display-name><context-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/applicationContext.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><servlet><display-name>AppServlet</display-name><servlet-name>appServlet</servlet-name><servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class></servlet><servlet-mapping><servlet-name>appServlet</servlet-name><url-pattern>/appServlet</url-pattern></servlet-mapping><resource-ref><description>MySQL DS</description><res-ref-name>jdbc/DataSourceA</res-ref-name><res-type>javax.sql.DataSource</res-type><res-auth>Container</res-auth></resource-ref><resource-ref><description>MySQL DS</description><res-ref-name>jdbc/DataSourceB</res-ref-name><res-type>javax.sql.DataSource</res-type><res-auth>Container</res-auth></resource-ref></web-app>

9.在Tomcat中运行应用程序

为了在tomcat中运行应用程序,我们首先必须构建项目。 产生的war位于tomcat的webapps文件夹中。 然后,我们启动服务器。 撞上之后

localhost:8080/springexample/appServlet

在浏览器中,我们可以检查在MySQL,这两个数据库, companyAcompanyBEmployeeAEmployeeB有一个记录。 浏览器中返回的消息是以下消息:

成功

10.回滚情况

现在,让我们看看如果两个事务之一失败了会发生什么。 我们将更改EmployeeBDAOImpl.java类的persistEmployee(EmployeeB employee)方法,以引发Exception

雇员BDAO Impl.java

package com.javacodegeeks.snippets.enterprise.dao;import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;import org.springframework.stereotype.Service;import com.javacodegeeks.snippets.enterprise.model.EmployeeB;@Service
public class EmployeeBDAOImpl implements EmployeeBDAO {@PersistenceContext(unitName="PersistenceUnitB")private EntityManager entityManager;public void persistEmployee(EmployeeB employee) throws Exception {
//		entityManager.persist(employee);throw new Exception();}
}

我们再次构建该项目,并将新的war文件放入tomcat的webapps文件中。 再次启动tomcat之后,结果如下:

回滚

这是由于事务之一引发异常而导致分布式事务也会回滚。

这是使用Atomikos事务管理器在Tomcat服务器中进行JTA多个资源事务的示例。 下载本教程的Eclipse项目: SpringJTAatomicosTomcatExample.zip

翻译自: https://www.javacodegeeks.com/2013/07/spring-jta-multiple-resource-transactions-in-tomcat-with-atomikos-example.html

jta atomikos

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/348326.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

台电+android+电话,通话系统_台电 G17s_平板电脑评测-中关村在线

通话系统将两张联通3G的SIM卡插入台电G17s之后&#xff0c;我们来感受一下它通话系统的使用是否令人满意。和一般的双卡Android手机平板一样&#xff0c;该机也不支持热插拔&#xff0c;需要将机器彻底关闭后插入SIM卡再开机。并且在开机后屏幕会弹出SIM卡信息&#xff0c;并询…

功能Java示例 第2部分–讲故事

这是称为“ Functional Java by Example”的系列文章的第2部分。 我在本系列的每个部分中发展的示例是某种“提要处理程序”&#xff0c;用于处理文档。 在上一部分中&#xff0c;我从一些原始代码开始&#xff0c;并应用了一些重构来描述“什么”而不是“如何”。 为了帮助代…

OpenHub框架–下一个有趣的功能

这是有关OpenHub框架的系列文章中的第三篇&#xff0c;第一篇介绍OpenHub框架 &#xff0c;第二篇介绍异步消息传递模型 。 该系列的最后一篇文章将更详细地介绍其他一些有趣的功能&#xff0c;并说明为什么OpenHub可以成为您的集成项目的理想选择的原因。 节流 节流是一种功…

ubuntu生成密钥和证书_基于浏览器的密钥生成以及与浏览器的密钥/证书存储的交互...

ubuntu生成密钥和证书想象以下情况&#xff1a; 您需要从访问您的网站的用户那里获取一个密钥&#xff08;在非对称情况下为用户的公共密钥 &#xff09;&#xff0c;并希望浏览器记住私有部分&#xff0c;而不会因冗长的导入过程而困扰用户。 老实说&#xff0c;实际上&#…

android数据流分类,【Android工程之类】1 MVVM架构 - MVVM与单向数据流

前言这个系列将讲述使用MVVM架构、LiveData、Room、Kodein、Retrofit、EventBus来建立一个统一的、优雅的、可维护的TODO程序&#xff0c;本系列分为多个章节&#xff0c;从0开始一步一步引入这些优秀的库。下图展示的是Jetpack组件库包含的内容&#xff0c;这套的架构方案的核…

java ssl证书_Java安全教程–创建SSL连接和证书的分步指南

java ssl证书在有关应用JEE安全性的系列文章中&#xff0c;我们为您提供了另一个有关如何在Java EE应用程序中创建SSL连接和创建证书的详细教程。 如我们之前的文章中所述&#xff0c; 安全套接字层&#xff08;SSL&#xff09;/传输层安全性&#xff08;TLS&#xff09;将启用…

通过Okta的单点登录保护Spring Boot Web App的安全

“我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕&#xff1f; 尝试使用Okta API进行托管身份验证&#xff0c;授权和多因素身份验证。 您可以使用SpringBoot和Okta在不到20分钟的时间内启动具有完整用户身份和授权管理的企…

java ee cdi_Java EE CDI程序化依赖关系消歧示例–注入点检查

java ee cdi在本教程中&#xff0c;我们将看到在注入Java EE CDI bean时如何避免程序依赖消除歧义。 我们已经在Jave EE依赖关系消除歧义示例中展示了如何避免CDI Bean中的依赖关系歧义消除。 在这里&#xff0c;我们将向您展示如何以动态方式避免依赖消除歧义。 我们将通过检查…

atom自动补全html代码,Atom - Emmet插件的使用详解(HTML/CSS代码自动补全)

一、Emmet的安装与介绍Emmet (前身为 Zen Coding) 是一个能大幅度提高前端开发效率的工具&#xff0c;能够实现 HTML、CSS 的快速编写。官网地址&#xff1a;http://emmet.io/官方文档&#xff1a;http://docs.emmet.io/cheat-sheet/Atom的emmet介绍页面&#xff1a;https://at…

html怎么做出相框的效果,PS滤镜制作漂亮的实木相框效果

一、新建一个600 * 800像素的文件&#xff0c;然后新建一个图层&#xff0c;前景颜色设置为红色&#xff0c;背景设置为深红色&#xff0c;执行&#xff1a;滤镜 > 渲染 > 纤维&#xff0c;参数设置如下图。二、执行&#xff1a;图像 > 旋转画布 > 逆时针90度&…

查询阜阳2021高考成绩,2021年阜阳高考成绩排名及成绩公布时间什么时候出来

阜阳高考结束后&#xff0c;每年都有很多家长和考试不知道阜阳高考成绩排名如何查询、阜阳高考成绩什么时候公布以及查询方式&#xff0c;本文小编整理了阜阳高考成绩查询排名的相关知识。一、阜阳高考成绩公布时间及查询方式根据往年阜阳高考成绩公布时间预测&#xff0c;2021…

2021高考厦门一中成绩查询,2021年厦门中考成绩和分数线什么时候公布(附查询入口)...

每年中考结束后很多考生和家长都很关心成绩什么时候公布&#xff0c;中考分数线什么时候公布&#xff1f;然而你离彻底解放就只差一步——查分数&#xff01;查分数&#xff0c;比上考场考试还要紧张啊&#xff01;考分不知道&#xff0c;玩耍似心跳。那么2019年厦门中考成绩什…

Java开发人员应该知道的前20个库和API

优秀且经验丰富的Java开发人员的特征之一是对API的广泛了解&#xff0c;包括JDK和第三方库。 我花了很多时间来学习API&#xff0c;尤其是在阅读了Effective Java 3rd Edition之后 &#xff0c;Joshua Bloch建议在Java 3rd Edition中使用现有的API进行开发&#xff0c;而不是为…

打磨锤子计算机专业,钳工磨锤子实训心得体会

钳工磨锤子实训心得体会实训是职业技能实际训练的简称,是指在学校控制状态下,按照人才培养规律与目标,对学生进行职业技术应用能力训练的教学过程。钳工磨锤子实训心得体会&#xff0c;我们来看看。钳工磨锤子实训心得体会1前言&#xff1a;通过这次的钳工实习报告&#xff0c;…

html编辑器设置为publisher,将PDF转换为Publisher的简单方法

二、 如何把PDF文件转换为Publisher支持的图片格式一些专业的软件或者在线网站都可以帮助我们把PDF文件转换为Publisher支持的图片格式。下面将提供几种支持PDF文件转换为图片格式的方法。(1) 使用都叫兽™PDF转换器进行格式转换热点推荐 - ADs都叫兽™PDF转换器 - 多功能的PDF…

Oracle应用容器云上的WildFly Swarm

在此博客文章中&#xff0c;我将描述如何将打包在WildFly Swarmber -jar中的CloudEE Duke应用程序部署到Oracle Application Container Cloud 。 在Oracle Application Container Cloud中进行部署所需的部署工件是一个ZIP归档文件&#xff0c;其中包含应用程序ber-jar和清单文…

适合学计算机用的机械键盘,一款好用的机械键盘应该怎么选?看完这篇就明白了...

一款好用的机械键盘应该怎么选&#xff1f;看完这篇就明白了2019-07-30 15:53:134点赞14收藏3评论今天给大家带来好物推荐第1期——机械键盘。作为在办公室办公的从业者们&#xff0c;平时工作中与电脑的接触时间最多。而人与电脑的交互主要靠键盘和鼠标&#xff0c;其中使用最…

六年级计算机课学什么时候,六年级信息技术《进一步了解计算机》教学设计

六年级信息技术《进一步了解计算机》教学设计教学目标知识与技能&#xff1a;1.了解计算机的五大部件2.了解各种典型的、常见的输入设备、输出设备、存储器等。过程与方法&#xff1a;通过学生利用教师提供的主题资源网站自主学习&#xff0c;了解计算机五大部件。情感、态度与…

asciidoc文件阅读_可搜索的文件? 是的你可以。 选择AsciiDoc的另一个原因

asciidoc文件阅读Elasticsearch是一个基于Apache Lucene的灵活&#xff0c;功能强大的开源&#xff0c;分布式实时云搜索和分析引擎&#xff0c;可提供全文搜索功能。 它是面向文档且无架构的。 Asciidoctor是一个纯Ruby处理器&#xff0c;用于将AsciiDoc源文件和字符串转换为…

专转本计算机专业录取分数线,2018江苏专转本各专业分数线一览!

原标题&#xff1a;2018江苏专转本各专业分数线一览&#xff01;2018江苏专转本分数线梳理018江苏专转本考试已过去四个月&#xff0c;分数线已经公布了三个多月。按照分数线进行梳理大致情况如下&#xff1a;300分以上院校专业常州大学的财务管理 320分独占鳌头。300分以上分数…