jpa-2.0 – JPA – 只有第一次提交失败,但应该全部失败
请有人帮我解释以下(对我来说)非常奇怪的JPA行为.我故意更改JPA中禁止的实体的主键.
所以首先提交正确抛出“异常描述:类[some.package.Holiday]的属性[date]被映射到数据库中的主键列.不允许更新.” 但第二(第三,第四,……)成功……!这怎么可能?! Holiday h1 = EM.find(Holiday.class,new GregorianCalendar(2011,3).getTime()); try { EM.getTransaction().begin(); h1.setDate(new GregorianCalendar(2011,4).getTime()); EM.getTransaction().commit(); System.out.println("First commit succeed"); } catch (Exception e) { System.out.println("First commit failed"); } try { EM.getTransaction().begin(); EM.getTransaction().commit(); System.out.println("Second commit succeed"); } catch (Exception e) { System.out.println("Second commit failed"); } 它将打印输出: First commit failed Second commit succeed 天哪,这怎么可能?! (在MySQL中使用EclipseLink 2.2.0.v20110202-r8913.) 解决方法
第一个事务的提交操作失败与第二个事务无关.这是因为当第一次提交失败时,EntityTransaction不再处于活动状态.当您发出第二个em.getTransaction().begin invocation时,将启动一个不知道第一个事务的新事务.
值得注意的是,尽管您的代码在两种情况下都可以使用相同的EntityTransaction引用,但此类实际上不必代表该事务.对于EclipseLink,EntityTransaction引用实际上包装了一个进一步使用RepeatableUnitOfWork的EntityTransactionWrapper实例,后两个类由EclipseLink实现而不是JPA提供. RepeatableWriteUnitOfWork实例实际上跟踪将合并到共享缓存(和数据库)的实体所做的更改集合.当第一个事务失败时,底层UnitOfWork无效,并在启动第二个EntityTransaction时建立新的UnitOfWork. 这同样适用于大多数其他JPA提供程序,因为EntityTransaction类不是具体的最终类.相反,它是一个通常由JPA提供程序中的另一个类实现的接口,它可能同样包装一个事务,从而要求客户端使用EntityTransaction引用而不是直接使用底层事务(可能是JTA事务或资源本地交易). 另外,你应该记住: > EntityTransaction.begin()只应调用一次.再次调用它将导致抛出IllegalStateException异常,因为当事务处于活动状态时无法调用它.因此,您可以第二次调用它,这意味着第一个事务不再处于活动状态.>如果您要求在第一个事务的上下文中执行的更改可用于第二个事务,则必须在第一个事务分离之后将实体合并回第二个事务中的共享上下文.虽然这可能听起来很荒谬,但您应该记住,在合并之前,客户端(读取,最终用户)可以修改分离的实体,因此最终用户所做的更改可能会被保留,而错误(如修改)可以在过渡期间纠正主键. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |