JPA:Eclipselink不尊重em.remove()

Osw*_*Osw 5 ejb jpa glassfish eclipselink

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

@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();
  }
}
Run Code Online (Sandbox Code Playgroud)

如果我留下em.flush()评论,那么我得到com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException(新旧对象具有相同的键值)

这种异常行为可能是什么原因?

服务器:Glassfish 3.1.2

Eclipse Persistence Services - 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>
Run Code Online (Sandbox Code Playgroud)

连接池:

${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
Run Code Online (Sandbox Code Playgroud)

Mat*_*ndy 6

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

默认情况下,EclipseLink会在删除操作之前首先插入和更新操作,以确保维护参照完整性.这是首选方法.

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

如果通过删除对象并插入替换来强制替换具有唯一约束的对象,则在删除操作之前插入操作发生时可能会导致约束违规.在这种情况下,调用setShouldPerformDeletesFirst以在插入操作之前执行删除操作.