当前位置: 首页 > 知识库问答 >
问题:

如何在JTA事务模式下配置EJB/JPA?

周锐
2023-03-14

这是一个配置JPA和使用JTA事务模式连接数据库的简单指南。此外,它还包括开发人员最常见的错误,您应该避免这些错误。希望这对你有帮助。

共有1个答案

魏康安
2023-03-14

1-在您的应用程序服务器中设置数据源:为了使用JTA模式在您的WebApp中配置JPA,您需要首先设置数据源。您可以从您的应用程序服务器(Glassfish/Payara/...)设置数据源。但是建议通过您的网络应用程序设置数据源。按照以下步骤通过您的Maven WebApp设置Glassfish或Payara的数据源:

  1. 在项目文件夹中创建一个名为安装的新文件夹(非包)。
  2. 创建一个新的xml文件,并将其命名为glassfish-resources.xml,并将其保存在安装文件夹中。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">
<resources>
    <jdbc-resource enabled="true" jndi-name="**jdbc/DBDev01**" object-type="user" pool-name="**jdbc/DBDev01-ConnectionPool**">
    <description/>
  </jdbc-resource>
   <jdbc-connection-pool allow-non-component-callers="false" 
                        associate-with-thread="false" connection-creation-retry-attempts="0" 
                        connection-creation-retry-interval-in-seconds="10" 
                        connection-leak-reclaim="false" 
                        connection-leak-timeout-in-seconds="0" 
                        connection-validation-method="auto-commit" 
                        datasource-classname="**org.mariadb.jdbc.MariaDbDataSource**" 
                        fail-all-connections="false" 
                        idle-timeout-in-seconds="300" 
                        is-connection-validation-required="false" 
                        is-isolation-level-guaranteed="true" 
                        lazy-connection-association="false" 
                        lazy-connection-enlistment="false" 
                        match-connections="false" 
                        max-connection-usage-count="0" 
                        max-pool-size="32" 
                        max-wait-time-in-millis="60000" 
                        name="**jdbc/DBDev01-ConnectionPool**" 
                        non-transactional-connections="false" 
                        pool-resize-quantity="2" 
                        res-type="javax.sql.DataSource" statement-timeout-in-seconds="-1" steady-pool-size="8" validate-atmost-once-period-in-seconds="0" wrap-jdbc-objects="false">
<!-- for MariaDB users, it recomended to add ?useMysqlMetadata=true, this will make MariaDB pretending that it is a MySQL for tools or libraries that not support MariaDB -->    
<property name="URL" value="**jdbc:mariadb://XXX.XXX.XXX.XXX:XXXX/DB_NAME?useMysqlMetadata=true**"/>
    <property name="User" value="**USERNAME**"/>
    <property name="Password" value="**PASSWORD**"/>
  </jdbc-connection-pool>
</resources>

注意: ** ** 之间的所有值都应根据您的设置进行修改。部署您的网络应用程序后,该文件将由您的应用程序服务器(Glassfish/Payara)加载。对于Payara用户,您也可以用“payara-resources.xml”命名该文件,但修改很少。参考: Payara部署描述符。

2-在WEB-INF/WEB中为数据源添加资源引用。xml:您需要通过在WEB-INF/WEB中添加数据源来为您的Webapp中的数据源添加资源引用。xml文件:

<web-app .....>
  ......

<resource-ref>
  <description>**DBDev01**</description>
  <res-ref-name>**jdbc/DBDev01**</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <res-auth>Container</res-auth>
  <!-- <res-sharing-scope>Shareable</res-sharing-scope> -->
</resource-ref>
</web-app>

注意:res-ref-name应该与您在glassfish资源文件中为数据源选择的名称完全匹配。

3-配置持久性。xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="**MyDB**" transaction-type="JTA">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <!--  List all Entity classes  -->
    <class>**com.MyEntityClassName**</class>

    <jta-data-source>**jdbc/DBDev01**</jta-data-source>
<!--  you can list all entity classes you need and set this value to true. or set this value to false to include other entity clases  -->
    <exclude-unlisted-classes>true</exclude-unlisted-classes>

<properties>
             <!-- while eclipselink not support MariaDB , set this property to enforce eclipselink to work with it as MySQL -->
            <property name="eclipselink.target-database" value="MySQL"/>
        </properties>
  </persistence-unit>
  </persistence>

注1:如果想使用JTA作为事务类型,那么必须定义JTA数据源。开发人员在属性中添加DB URL、用户名和密码,试图在不定义JTA数据源的情况下连接到数据库,这是一个常见的错误。这将不起作用,并将导致应用程序服务器使用已定义的默认数据源,该数据源通常是H2数据库。

注2:eclipselink(JPA库)不支持MariaDB。但有一个解决办法。解决方案1::在连接URL上添加“?useMysqlMetadata=true”作为后缀,如:

<properties>
         <!-- while eclipselink not support MariaDB , set this property to enforce eclipselink to work with it as MySQL -->
        <property name="eclipselink.target-database" value="MySQL"/>
    </properties>

4-在POM中添加JDBC客户端作为依赖项。xml:

<dependency>
<!--  This is for MariaDB. You should change it if you are using other kind of DB like MySQL or Oracle DB  -->
    <groupId>org.mariadb.jdbc</groupId>
    <artifactId>mariadb-java-client</artifactId>
    <version>2.7.2</version>
</dependency>

5.享受代码:编写sessionBean:

@Stateless
public class StudentManager
{
/* Notes: 
1.you should use the same name exactly that defined in Persistence.xml file.
2.You can not use @PersistenceUnit with JTA. only use @PersistenceContext with JTA.
*/

    @PersistenceContext(unitName="MyDB")
    private EntityManager em;
    
    public StudentManager()
    {
        
    }
    
    public void persist(Student student) {
        
        em.persist(student);
    }    
}

编写TestController:

@Named
@SessionScoped
public class TestController
{
    @Inject
    private StudentManager studentManager;
    private String message = "";
    
    public void test()
    {
        Student student = new Student();
   
        Student.setCode(11223344);
        Student.setName("John");
        
        studentManager.persist(Student); 
/*Note:we used studentManager directly without constructing.
writing studentManager = new StudentManager() is a common mistake and will lead you to get a null EntityManager.*/
        this.setMessage("A new Student already saved successful with Code:" + Student.getCode());
    }

常见问题:应该使用@Inject还是@EJB?答案如下

用于测试的简单JSF页面:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        <h:form>
             <h:commandButton value="Test Save a Student over JTA" action="#{testController.test()}" />
             <br />
             <h:outputLabel for="message" value="#{test.message}" />
        </h:form>

    </h:body>
</html>

 类似资料:
  • 此外,我已经用以下参数配置了HBase集群: 它不起作用。 1。HMaster启动 2。我将“http://nn1:16010”放入浏览器 3。HMaster消失 以下是我的日志/hbase-hadoop-master-nn1.log: http://paste.openstack.org/show/549232/

  • Infinispan留档说了很多关于它的锁定方案的东西,乐观的和悲观的,但是没有详细说明如何使用事务。可能它被认为是知道的,因为它使用Java的默认API,但是如果是这样,我也没有找到关于JTA使用模式的信息。 我假设,在使用乐观事务时,它将被提交或回滚,这取决于对数据的并发访问。如果回滚,我将能够重播事务,希望现在它将在其他并发访问之前完成,并将成功。我在TransactionManager上有

  • Spring Boot通过使用Atomikos或Bitronix嵌入式事务管理器支持跨多个XA资源的分布式JTA事务。 部署到合适的Java EE Application Server时,也支持JTA事务。 检测到JTA环境时,Spring的JtaTransactionManager用于管理事务。 自动配置的JMS,DataSource和JPA bean已升级为支持XA事务。 您可以使用标准的Sp

  • 环境: 我们有一个应用程序部署在 JBoss 4.2.3.GA 服务器中,它使用Hibernate 3.4 和 JTA 1.0。 有一个导入器创建或更新某些实体,然后导入一些数据。由于多种原因,大部分导入是在新事务中完成的,在每个事务中,在外部事务中创建/更新的实体可能会再次更新。 调用序列类似于以下伪代码: 服务1: 服务2: 问题: 现在的问题是,我们最终会遇到一个竞争条件,有几个事务试图锁定

  • JTA事务意外回滚(可能是由于超时);嵌套的异常是 由于JPA,我得到了一个超时异常:如何增加事务所需的时间? 我应该在哪里包括参数来解决这个问题? 我用的是Tomcat7。

  • 我正在阅读使用Spring框架的事务管理。在第一个组合中,我使用Spring Hibernate和Hibernate的API来控制事务(Hibernate API)。接下来,我想使用注释进行测试,它确实起了作用。 我感到困惑的是: > JPA、JTA、Hibernate是否有自己的事务管理方式。举个例子,考虑如果我使用Spring Hibernate,在那种情况下,你会使用“JPA”事务吗? 就像