0

我很确定我对 JPA 不了解(我正在使用 OpenJPA)并且它导致了这个问题。我想复制一个 Job 实体。

@Entity
@Table(name="Job")
public class Job implements Serializable {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;

    @ManyToOne
    private Job job;

    @OneToMany(fetch = FetchType.EAGER)
    private Set<Job> jobCollection;
    ...

    public Job getJob() {
         return this.job;
    }

    public void setJob(Job job) {
         this.job = job;
    }

    public Set<Job> getCopies() {
         return this.jobCollection;
    }

    public void setCopies(Set<Job> jobCollection) {
         this.jobCollection = jobCollection;
    }
}

在创建第一个副本时,运行以下代码可以正常工作。

public void testCopyJob(){
    Job job = jobManager.findJobById(100);
    Job jobWithCopies = null;
    try {
        jobWithCopies = jobManager.copyJob(job, "test copy");
    } catch (Exception e) {
        fail(e.getMessage());
    }
    Set<Job> copies = jobWithCopies.getCopies();
    assertEquals("num copies", 1, copies.size());

    //make a second copy
    Job jobWithCopies2 = null;
    try {
        jobWithCopies2 = jobManager.copyJob(jobWithCopies, "test copy");
        assertEquals("multiple copies", 2, jobWithCopies2.getCopies().size());
    } catch (Exception e) {
        e.printStackTrace();
        fail(e.getMessage());
    }
}

尝试创建第二个副本失败并...

[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R <openjpa-1.2.1-SNAPSHOT-r422266:686069 fatal general error> org.apache.openjpa.persistence.PersistenceException: null
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:1688)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.openjpa.kernel.StateManagerImpl.assignObjectId(StateManagerImpl.java:523)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.openjpa.kernel.StateManagerImpl.assignField(StateManagerImpl.java:608)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.openjpa.kernel.StateManagerImpl.beforeAccessField(StateManagerImpl.java:1494)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.openjpa.kernel.StateManagerImpl.accessingField(StateManagerImpl.java:1477)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at entities.Job.pcGetid(Job.java)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at entities.Job.hashCode(Job.java:402)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at java.util.HashMap.putImpl(Unknown Source)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at java.util.HashMap.put(Unknown Source)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at java.util.HashSet.add(Unknown Source)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.openjpa.util.java$util$HashSet$proxy.add(Unknown Source)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at entities.controller.JobManager.copyJob(JobManager.java:140)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at entities.controller.JobManagerTest.testCopyJob(JobManagerTest.java:55)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:45)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at java.lang.reflect.Method.invoke(Method.java:599)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at junit.framework.TestCase.runTest(TestCase.java:154)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at junit.framework.TestCase.runBare(TestCase.java:127)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at junit.framework.TestResult$1.protect(TestResult.java:106)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at junit.framework.TestResult.runProtected(TestResult.java:124)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at junit.framework.TestResult.run(TestResult.java:109)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at junit.framework.TestCase.run(TestCase.java:118)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at junit.framework.TestSuite.runTest(TestSuite.java:208)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at junit.framework.TestSuite.run(TestSuite.java:203)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.cactus.server.runner.ServletTestRunner.run(ServletTestRunner.java:309)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.cactus.server.runner.ServletTestRunner.doGet_aroundBody0(ServletTestRunner.java:187)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.cactus.server.runner.ServletTestRunner.doGet_aroundBody1$advice(ServletTestRunner.java:225)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.cactus.server.runner.ServletTestRunner.doGet(ServletTestRunner.java:1)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at javax.servlet.http.HttpServlet.service(HttpServlet.java:718)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at javax.servlet.http.HttpServlet.service(HttpServlet.java:831)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1449)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:790)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:443)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:175)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:3610)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at com.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:274)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:926)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1557)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:173)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:455)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewInformation(HttpInboundLink.java:384)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.ready(HttpInboundLink.java:272)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.sendToDiscriminators(NewConnectionInitialReadCallback.java:214)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.complete(NewConnectionInitialReadCallback.java:113)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:202)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:766)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:896)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1527)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R Caused by: java.lang.UnsupportedOperationException
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.openjpa.kernel.DetachedStateManager.getMetaData(DetachedStateManager.java:696)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.openjpa.jdbc.meta.strats.UntypedPCValueHandler.toRelationDataStoreValue(UntypedPCValueHandler.java:121)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.openjpa.jdbc.sql.RowImpl.setRelationId(RowImpl.java:327)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.openjpa.jdbc.sql.SecondaryRow.setRelationId(SecondaryRow.java:106)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.openjpa.jdbc.meta.strats.HandlerStrategies.set(HandlerStrategies.java:150)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.openjpa.jdbc.meta.strats.HandlerStrategies.set(HandlerStrategies.java:104)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.openjpa.jdbc.meta.strats.HandlerCollectionTableFieldStrategy.insert(HandlerCollectionTableFieldStrategy.java:154)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.openjpa.jdbc.meta.strats.HandlerCollectionTableFieldStrategy.insert(HandlerCollectionTableFieldStrategy.java:130)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.openjpa.jdbc.meta.FieldMapping.insert(FieldMapping.java:579)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.insert(AbstractUpdateManager.java:197)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.populateRowManager(AbstractUpdateManager.java:139)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at com.ibm.ws.persistence.jdbc.kernel.ConstraintUpdateManager.flush(ConstraintUpdateManager.java:73)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at com.ibm.ws.persistence.jdbc.kernel.ConstraintUpdateManager.flush(ConstraintUpdateManager.java:60)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.flush(JDBCStoreManager.java:655)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.openjpa.kernel.DelegatingStoreManager.flush(DelegatingStoreManager.java:130)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:2010)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.openjpa.kernel.BrokerImpl.flushSafe(BrokerImpl.java:1908)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:1679)
[11/25/08 8:46:56:546 EST] 00000018 SystemErr     R     ... 52 more

在 JobManager.copyJob() 方法中抛出此异常(在行:attachJob.getCopies().add(newJob);)...

@JPAManager(targetEntity=entities.Job.class)
public class JobManager {

      private EntityManager getEntityManager() {
              EntityManagerFactory emf = Persistence
                      .createEntityManagerFactory("import");
              return emf.createEntityManager();
      }

    @Action(Action.ACTION_TYPE.FIND)
    public Job findJobById(int id) {
            EntityManager em = getEntityManager();
            Job job = null;
            try {
               job = (Job) em.find(Job.class, id);
            } finally {
               em.close();
            }
            return job;
    }

    public Job copyJob(Job job, String newJobName) throws Exception {
            EntityManager em = getEntityManager();
            Job attachedJob = null;
            try {
                    em.getTransaction().begin();
                   //merge any changes made to job
                            attachedJob = em.merge(job);
                  //copy the job and establish bi-directional relationship
                            Job newJob = new Job(job);
                            newJob.setName(newJobName);
                            newJob.setJob(attachedJob);
                            em.persist(newJob);
                            attachedJob.getCopies().add(newJob);    
                  em.getTransaction().commit(); //commit changes to original job
             } catch (Exception ex) {
                    try {
                            if (em.getTransaction().isActive()) {
                                  em.getTransaction().rollback();
            }
                    } catch (Exception e) {
                            ex.printStackTrace();
                            throw e;
        }
                    throw ex;
             } finally {
                    em.close();
             }
            return attachedJob;
     }
}

这是我正在使用的生成的数据库模式......

CREATE TABLE Job (id INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY, JOB_ID INTEGER, PRIMARY KEY (id));
CREATE TABLE Job_jobCollection (JOB_ID INTEGER, element VARCHAR(254));
ALTER TABLE Job ADD FOREIGN KEY (JOB_ID) REFERENCES Job (id);
ALTER TABLE Job_jobCollection ADD FOREIGN KEY (JOB_ID) REFERENCES Job (id);

查看 OpenJPA 1.2 源代码显示未实现 DetachedStateManager.getMetaData() 方法,所以我想知道为什么要调用它。有小费吗??

4

2 回答 2

1

您没有显示 Job 的复制构造函数的实现是什么,但是如果您从一个 Job 复制 id 作为该 Job 副本的 id,那么尝试保存复制作业将失败,因为 JPA 会知道具有该 ID 的 Job 实例存在于另一个对象中,并且应该保留该原始对象。

不过,看起来您的问题实际上出在 hashCode 中,并且您的示例显示您没有 hashCode 实现。看起来 openjpa 为您提供了基于 Id 值的 hashCode 实现。当您将某些内容添加到 Set 时,Set 将在您的对象上调用 hashCode() 作为确定对象是否已在 Set 中的过程的一部分。

我会尝试将 id 从 int 更改为 Integer(openjpa 似乎试图从一个可能只是盒装整数的对象进行分配)。或者实现你自己的 hashCode,它只返回 Id 的值。

于 2009-02-13T22:25:06.350 回答
-1

我不熟悉 JPA,因此我不知道您的 JobManager 是否做错了事。

真正有用的是,如果您可以提供更长的堆栈跟踪,以便我们可以告诉您是什么导致您到达DetachedStateManager.getMetaData()并从那里开始。

yc

于 2008-11-24T23:37:53.513 回答