JPA:Eclipselink不尊重em.remove()

JPA:Eclipselink不尊重em.remove(),jpa,glassfish,ejb,eclipselink,Jpa,Glassfish,Ejb,Eclipselink,我需要删除一个实体并创建另一个实体: @Stateless public class StatelessBean { @PersistenceUnit(unitName = "Unit001") EntityManagerFactory emf; protected void test() { EntityManager em = emf.createEntityManager(); MyObj obj1 = em.find(MyObj.class, 100);

我需要删除一个实体并创建另一个实体:

@Stateless
public class StatelessBean {
  @PersistenceUnit(unitName = "Unit001")
  EntityManagerFactory emf;

  protected void test() {
    EntityManager em = emf.createEntityManager();
    MyObj obj1 = em.find(MyObj.class, 100);
    MyObj obj2 = new MyObj();
    obj2.setKey("the same unique key as in obj1");
    em.remove(obj1);
    // em.flush(); 
    em.persist(obj2); // works fine when flush() is uncommented
    em.close();
  }
}
如果我对
em.flush()
进行注释,那么我会得到
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException
(新对象和旧对象的键值相等)

这种反常行为的原因是什么

服务器:Glassfish 3.1.2

Eclipse持久性服务-2.3.2.v20111125-r10461

persistence.xml:

<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
  <persistence-unit name="Unit001">
    <jta-data-source>jdbc/Unit001DS</jta-data-source>
    <properties>
      <property name="eclipselink.logging.level" value="INFO"/>
      <property name="eclipselink.target-database" value="MySQL"/>
    </properties>
  </persistence-unit>
</persistence>

原因可能是Eclipselink在提交期间更改了操作顺序,如中所述:

默认情况下,EclipseLink在删除操作之前首先插入和更新操作,以确保保持引用完整性。这是首选方法

您可以通过刷新(正如您已经发现的)或为Eclipselink设置特殊参数来更改此行为:

如果强制使用唯一约束替换对象,则 删除它并插入替换,可能会导致约束 如果插入操作发生在删除操作之前,则违反。 在这种情况下,请调用
setshouldperformedelectesfirst
执行删除操作 插入操作之前的操作


EclipseLink维护并优化提交顺序,以:

1-维护引用完整性约束:如果插入两个相关对象(或多个对象的一个大型互连图),则必须以非常特定且不明显的顺序插入/更新/删除它们,以维护引用完整性约束。在某些情况下,甚至可能需要插入shell对象并在解析循环依赖关系后更新其外键。删除必须在最后发生,因为用于引用已删除对象的对象必须首先更新关系

2-组操作和表访问:这避免了数据库死锁,并允许最佳使用批写入

3-按id一致地排序更新/删除:这是可配置的,避免了潜在的数据库死锁


如果EclipseLink只是盲目地按照应用程序执行的顺序编写,那么您必须自己管理所有这些。我真的怀疑你是否真的想这么做。对于您真正需要的情况,您可以使用flush()。

谢谢,但是
其他JPA实现以同样的方式来实现它对我来说有点可疑-同一个项目作为JPA提供者运行
Hibernate
绝对很好。您可能是对的,我不确定,请在另一篇文章中阅读。将编辑我的答案。是否有任何配置选项可以强制eclipselink以java代码流的形式生成sql?我的时间很短,希望有一个与hibernate兼容的解决方案,而不只是调整sql删除。我不知道任何问题(除了
flush
)。谢谢,因为问题已经得到了回答,所有其他问题都是不同的。对不起,我不相信。我们谈论的是JPA实现,不是AI,不是吗?必须以某种方式尊重
EntityManager
调用流,否则我的所有事务都将以两个无序集合结束-
toPersist
toDelete
。如果我在这一行代码中说
remove
,这对JPA提供商来说应该意味着什么。我说得对吗?
${ASADMIN} --port ${DOMAIN_ADMIN_PORT}  create-jdbc-connection-pool --datasourceclassname com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource --restype javax.sql.ConnectionPoolDataSource --property "User=user:Password=pass:URL=jdbc\:mysql\://${DB_ADDRESS}/db" Unit001DS
${ASADMIN} --port ${DOMAIN_ADMIN_PORT}  create-jdbc-resource --connectionpoolid Unit001DS jdbc/Unit001DS