Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 在没有XA的事务中是否可能有两个MSSQL持久化单元?_Sql Server_Jpa_Jakarta Ee_Xa_Persistence Unit - Fatal编程技术网

Sql server 在没有XA的事务中是否可能有两个MSSQL持久化单元?

Sql server 在没有XA的事务中是否可能有两个MSSQL持久化单元?,sql-server,jpa,jakarta-ee,xa,persistence-unit,Sql Server,Jpa,Jakarta Ee,Xa,Persistence Unit,我们有一个应用程序,它有许多实体类,其中必须有两个表。这些表是相同的,唯一的区别是名称。这里提供的常见解决方案是使用继承(映射超类和每个类一个表策略)或两个具有不同映射的持久性单元。我们使用后一种解决方案,并且应用程序是基于这种方法构建的,因此现在认为它是给定的 有一些EJB方法将在两个持久性上下文上进行更新,并且必须在一个事务中进行更新。两个持久性上下文具有相同的数据源,该数据源是与Microsoft SQL Server数据库(2012版本)的支持XA的连接。上下文之间的唯一区别是,有一个映

我们有一个应用程序,它有许多实体类,其中必须有两个表。这些表是相同的,唯一的区别是名称。这里提供的常见解决方案是使用继承(映射超类和每个类一个表策略)或两个具有不同映射的持久性单元。我们使用后一种解决方案,并且应用程序是基于这种方法构建的,因此现在认为它是给定的

有一些EJB方法将在两个持久性上下文上进行更新,并且必须在一个事务中进行更新。两个持久性上下文具有相同的数据源,该数据源是与Microsoft SQL Server数据库(2012版本)的支持XA的连接。上下文之间的唯一区别是,有一个映射XML来更改某些实体类的表名,从而在这些表上工作

其中一位架构负责人希望消除XA事务,因为它们会对数据库造成很大的开销,而且显然也会使执行的查询的日志记录和分析变得更加困难,可能还会阻止一些准备好的语句缓存。我不知道所有细节,但对于许多应用程序,我们已经设法消除了XA。然而,对于这一个,我们目前不能,因为有两个持久性上下文

在这种情况下,是否有某种方法可以在没有XA的情况下以事务方式更新这两个上下文?如果是,怎么做?如果没有,是否有一些架构或配置更改可以使用一个持久性上下文,而不必为这两个表使用子类

我知道这些问题:以及


在投票将其作为副本关闭之前,请注意情况不同。我们不是像第一个问题中那样处于只读状态,两个上下文都在同一个数据库上运行,我们只使用MSSQL,我们使用的是GlassFish,而不是Weblogic。

经过一些实验,我发现在容器管理的事务中,实际上可能有两个使用非XA资源的持久化单元。但是,它可能依赖于实现。TL;博士在底部

如果一个事务中有多个资源参与,JTA应该需要XA资源。它使用X/openxa来允许分布式事务,例如多个数据库或数据库和JMS队列上的事务。显然有一些优化(可能是GlassFish特有的,我不确定)允许最后一个参与者是非XA的。然而,在我的用例中,两个持久化单元都用于同一个数据库(但是一组不同的表,有一些可能的重叠),并且都不是XA。这意味着,当第二个资源不支持XA时,我们希望抛出异常

假设这是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="playground" transaction-type="JTA">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>jdbc/playground</jta-data-source>
        <properties>
            <property name="hibernate.dialect" value="be.dkv.hibernate.SQLServer2012Dialect" />
            <property name="hibernate.hbm2ddl.auto" value="update" />
            <property name="hibernate.show_sql" value="true" />
        </properties>
    </persistence-unit>
    <persistence-unit name="playground-copy" transaction-type="JTA">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>jdbc/playground</jta-data-source>
        <mapping-file>META-INF/orm-playground-copy.xml</mapping-file>
        <properties>
            <property name="hibernate.dialect" value="be.dkv.hibernate.SQLServer2012Dialect" />
            <property name="hibernate.hbm2ddl.auto" value="update" />
            <property name="hibernate.show_sql" value="true" />
        </properties>
    </persistence-unit>
</persistence>
如果您创建了两个JDBC资源,但都指向同一个连接池,那么它同样可以正常工作。这甚至在显式使用class
com.microsoft.sqlserver.jdbc.SQLServerConnectionPoolDataSource
时起作用,确认这可能是JPA级别的优化,而不是意外地为同一数据源获得两次相同的连接(这将破坏GlassFish池)。当使用XA数据源时,它确实是一个支持XA的连接,但是JPA提供者仍然会对两个持久性上下文使用相同的连接。只有在使用单独的池时,它实际上才是两个完全独立的启用XA的连接,并且您将不再得到上述异常

那么,有什么问题吗?首先,我在JPA或JTA规范中没有发现任何描述(或强制)这种行为的内容。这意味着这可能是一个特定于实现的优化。移动到不同的JPA提供者,甚至是不同的版本,它可能不再工作

其次,有可能出现死锁。如果您在两个上下文中都获取上面示例中的实体,然后在一个上下文中对其进行更改并刷新,就可以了。在一个上下文中获取它,调用flush方法,然后尝试在另一个上下文中获取它,可能会出现死锁。如果允许读取未提交事务隔离,则可以避免这种情况,但在一个上下文中看到的情况将取决于在另一个上下文中获取刷新的时间。因此,手动刷新调用可能很棘手

作为参考,使用的GlassFish版本为
3.1.2.2
。JPA提供程序是Hibernate版本
3.6.4.Final


TL;DR


,您可以在JavaEE容器管理的事务中使用两个具有相同非XA资源的持久性上下文,并且ACID属性将被保留。然而,这要归功于当为具有相同数据源的同一事务创建多个EntityManager时,可能会进行Hibernate优化。由于JPA或JTA规范似乎没有强制要求这样做,所以您可能无法在JPA实现、版本或应用服务器之间依赖这种行为。因此,请进行测试,不要期望具有完全的可移植性。

如果两个持久化单元使用相同的数据源,那么您不需要XA@SteveC他们将从一个池中获得自己的连接,因此我看不出有任何方法可以强迫他们拥有相同的连接(从而实现事务)或者JPA将如何实际管理这一点。我希望他们都会参与同一个JTA事务…@SteveC他们都会参与同一个JTA事务,作为单独的连接,被视为分布式事务的一部分。这需要JTA提供XA源。如果不使用XA,两个持久性上下文都必须共享它们的连接,因为JDBC级别的事务绑定到连接。据我所知,这在容器管理的JPA中是不可能的。这就是问题所在。我一点也不确定。我会做一些测试来调查这种行为
Caused by: java.sql.SQLException: Error in allocating a connection. 
Cause: java.lang.IllegalStateException: Local transaction already has 1 non-XA Resource: cannot add more resources.