Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.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

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
Hibernate Persist在远程会话bean上未按预期工作_Hibernate_Jpa_Glassfish_Eclipselink_Persistence - Fatal编程技术网

Hibernate Persist在远程会话bean上未按预期工作

Hibernate Persist在远程会话bean上未按预期工作,hibernate,jpa,glassfish,eclipselink,persistence,Hibernate,Jpa,Glassfish,Eclipselink,Persistence,我在两个不同Glassfish域之间通信的两个JEE应用程序之间存在持久性问题 基本结构 我们在Glassfish服务器的两个不同域上部署了两个JEE应用程序 Application1部署在domain1上并使用数据库Database1 Application2部署在domain2上,并使用数据库Database2 Application1通过远程EJB与Application2通信 会话bean 另一种观点 玻璃鱼4.0 域1 应用程序1数据库1 应用程序1 ejb 应用1战争

我在两个不同Glassfish域之间通信的两个JEE应用程序之间存在持久性问题

基本结构
  • 我们在Glassfish服务器的两个不同域上部署了两个JEE应用程序
  • Application1部署在domain1上并使用数据库Database1
  • Application2部署在domain2上,并使用数据库Database2
  • Application1通过远程EJB与Application2通信 会话bean
另一种观点
  • 玻璃鱼4.0
    • 域1
      • 应用程序1数据库1
        • 应用程序1 ejb
        • 应用1战争
    • 域2
      • 应用程序2数据库2
        • 应用程序2 ejb
        • 应用2战争
环境
  • 我们正在使用Glassfish 4.0
  • 我们使用JDK7/JEE7在 玻璃鱼
  • 我们在应用程序中使用EclipseLink实现持久性,I 已启用eclipse日志来检查日志中的请求
  • 我们对这两个数据库都使用MySQL
  • 我们使用XADataSource能够在这两个服务器上执行请求 同一事务中的数据库

我正在使用的测试用例
  • 来自Application1WAR的托管bean从Application1EJB调用本地会话bean(当用户在浏览器中执行操作时)
  • 来自Application1EJB的本地会话bean将调用来自Application2EJB的远程会话bean
  • Application2EJB中的远程会话bean将在数据库数据库2中持久化一个实体:
    em.persist(entity2)
  • application1ejb中的本地会话bean将在数据库数据库1中持久化一个实体:
    em.persist(entity1)
  • 不知何故,它应该与我们使用的“XADataSource”是同一个事务。
    因此,如果出于任何原因发生运行时异常,则不应持久化实体

    问题 第一次调用Application1 ejb的方法时,它会工作:

    • Application2将实体持久化到数据库2中
    • Application1将实体持久化到数据库1中
    这些请求可以在日志中看到,我可以在Database1和Database2中看到新的实体

    下次调用Application1 ejb的方法时,它将不起作用:

    • Application1可以调用Application2,但即使Application2调用了
      em.persist(entity2)
      ,它也不会将实体持久化到数据库2中
    • Application1将实体持久化到数据库1中
    请求可以在应用程序1的日志中看到,但在应用程序2的日志中看不到任何请求

    新实体可以在数据库1中看到。
    但在数据库中看不到新实体2。
    在浏览器中,服务器似乎没有向客户端提供任何响应

    我试过几种方法。。。
    • 在较新的Glassfish(4.0到5.0)上部署projets:问题仍然存在
    • 更新MySQL的Java连接器(5.1.23到5.1.45):问题仍然存在
    • 更新EclipseLink(2.5到2.5.2):问题仍然存在
    冬眠 如果我使用Hibernate而不是EclipseLink,它将按预期工作。但是迁移到Hibernate不是我们现在能负担得起的,因为我们必须迁移大型JEE应用程序

    em.flush() 如果我在
    em.persist(entity2)
    之后强制Application2EJB刷新,它每次都会工作,并且浏览器总是收到来自服务器的响应

    但是如果我刷新,这意味着如果在某一点发生异常,一个实体将被持久化到Database2(因为刷新),而没有实体将被持久化到Database1(因为异常),这不是我们想要的


    生成问题的一些代码 Application1/SessionBean.java

    package application1.sessionbeans;
    
    import application1.entities.Entity1;
    import javax.ejb.EJB;
    import javax.ejb.Stateless;
    import application2.sessionbeans.remote.SessionBeanRemote;
    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    
    @Stateless
    public class SessionBean implements SessionBeanLocal {
    
        @EJB(name = "SessionBeanRemote-ejbref")
        private SessionBeanRemote sessionBeanRemote;
    
        @PersistenceContext
        private EntityManager em;
    
        @Override
        public void test() {
            System.out.println("SessionBean Application1");
            em.persist(new Entity1());
            sessionBeanRemote.test();
        }
    }
    
    package application2.sessionbeans;
    
    import application2.entities.Entity2;
    import application2.sessionbeans.remote.SessionBeanRemote;
    import javax.ejb.Stateless;
    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    
    @Stateless
    public class SessionBean implements SessionBeanRemote {
    
        @PersistenceContext
        private EntityManager em;
    
        @Override
        public void test() {
            System.out.println("sessionBean Application2");
            em.persist(new Entity2());
        }
    }
    
    Application1/glassfish-ejb-jar.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE glassfish-ejb-jar PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 EJB 3.1//EN" "http://glassfish.org/dtds/glassfish-ejb-jar_3_1-1.dtd">
    <glassfish-ejb-jar>
        <enterprise-beans>
            <ejb>
                <ejb-name>SessionBean</ejb-name>
                <jndi-name>java:global/EnterpriseApplication1/EnterpriseApplication1-ejb/SessionBean</jndi-name>
                <ejb-ref>
                    <ejb-ref-name>SessionBeanRemote-ejbref</ejb-ref-name>
                    <jndi-name>corbaname:iiop:localhost:4537#java:global/EnterpriseApplication2/EnterpriseApplication2-ejb/SessionBean</jndi-name>
                </ejb-ref>
            </ejb>
        </enterprise-beans>
    </glassfish-ejb-jar>
    
    Application2/persistence.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="EnterpriseApplication1-ejbPU" transaction-type="JTA">
            <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
            <jta-data-source>aEnercomDS</jta-data-source>
            <exclude-unlisted-classes>false</exclude-unlisted-classes>
            <properties>
                <property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
            </properties>
        </persistence-unit>
    </persistence>
    
    <?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="EnterpriseApplication2-ejbPU" transaction-type="JTA">
            <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
            <jta-data-source>AEnercomCollectData-DS</jta-data-source>
            <exclude-unlisted-classes>false</exclude-unlisted-classes>
            <properties>
                <property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
            </properties>
        </persistence-unit>
    </persistence>
    

    我试图使这个例子尽可能简单

    这里是否有人能够在不同的Glassfish域之间保持实体而没有任何问题


    persistence.xml中是否缺少一个属性来实现此功能?

    “但如果我刷新,这意味着如果某个点发生异常,则将在Database2中持久化一个实体(因为刷新),而在Database1中不会持久化任何实体(因为异常),这不是我们想要的——为什么会发生?刷新与设置transactionYes不同,但刷新会导致实体管理器写入数据库。我还可以说,当Application1和Application2应用程序位于同一个Glassfish域上时,一切都按预期工作。在数据库中写入与提交事务仍然不同。这就是拥有一个事务的全部意义,能够向数据库发出多个写语句,并且仍然能够在出现任何错误时回滚它们。换句话说,如果您使用flush解决方案,您应该很好您应该设置一个更精细的日志级别,以找出日志中可能出现的错误。不需要刷新,但奇怪的是,您的方法返回时不会抛出错误或出现问题的迹象。@crizzis我完全同意,但似乎我已经找到了刷新后无法正确回滚的原因。我们使用MyISAM作为MySQL的默认存储引擎。我刚刚对InnoDB做了相同的测试,如果我在
    em.flush()
    ”之后抛出异常,那么这次回滚确实会发生。但是如果我flush,这意味着如果在某一点上发生异常,一个实体将被持久化到Database2中(因为flush),而没有实体将被持久化到Database中
    package application2.sessionbeans.remote;
    
    import javax.ejb.Remote;
    
    @Remote
    public interface SessionBeanRemote {
    
        public void test();
    
    }