Java openjpa2.0如何在运行时增强实体?

Java openjpa2.0如何在运行时增强实体?,java,orm,jpa,openjpa,Java,Orm,Jpa,Openjpa,下面是我的测试代码: package jee.jpa2; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.Persistence; import javax.persistence.Qu

下面是我的测试代码:

package jee.jpa2;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import javax.persistence.Query;

import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@Test
public class Tester {
    EntityManager em;
    EntityTransaction tx;
    EntityManagerFactory emf;

    @BeforeClass
    public void setup() {
        emf = Persistence.createEntityManagerFactory("basicPU", System.getProperties());
    }

    @Test
    public void insert() {
        Item item = new Item();
        for (int i = 0; i < 1000; ++i) {
            em = emf.createEntityManager();
            tx = em.getTransaction();
            tx.begin();
            item.setId(null);
            em.persist(item);
            tx.commit();
            em.clear();
            em.close();
            tx=null;
            em=null;
        }
    }

    @Test
    public void read() {
        em = emf.createEntityManager();
        tx = em.getTransaction();
        tx.begin();
        Query findAll = em.createNamedQuery("findAll");
        List<Item> all = findAll.getResultList();
        for (Item item : all) {
            System.out.println(item);
        }
        tx.commit();
    }
}
执行测试后,我得到一个错误:

Item [id=1, name=Digambar]
Item [id=2, name=Digambar]
PASSED: read
FAILED: insert
<openjpa-2.0.0-r422266:935683 nonfatal store error> org.apache.openjpa.persistence.EntityExistsException: Attempt to persist detached object "jee.jpa2.Item-2".  If this is a new instance, make sure any version and/or auto-generated primary key fields are null/default when persisting.
FailedObject: jee.jpa2.Item-2
    at org.apache.openjpa.kernel.BrokerImpl.persist(BrokerImpl.java:2563)
    at org.apache.openjpa.kernel.BrokerImpl.persist(BrokerImpl.java:2423)
    at org.apache.openjpa.kernel.DelegatingBroker.persist(DelegatingBroker.java:1069)
    at org.apache.openjpa.persistence.EntityManagerImpl.persist(EntityManagerImpl.java:705)
    at jee.jpa2.Tester.insert(Tester.java:33)
Item[id=1,name=Digambar]
项目[id=2,名称=Digambar]
通过:阅读
失败:插入
org.apache.openjpa.persistence.EntityExistsException:尝试持久化分离的对象“jee.jpa2.Item-2”。如果这是一个新实例,请确保任何版本和/或自动生成的主键字段在持久化时为null/default。
失败对象:jee.jpa2.Item-2
位于org.apache.openjpa.kernel.BrokerImpl.persist(BrokerImpl.java:2563)
位于org.apache.openjpa.kernel.BrokerImpl.persist(BrokerImpl.java:2423)
位于org.apache.openjpa.kernel.DelegatingBroker.persist(DelegatingBroker.java:1069)
位于org.apache.openjpa.persistence.EntityManagerImpl.persistent(EntityManagerImpl.java:705)
在jee.jpa2.Tester.insert(Tester.java:33)中

请解释一下这里发生了什么?

你有没有看过源代码?它深入内核的内部:


第2563行

OpenJPA2.0可以在JDK1.6(非JRE)上运行时动态安装运行时增强器。从技术上讲,它们使用动态连接java代理,而不需要
-javaagent
选项


因此,
Item
类实际上得到了增强,实体管理器知道,尽管存在
null
id并关闭了实体管理器,它仍在持久化一个分离的实例。

严格地回答问题标题,运行时增强是使用javaagent完成的,在使用JDK 1.6时可以动态加载javaagent(这记录在中)

关于您面临的问题,我怀疑这是一个OpenJPA错误(我见过一些类似的问题,例如),错误消息与您的代码不一致,因为您将主键字段设置为
null
,并且没有任何版本字段。您应该报告它

也就是说,解决这个问题的一个简单方法是在循环中创建一个新的
实例

public void insert() {
    for (int i = 0; i < 1000; ++i) {
        Item item = new Item();
        em = emf.createEntityManager();
        tx = em.getTransaction();
        tx.begin();
        em.persist(item);
        tx.commit();
        em.clear();
        em.close();
        tx=null;
        em=null;
    }
}
更新:回答评论。来自JPA规范:

3.2实体实例的生命周期 本节介绍了 用于管理的EntityManager操作 实体实例的生命周期 可以对实体实例进行特征化 作为新的、管理的、独立的或 删除

  • 新的实体实例没有持久标识,并且还没有持久标识 与持久性上下文关联
  • 托管的实体实例是具有持久标识的实例 当前与 持久性上下文
  • 分离的实体实例是具有持久标识的实例 没有(或不再)关联的 具有持久性上下文
  • 删除的实体实例是具有持久标识的实例, 与持久性上下文关联, 已计划从系统中删除 数据库

因此,如果您有一个分离的实体(因此不与持久性上下文关联),并且如果您将
Id
注释字段设置为
null
(因此没有持久性标识)然后,您完全可以将规范定义为新实体,而不管OpenJPA行为。这就是为什么我认为这是OpenJPA中的一个错误(并且错误消息无论如何是不相干的)。

< P>错误消息告诉您问题是什么。 尝试持久化分离的对象“jee.jpa2.Item-2”


在第一个循环中持久化实体后,对em.persist(..)的所有后续调用实际上是传入一个分离的实体(不是新实体)。将id字段设置为NULL并不意味着该实体现在是新的。

请注意,“实体管理器通过Java对象引用跟踪实体。”

当且仅当我在for循环中移动
emf=Persistence.createEntityManagerFactory(“BasicCPU”)
语句时,我才能在for循环中一次又一次地持久化相同的java对象/引用。 像这样:

清单1:

Item item = new Item(); 
    for (int i = 0; i < 1000; ++i) { 
        emf = Persistence.createEntityManagerFactory("basicPU");            
        em = emf.createEntityManager();         
        tx = em.getTransaction();
        tx.begin(); 
        item.setId(null); 
        em.persist(item); 
        tx.commit();
        em.clear();
        em.close(); 
    } 
Item item = new Item(); 
    emf = Persistence.createEntityManagerFactory("basicPU");     
    for (int i = 0; i < 1000; ++i) { 
        em = emf.createEntityManager();         
        tx = em.getTransaction();
        tx.begin(); 
        item.setId(null); 
        em.persist(item); 
        tx.commit();
        em.clear();
        em.close(); 
    } 
这意味着emf.createEntityManager()总是返回entityManager的新实例。

因此,在清单1和清单2中,我总是得到新的EntityManager实例,而在清单1中,我仍然可以在数据库中保留相同的对象,但在清单2中,我得到EntityExistException。为什么呢?


我想如果我在两个清单(1和2)中都有新的EntityManager我应该能够在数据库中持久化同一个对象,因为EntityManager通过java对象引用跟踪实体,在每次迭代中我都有新的EntityManager,它不知道或不应该知道其他EntityManager对象实例在上一次迭代中保存/持久化在数据库中的对象引用。

在我设置prim之后ary key NULL;为什么我在新的EntityManager和事务上下文中得到EntityExistsException。?第一个答案是+1,第二个答案是-1。这不是一个错误……我认为这是对OpenJPA工作原理的理解不足。我不相信规范中说将ID字段设置为NULL会将分离的实体转换到任何地方的新实例。这就是对规范的解释。@Rick是的,这是一种解释,我不建议依赖这种解释(我确实认为从分离到新的转换是不正确的)。问题是规范没有关闭这扇门(规范中应该没有解释的空间)。但无论如何,错误消息可以改进。但我正在将同一个实体传递给新的entityManager,它不知道该实体是否已持久化?当OpenJPA增强实体时,它会在封面下添加一个字段,跟踪状态(这应该允许更有效的entityManager.merge(…)操作)。当您将另一个EntityManager持久化的实例传递给新实例时,新EM
Item item = new Item(); 
    for (int i = 0; i < 1000; ++i) { 
        emf = Persistence.createEntityManagerFactory("basicPU");            
        em = emf.createEntityManager();         
        tx = em.getTransaction();
        tx.begin(); 
        item.setId(null); 
        em.persist(item); 
        tx.commit();
        em.clear();
        em.close(); 
    } 
Item item = new Item(); 
    emf = Persistence.createEntityManagerFactory("basicPU");     
    for (int i = 0; i < 1000; ++i) { 
        em = emf.createEntityManager();         
        tx = em.getTransaction();
        tx.begin(); 
        item.setId(null); 
        em.persist(item); 
        tx.commit();
        em.clear();
        em.close(); 
    } 
emf = Persistence.createEntityManagerFactory("basicPU");
        for (int i = 0 ; i<10; i++){
                System.out.println(emf.createEntityManager());
        }
org.apache.openjpa.persistence.EntityManagerImpl@18105e8
org.apache.openjpa.persistence.EntityManagerImpl@9bad5a
org.apache.openjpa.persistence.EntityManagerImpl@91f005
org.apache.openjpa.persistence.EntityManagerImpl@1250ff2
org.apache.openjpa.persistence.EntityManagerImpl@3a0ab1
org.apache.openjpa.persistence.EntityManagerImpl@940f82
org.apache.openjpa.persistence.EntityManagerImpl@864e43
org.apache.openjpa.persistence.EntityManagerImpl@17c2891
org.apache.openjpa.persistence.EntityManagerImpl@4b82d2
org.apache.openjpa.persistence.EntityManagerImpl@179d854