JPA事务中的java.lang.UnsupportedOperationException

时间:2008-11-24 19:11:40

标签: java orm jpa persistence openjpa

我很确定我不了解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()方法中抛出此异常(在行:attachedJob.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()方法未实现,因此我想知道为什么要调用它。任何提示??

2 个答案:

答案 0 :(得分:1)

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

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

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

答案 1 :(得分:0)

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

真正有用的是,如果你能提供更长的堆栈跟踪,那么我们可以告诉你DetachedStateManager.getMetaData()是什么导致你从那里的某个地方开始。

YC