是不是应该与em.getTransaction()一致的多个事务?

sim*_*ico 7 java transactions derby eclipselink jpa-2.0

当我执行:

public void beginTransaction() {
    em.getTransaction().begin();
}
Run Code Online (Sandbox Code Playgroud)

在以相同方式启动活动事务之后,我得到以下异常:

Exception Description: Transaction is currently active
java.lang.IllegalStateException: 
Exception Description: Transaction is currently active
        at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.begin(EntityTransactionImpl.java:45)
        at com.mysimpatico.memoplatform.persistence.Database.beginTransaction(Database.java:44)
        at com.mysimpatico.memoplatform.persistence.tests.PersistenceTest.setUp(PersistenceTest.java:39)
Run Code Online (Sandbox Code Playgroud)

底层DBMS是嵌入式apache derby,据我所知,它不支持来自不同JVMS的多个连接,但是支持并发事务.文档

此测试代码失败:

public <Entity> int getNo(final Class<Entity> entityClass) {
    final CriteriaBuilder qb = em.getCriteriaBuilder();
    final CriteriaQuery<Long> cq = qb.createQuery(Long.class);
    cq.select(qb.count(cq.from(entityClass)));
    final int ret = em.createQuery(cq).getSingleResult().intValue();
    return ret;
}

protected void insertWords(final List<String[]> expressionDefTriples, MUser usr, final MeaningsDatabase mengsDB) throws Exception {
    for (String[] expressionDefTriple : expressionDefTriples) {
        mengsDB.persistSynonyms(MeaningsDatabase.toEnumMap(expressionDefTriple, usr));
        testSynonymsPersistance(expressionDefTriple,mengsDB);
    }
}

protected void testSynonymsPersistance(final String[] expDefTriple, final MeaningsDatabase mengsDB) {
    final Expression exp = mengsDB.get(Expression.class, expDefTriple[0]);
    testGender(exp, expDefTriple[2]);
    final Expression def = mengsDB.get(Expression.class, expDefTriple[1]);
    assertNotNull(def);
    assertTrue(exp.getMengs().size() > 0);
    assertTrue(def.getMengs().size() > 0);
    assertTrue(mengsDB.getNo(Meaning.class) > 0); //fails here
}

public void persistSynonyms(final EnumMap<Input, MemoEntity> input) throws MultipleMengsException {
    final Expression def = extractExp(input, Input.definition);
    final Expression exp = extractExp(input, Input.expression);
    final MUser usr = extractUsr(input);

    beginTransaction();
    final Meaning meng = persistMeng(exp, usr, def);
    commitTransaction();
    signalContentAvailability();
    logInsertion(meng, exp, def);
}
Run Code Online (Sandbox Code Playgroud)

本质上我在同一个em中启动并提交一个事务,但是当我使用相同的em执行getNo()方法时,它找不到前一个提交的内容.我没有看到问题出在哪里.显然存在一个问题,因为像em.find(..)这样的"本地"代码会找到已提交的更改,但不会查找条件查询.

Pas*_*ent 7

EntityManager#getTransaction()实际上返回 当前资源本地事务,你不能说EntityTransaction#begin()当一个事务已经被激活:

/**
* Start a resource transaction.
* @throws IllegalStateException if isActive() is true
*/
public void begin();
Run Code Online (Sandbox Code Playgroud)

您可以做的是创建串行本地事务,如javadoc中所示EntityManager#getTransaction():

/**
 * Return the resource-level <code>EntityTransaction</code> object.
 * The <code>EntityTransaction</code> instance may be used serially to
 * begin and commit multiple transactions.
 * @return EntityTransaction instance
 * @throws IllegalStateException if invoked on a JTA
 *         entity manager
 */
public EntityTransaction getTransaction();
Run Code Online (Sandbox Code Playgroud)

总而言之,JPA(和JTA)不支持嵌套事务.

参考