【问题标题】:JPA Transactions on InformixInformix 上的 JPA 事务
【发布时间】:2013-03-26 20:43:55
【问题描述】:

我需要在 Java SE 7.0 环境中使用 JPA 2.0 和 EclipseLink 3.0 更新表,使用非事务性 Informix DB v. 11.50,persistence.xml 是:

<persistence-unit name="pp_pu" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <class>...</class>
    <class>...</class>
    <properties>
        <property name="javax.persistence.jdbc.url"
                  value="jdbc:informix-sqli://10.191.78.230:40494/ptpr:informixserver=online_ptpr"/>
        <property name="javax.persistence.jdbc.driver" value="com.informix.jdbc.IfxDriver"/>
        <property name="javax.persistence.jdbc.user" value="test"/>
        <property name="javax.persistence.jdbc.password" value="test"/>
    </properties>
</persistence-unit>

当我尝试进行更新时,我收到以下错误:

Exception in thread "main" javax.persistence.TransactionRequiredException: 
Exception Description: No transaction is currently active
    at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionWrapper.throwCheckTransactionFailedException(EntityTransactionWrapper.java:113)
    at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionWrapper.checkForTransaction(EntityTransactionWrapper.java:50)
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.checkForTransaction(EntityManagerImpl.java:1776)
    at org.eclipse.persistence.internal.jpa.EJBQueryImpl.executeUpdate(EJBQueryImpl.java:533)

然后我尝试使用以下方法解决错误:

em.getTransaction().begin();
// Update query
em.getTransaction().commit();

现在我收到以下错误:

Internal Exception: java.sql.SQLException: Transactions not supported
Error Code: -79744
Exception in thread "main" Local Exception Stack: 
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: Transactions not supported
Error Code: -79744
Query: DataModifyQuery(sql="update tg_proteccion_cv
set i_eq_validados=?,
    i_eq_a_protegidos=?
where v_id_proteccion=?
    and v_cve_cliente=?")
    at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:324)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicBeginTransaction(DatabaseAccessor.java:230)
    at org.eclipse.persistence.internal.databaseaccess.DatasourceAccessor.beginTransaction(DatasourceAccessor.java:239)
    at org.eclipse.persistence.internal.sessions.AbstractSession.basicBeginTransaction(AbstractSession.java:479)
    at org.eclipse.persistence.sessions.server.ClientSession.addWriteConnection(ClientSession.java:646)
    at org.eclipse.persistence.sessions.server.ServerSession.acquireClientConnection(ServerSession.java:246)
    at org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:226)
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:207)
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:193)
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeNoSelectCall(DatasourceCallQueryMechanism.java:236)
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeNoSelect(DatasourceCallQueryMechanism.java:216)
    at org.eclipse.persistence.queries.DataModifyQuery.executeDatabaseQuery(DataModifyQuery.java:85)
    at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:829)
    at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:728)
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2863)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1501)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1483)
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1457)
    at org.eclipse.persistence.internal.jpa.EJBQueryImpl.executeUpdate(EJBQueryImpl.java:540)
    at com.telcel.gsa.dsiee.pprecios.amb_alt.FixProtsCv.updateCV(FixProtsCv.java:70)
    at com.telcel.gsa.dsiee.pprecios.amb_alt.FixProtsCv.fix(FixProtsCv.java:88)
    at com.telcel.gsa.dsiee.pprecios.amb_alt.FixProtsCv.main(FixProtsCv.java:42)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: java.sql.SQLException: Transactions not supported
    at com.informix.util.IfxErrMsg.getSQLException(IfxErrMsg.java:348)
    at com.informix.jdbc.IfxSqliConnect.setAutoCommit(IfxSqliConnect.java:1333)
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicBeginTransaction(DatabaseAccessor.java:223)
    ... 25 more

使用 JDBC 进行更新没有问题,¿JPA 是否支持非事务数据库? 出于性能原因,DBA 已关闭 Informix 上的事务支持,这不会改变。 那么,我有什么遗漏吗?怎么了?

P.D. 我使用启用事务的 Informix DB 进行了相同的更新,并且它可以工作。

【问题讨论】:

  • 悄悄地扭动 DBA 的手臂,直到他将事务放回 DB。没有事务就工作是不明智的。
  • 您遇到的错误看起来像是尝试在没有事务的数据库上执行事务(BEGIN、COMMIT)的后果。就好像persistence.xml 描述没有认识到没有交易的可能性。标准(Informix 级别)错误包括: -255:不在事务中(当没有事务处于活动状态时提交事务数据库); -256:事务不可用(在非事务数据库上开始或提交)。你如何解决这个我不确定。最好使用事务数据库,但这似乎不是一个选择。直觉:JPA 不适用于此。

标签: java jpa eclipselink informix


【解决方案1】:

最终的工作示例(由 James 建议)是:

public class Test {


    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("pp_pu");
        EntityManager em = emf.createEntityManager();

        Session session = em.unwrap(Session.class);
        session.getLogin().useExternalTransactionController();


        em.getTransaction().begin();
        int updates = em.createNamedQuery("CgEstatusEntity.updateById")
                .setParameter("iCveEstatus", 1)
                .setParameter("vDescEstatus", "Test9")
                .executeUpdate();
        System.out.println(updates);

        em.getTransaction().commit();

    }


}

【讨论】:

    【解决方案2】:

    禁用事务支持很奇怪。

    使用 EclipseLink,您可以使用 SessionCustomizer 禁用事务,

    session.getLogin().useExternalTransactionController();
    

    这将使 EclipseLink 在管理事务(通常是 JTA)方面考虑其他事情,但在你的情况下,什么都没有......

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-12
      • 2018-03-10
      • 2013-04-10
      • 2019-11-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多