-->

TransactionAttribute.REQUIRES_NEW in JPA

2020-07-24 06:49发布

问题:

I tested my ejb jpa transactions. I use Container-managed entityManager:

@PersistenceContext(unitName = "ParticularUnit")
EntityManager em;

Such I has got transaction PersistanceContext scope and container manages each transaction. For each instance of pooled session beans, created instance of entityManager. When I mark bean method with @TransactionAttribute(TransactionAttributeType.REQUIRED) and invoke two method within, I expected then method test1 will have another PersitenceContext, but I was surprised, because it was the same.

@TransactionAttribute(TransactionAttributeType.REQUIRED)

public void test(Configuration config){
        if (!em.contains(config)) {
            config = em.find(Configuration.class, config.getId());
        }
        System.out.println("********************");
        System.out.println("actiovation, em= "+ em);
        System.out.println("actiovation, config= "+ config);
        System.out.println("*********************");

        test1(config);
        test2(config);
    }

    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void test1(Configuration config){
        config = em.find(Configuration.class, config.getId());
        System.out.println("////////");
        System.out.println("requires_new"+ config);
        System.out.println("requires_new, em= "+ em);
        System.out.println("----------------");
    }

    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void test2(Configuration config){
        config = em.find(Configuration.class, config.getId());
        System.out.println("////////");
        System.out.println("required"+ config);
        System.out.println("required, em= "+ em);
        System.out.println("----------------");
    }

I call test and got this trace.

********************
 actiovation, em= JPATxEntityManager@54515451
 actiovation, config= com.profix.sc.db.configuration.Configuration@7f287f28
 *********************
 ////////
 requires_newcom.profix.sc.db.configuration.Configuration@7f287f28
 requires_new, em= JPATxEntityManager@54515451[PuId=SCApplication#SCApplication-ejb.jar#SCApplication, SCApplication#SCApplication-ejb.jar#PaymentConfigBean#com.profix.sc.ejb.PaymentConfigBean/em]
----------------
  ////////
    requiredcom.profix.sc.db.configuration.Configuration@7f287f28
  required, em= JPATxEntityManager@54515451[PuId=SCApplication#SCApplication-ejb.jar#SCApplication, SCApplication#SCApplication-ejb.jar#PaymentConfigBean#com.profix.sc.ejb.PaymentConfigBean/em]

Why within test1() persistenceContext is the same as in test()?

回答1:

I guess that you're not invoking a business method at all. You're invoking local call (implicit 'this') - not the EJB one.

Try doing this call by using a business interface.

Try changing the calls to test1() and test2() in your test() class from:

test1(config);
test2(config);

to

getBusinessObject(YourEJB.class).test1(config);
getBusinessObject(YourEJB.class).test2(config);

PS. I'm not sure about that, but the container can use proxy object for EntityManager, so try testing if you're really in the same PersistenceContext (by doing some operations rather than just calling it's reference)