【问题标题】:JPA: Outside container transaction not committingJPA:外部容器事务未提交
【发布时间】:2016-03-31 12:22:32
【问题描述】:

我正在为我的应用程序测试 JPA。

与数据库的连接似乎成功,

Running com.vgorcinschi.rimmanew.ejbs.OutsideContainerJpaTests 
[EL Info]: 2015-12-25 07:32:26.202--ServerSession(1302779492)--EclipseLink, version: Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd
[EL Info]: connection: 2015-12-25 07:32:26.493--ServerSession(1302779492)--file:/home/vgorcinschi/NetBeansProjects/RimmaNew/target/classes/_outsideContainer login successful

但数据没有持久化。

因为我的应用程序在 GlassFish 上运行并且我正在容器外尝试 JUnit 测试,所以我创建了第二个持久性单元。这是 persistence.xml 文件中的内容(请注意,我已将我的凭据隐藏到数据库):

<persistence-unit name="outsideContainer" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
        <property name="javax.persistence.schema-generation.database.action" value="create"/>
        <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
        <property name="javax.persistence.jdbc.url"
                  value="jdbc:mysql://127.0.0.1:3306/beaty_shop?zeroDateTimeBehavior=convertToNull"/>
        <property name="javax.persistence.jdbc.user" value="**********"/>
        <property name="javax.persistence.jdbc.password" value="*************"/>
    </properties>
</persistence-unit>

这是返回 EntityManagerFactory 的单例方法:

public static EntityManagerFactory getUniqueInstance() {
    if (uniqueInstance == null) {
        synchronized (EntityManagerFactoryProvider.class) {
            if (uniqueInstance == null) {
                uniqueInstance = Persistence.createEntityManagerFactory("outsideContainer");
            }
        }
    }
    return uniqueInstance;
}

这是存储库存根,它不会引发异常,但也不会将数据持久化到 DB。事务已启动并提交...

public class JpaAppointmentRepositoryStub implements AppointmentRepository {



  private EntityManagerFactory emf;

    public JpaAppointmentRepositoryStub(EntityManagerFactory emf) {
        this.emf = emf;
    }

    public JpaAppointmentRepositoryStub() {
    }

    @Override
    public void add(Appointment appointment) {
        EntityManager em = entityManagerFactory.createEntityManager();
        EntityTransaction trans = em.getTransaction();
        try {
            trans.begin();
            em.persist(appointment);
            trans.commit();
        } catch (Exception e) {
            trans.rollback();
        } finally {
            em.close();
        }
    }

    @Override
    public void update(Appointment appointment) {
        EntityManager em = entityManagerFactory.createEntityManager();
        em.merge(appointment);
    }

    @Override
    public Appointment get(long id) {
        EntityManager em = entityManagerFactory.createEntityManager();
        try {
            return em.find(Appointment.class, id);
        } catch (NoResultException e) {
            return null;
        } finally {
            em.close();
        }
    }


}

来自 EntityManager 的事务不为空:

@Test
public void aTransactionIsNotNull(){
    EntityManager em = entityManagerFactory.createEntityManager();
    EntityTransaction trans = em.getTransaction();
    assertNotNull(trans);
    em.close();
}

最后一条有趣且有用的信息是,Repository 正在由一个 Service 类“操作”,该 Service 类具有用于 Repository 的保存和更新操作的单一方法。所以唯一的缺点应该是在每次调用时打开和关闭两个实体管理器:

public class OutsideContainerAppointmentService implements AppointmentService{
private final AppointmentRepository repository;
...
@Override
    public void save(Appointment appointment) {
        if (findById(appointment.getId()) != null) 
            repository.update(appointment);
        else 
            repository.add(appointment);        
    }
...
}

MySQL Connector/J 在此 Maven 项目的测试依赖项中(但由于登录成功,这不是问题)。

那么你认为可能是什么问题?

【问题讨论】:

    标签: java maven jpa junit persistence


    【解决方案1】:

    即使它没有意义(至少到目前为止)正确的解决方案是这样。

    我已经添加了 .joinTransaction() 方法,一切都开始正常了。

        @Override
        public void add(Appointment appointment) {
            EntityManager em = entityManagerFactory.createEntityManager();
            EntityTransaction trans = em.getTransaction();
            trans.begin();
            try {
                    //this is the line that I have added                
                    em.joinTransaction();
                    em.persist(appointment);
                    trans.commit();
                } catch (Exception e) {
                    trans.rollback();
                } finally {
                    em.close();
                }
            }
    

    但根据JPA wiki 在这种情况下我不应该使用 .joinTransaction() :

    joinTransaction 仅用于 JTA 托管的 EntityManagers (JTA persistence.xml 中的事务类型)。对于 RESOURCE_LOCAL EntityManagers,您可以随时提交 JPA 事务 渴望。

    我必须修复的另一个“错误”是将appointmentService.save(dummy); 转移到 setUp() 方法之外和 @Test 注释方法内部。这就是我开始对数据库进行双重写入的原因。

    【讨论】:

      猜你喜欢
      • 2011-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-08
      • 1970-01-01
      • 2015-03-15
      • 2016-08-30
      • 2015-07-24
      相关资源
      最近更新 更多