Using Nativequery to delete/update records in JTA

社会主义新天地 提交于 2019-12-11 20:22:46

问题


I was stuck in very hard situation for a moment.

The problem is: I have to use NativeQuery to delete and/or update some DB records in a JTA context (EJB).

my JPA persistence.xml looks like:

<persistence-unit name="OzsscJPANBPU" transaction-type="JTA">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <jta-data-source>jdbc/postgres_ozssc</jta-data-source>
    <mapping-file>com/longz/ozssc/model/PostcodeEntity.xml</mapping-file>
    <class>com.longz.ozssc.model.CustomerEntity</class>
 ......

If I use delete statement in this way:

@Override
public void remove(SmsdOutboxEntity toberemoved){
    em.createNativeQuery("Delete from outbox where \"ID\" = " + toberemoved.getId()).executeUpdate();

TransactionRequiredException thrown:

root cause

javax.persistence.TransactionRequiredException: 
Exception Description: No transaction is currently active

Such there is no transaction existing.

If we use transaction manually as:

@Override
public void remove(SmsdOutboxEntity toberemoved){
    em.getTransaction().begin();
    em.createNativeQuery("Delete from outbox where \"ID\" = " + toberemoved.getId()).executeUpdate();
    /*em.flush();*/
    em.getTransaction().commit();

IllegalStateException thrown:

root cause

javax.ejb.EJBException: EJB Exception: ; nested exception is: 
java.lang.IllegalStateException: The method public abstract javax.persistence.EntityTransaction javax.persistence.EntityManager.getTransaction() cannot be invoked in the context of a JTA EntityManager.

Seems I can't use transaction manually, as JTA will manage transaction their self.

So my question is: How I can use Native Query to delete/update records in a JTA managed context?

Please advise.


回答1:


For JTA the transaction is provided by the container and you should not create it by yourself. To obtain the transaction in JTA, you have to access it as a resource:

@Resource public UserTransaction utx;
@Resource public EntityManagerFactory factory;

@Override
public void remove(SmsdOutboxEntity toberemoved){
   EntityManager em = factory.createEntityManager();
try {
   em.createNativeQuery("Delete from outbox where \"ID\" = " + toberemoved.getId()).executeUpdate();
   utx.commit();

catch (RuntimeException e) {
    if (utx != null) utx.rollback();
    throw e; // or display error message
}
finally {
    em.close();
}

If you want to omit the part where you have commit/rollback the transaction by yourself, you need to have your transaction managed by some container like EJB3. For that you can use stateless/stateful ejb beans.

UPDATE:

For WebLogic, try to use its user weblogic.transaction.UserTransaction instead of javax.transaction.UserTransaction. As the doc says:

This interface defines WebLogic-specific extensions to javax.transaction.UserTransaction.



来源:https://stackoverflow.com/questions/30179083/using-nativequery-to-delete-update-records-in-jta

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!