外键作为复合主键的一部分和OpenJPA中的ManyToOne关系

时间:2014-07-28 20:02:18

标签: java hibernate jpa orm openjpa

我想用OpenJPA 2.3创建简单的数据库。

TableA:
- f_id    PK
- item    PK
- release PK
- b_id    PK
- field1
- field2

TableB:
- id      PK
- name
- date

b_id中的TableA引用id中的TableB(多个TableA行到一个TableB行)。 b_id是整个复合主键的一部分。

TableA类:

@Entity 
@IdClass(TableA_PK.class)
public class TableA implements Serializable {
    @Id
    private int fId;
    @Id
    private String item;
    @Id
    private String release;
    @Id
    @ManyToOne
    @PrimaryKeyJoinColumn(name="b_id", referencedColumnName="id")
    private TableB tableB;
    @Column
    private String field1;
    @Column
    private String field2;

    public TableA() {}
    //getters, setters, equals, hashCode methods
}

TableA主键类:

public class TableA_PK implements Serializable {
    private int fId;
    private String item;
    private String release;
    private TableB tableB;

    public TableA_PK() {}
    //getters, setters, equals, hashCode methods
}

TableB类:

 @Entity 
 public class TableB implements Serializable {
    @Id
    @GeneratedValue
    private long id;
    @Column
    private String name;
    @Column
    private Date date;

    @OneToMany(mappedBy="tableB", fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
    private List<TableA> rows;

    public TableB() {}
    //getters, setters, equals, hashCode methods
}

当我尝试持久化TableB对象时抛出了异常:

org.apache.openjpa.persistence.ArgumentException: Attempt to map "model.TableA.tableB" failed: the owning entity is not mapped.

如何解决这个问题?

我的理论/解释:看起来,当我试图坚持TableB对象时,rows的每个元素都必须保留。但在TableA中有一个字段private TableB tableB(尚未保留),因此我们会陷入无限递归;)。

修改

完整追踪(更改前):

<openjpa-2.3.0-r422266:1540826 fatal user error> org.apache.openjpa.persistence.ArgumentException: Errors encountered while resolving metadata.  See nested exceptions for details.
    at org.apache.openjpa.meta.MetaDataRepository.resolve(MetaDataRepository.java:675)
    at org.apache.openjpa.meta.MetaDataRepository.getMetaDataInternal(MetaDataRepository.java:418)
    at org.apache.openjpa.meta.MetaDataRepository.getMetaData(MetaDataRepository.java:389)
    at org.apache.openjpa.jdbc.meta.MappingRepository.getMapping(MappingRepository.java:354)
    at org.apache.openjpa.jdbc.meta.MappingTool.getMapping(MappingTool.java:682)
    at org.apache.openjpa.jdbc.meta.MappingTool.buildSchema(MappingTool.java:754)
    at org.apache.openjpa.jdbc.meta.MappingTool.run(MappingTool.java:652)
    at org.apache.openjpa.jdbc.kernel.JDBCBrokerFactory.synchronizeMappings(JDBCBrokerFactory.java:154)
    at org.apache.openjpa.jdbc.kernel.JDBCBrokerFactory.synchronizeMappings(JDBCBrokerFactory.java:164)
    at org.apache.openjpa.jdbc.kernel.JDBCBrokerFactory.newBrokerImpl(JDBCBrokerFactory.java:122)
    at org.apache.openjpa.kernel.AbstractBrokerFactory.newBroker(AbstractBrokerFactory.java:209)
    at org.apache.openjpa.kernel.DelegatingBrokerFactory.newBroker(DelegatingBrokerFactory.java:155)
    at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:226)
    at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:153)
    at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:59)
    at org.JpaTest.test(JpaTest.java:40)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: <openjpa-2.3.0-r422266:1540826 fatal user error> org.apache.openjpa.persistence.ArgumentException: The id class specified by type "class org.model.TableA" does not match the primary key fields of the class.  Make sure your identity class has the same primary keys as your persistent type, including pk field types. Mismatched property: "tableB"
    at org.apache.openjpa.meta.ClassMetaData.validateAppIdClassPKs(ClassMetaData.java:2225)
    at org.apache.openjpa.meta.ClassMetaData.validateAppIdClass(ClassMetaData.java:2099)
    at org.apache.openjpa.meta.ClassMetaData.validateIdentity(ClassMetaData.java:2035)
    at org.apache.openjpa.meta.ClassMetaData.validateMeta(ClassMetaData.java:1947)
    at org.apache.openjpa.meta.ClassMetaData.resolve(ClassMetaData.java:1808)
    at org.apache.openjpa.meta.MetaDataRepository.processBuffer(MetaDataRepository.java:829)
    at org.apache.openjpa.meta.MetaDataRepository.resolveMeta(MetaDataRepository.java:726)
    at org.apache.openjpa.meta.MetaDataRepository.resolve(MetaDataRepository.java:650)
    ... 38 more
NestedThrowables:
<openjpa-2.3.0-r422266:1540826 fatal user error> org.apache.openjpa.persistence.ArgumentException: Attempt to map "org.model.TableA.tableB" failed: the owning entity is not mapped.
    at org.apache.openjpa.jdbc.meta.MappingInfo.assertTable(MappingInfo.java:628)
    at org.apache.openjpa.jdbc.meta.MappingInfo.createForeignKey(MappingInfo.java:1080)
    at org.apache.openjpa.jdbc.meta.ValueMappingInfo.getTypeJoin(ValueMappingInfo.java:115)
    at org.apache.openjpa.jdbc.meta.ValueMappingInfo.getTypeJoin(ValueMappingInfo.java:92)
    at org.apache.openjpa.jdbc.meta.strats.RelationFieldStrategy.map(RelationFieldStrategy.java:166)
    at org.apache.openjpa.jdbc.meta.FieldMapping.setStrategy(FieldMapping.java:146)
    at org.apache.openjpa.jdbc.meta.RuntimeStrategyInstaller.installStrategy(RuntimeStrategyInstaller.java:82)
    at org.apache.openjpa.jdbc.meta.FieldMapping.resolveMapping(FieldMapping.java:496)
    at org.apache.openjpa.jdbc.meta.FieldMapping.resolve(FieldMapping.java:461)
    at org.apache.openjpa.jdbc.meta.strats.RelationToManyInverseKeyFieldStrategy.map(RelationToManyInverseKeyFieldStrategy.java:135)
    at org.apache.openjpa.jdbc.meta.strats.RelationCollectionInverseKeyFieldStrategy.map(RelationCollectionInverseKeyFieldStrategy.java:94)
    at org.apache.openjpa.jdbc.meta.FieldMapping.setStrategy(FieldMapping.java:146)
    at org.apache.openjpa.jdbc.meta.RuntimeStrategyInstaller.installStrategy(RuntimeStrategyInstaller.java:82)
    at org.apache.openjpa.jdbc.meta.FieldMapping.resolveMapping(FieldMapping.java:496)
    at org.apache.openjpa.jdbc.meta.FieldMapping.resolve(FieldMapping.java:461)
    at org.apache.openjpa.jdbc.meta.ClassMapping.resolveMapping(ClassMapping.java:854)
    at org.apache.openjpa.meta.ClassMetaData.resolve(ClassMetaData.java:1811)
    at org.apache.openjpa.meta.MetaDataRepository.processBuffer(MetaDataRepository.java:829)
    at org.apache.openjpa.meta.MetaDataRepository.resolveMapping(MetaDataRepository.java:784)
    at org.apache.openjpa.meta.MetaDataRepository.resolve(MetaDataRepository.java:664)
    at org.apache.openjpa.meta.MetaDataRepository.getMetaDataInternal(MetaDataRepository.java:418)
    at org.apache.openjpa.meta.MetaDataRepository.getMetaData(MetaDataRepository.java:389)
    at org.apache.openjpa.jdbc.meta.MappingRepository.getMapping(MappingRepository.java:354)
    at org.apache.openjpa.jdbc.meta.MappingTool.getMapping(MappingTool.java:682)
    at org.apache.openjpa.jdbc.meta.MappingTool.buildSchema(MappingTool.java:754)
    at org.apache.openjpa.jdbc.meta.MappingTool.run(MappingTool.java:652)
    at org.apache.openjpa.jdbc.kernel.JDBCBrokerFactory.synchronizeMappings(JDBCBrokerFactory.java:154)
    at org.apache.openjpa.jdbc.kernel.JDBCBrokerFactory.synchronizeMappings(JDBCBrokerFactory.java:164)
    at org.apache.openjpa.jdbc.kernel.JDBCBrokerFactory.newBrokerImpl(JDBCBrokerFactory.java:122)
    at org.apache.openjpa.kernel.AbstractBrokerFactory.newBroker(AbstractBrokerFactory.java:209)
    at org.apache.openjpa.kernel.DelegatingBrokerFactory.newBroker(DelegatingBrokerFactory.java:155)
    at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:226)
    at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:153)
    at org.apache.openjpa.persistence.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:59)
    at org.JpaTest.test(JpaTest.java:40)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

完整跟踪,更改后(当我在tableBTableA_PK更改了long的类型时):

<openjpa-2.3.0-r422266:1540826 nonfatal general error> org.apache.openjpa.persistence.PersistenceException: org.model.TableB cannot be cast to java.lang.Number
    at org.apache.openjpa.kernel.BrokerImpl.persistAll(BrokerImpl.java:2526)
    at org.apache.openjpa.kernel.SingleFieldManager.persist(SingleFieldManager.java:279)
    at org.apache.openjpa.kernel.StateManagerImpl.cascadePersist(StateManagerImpl.java:3081)
    at org.apache.openjpa.kernel.BrokerImpl.persistInternal(BrokerImpl.java:2703)
    at org.apache.openjpa.kernel.BrokerImpl.persist(BrokerImpl.java:2604)
    at org.apache.openjpa.kernel.BrokerImpl.persist(BrokerImpl.java:2587)
    at org.apache.openjpa.kernel.BrokerImpl.persist(BrokerImpl.java:2491)
    at org.apache.openjpa.kernel.DelegatingBroker.persist(DelegatingBroker.java:1077)
    at org.apache.openjpa.persistence.EntityManagerImpl.persist(EntityManagerImpl.java:716)
    at org.JpaTest.test(JpaTest.java:43)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.ClassCastException: org.model.TableB cannot be cast to java.lang.Number
    at org.apache.openjpa.util.ApplicationIds$PrimaryKeyFieldManager.fetchLongField(ApplicationIds.java:669)
    at org.apache.openjpa.enhance.org$model$TableA$pcsubclass.pcCopyKeyFieldsToObjectId(Unknown Source)
    at org.apache.openjpa.enhance.PCRegistry.copyKeyFieldsToObjectId(PCRegistry.java:169)
    at org.apache.openjpa.util.ApplicationIds.fromPKValues(ApplicationIds.java:224)
    at org.apache.openjpa.enhance.ReflectingPersistenceCapable.pcNewObjectIdInstance(ReflectingPersistenceCapable.java:277)
    at org.apache.openjpa.util.ApplicationIds.create(ApplicationIds.java:427)
    at org.apache.openjpa.kernel.BrokerImpl.persistInternal(BrokerImpl.java:2675)
    at org.apache.openjpa.kernel.BrokerImpl.persistAll(BrokerImpl.java:2521)
    ... 32 more

完整跟踪,更改后(我在tableB上更改了TableA_PK的{​​{1}}类型,Longid的类型TableB }}):

Long

@Gas ANSWER后编辑

我就像你说的那样。但我有问题,坚持整个<openjpa-2.3.0-r422266:1540826 nonfatal general error> org.apache.openjpa.persistence.PersistenceException: Can not set java.lang.Long field org.model.TableA_PK.tableB to org.model.TableB at org.apache.openjpa.kernel.BrokerImpl.persistAll(BrokerImpl.java:2526) at org.apache.openjpa.kernel.SingleFieldManager.persist(SingleFieldManager.java:279) at org.apache.openjpa.kernel.StateManagerImpl.cascadePersist(StateManagerImpl.java:3081) at org.apache.openjpa.kernel.BrokerImpl.persistInternal(BrokerImpl.java:2703) at org.apache.openjpa.kernel.BrokerImpl.persist(BrokerImpl.java:2604) at org.apache.openjpa.kernel.BrokerImpl.persist(BrokerImpl.java:2587) at org.apache.openjpa.kernel.BrokerImpl.persist(BrokerImpl.java:2491) at org.apache.openjpa.kernel.DelegatingBroker.persist(DelegatingBroker.java:1077) at org.apache.openjpa.persistence.EntityManagerImpl.persist(EntityManagerImpl.java:716) at org.JpaTest.test(JpaTest.java:49) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) at org.junit.runners.ParentRunner.run(ParentRunner.java:309) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) Caused by: java.lang.IllegalArgumentException: Can not set java.lang.Long field org.model.TableA_PK.tableB to org.model.TableB at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source) at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source) at sun.reflect.UnsafeObjectFieldAccessorImpl.set(Unknown Source) at java.lang.reflect.Field.set(Unknown Source) at org.apache.openjpa.enhance.Reflection.set(Reflection.java:538) at org.apache.openjpa.enhance.org$model$RowData$pcsubclass.pcCopyKeyFieldsToObjectId(Unknown Source) at org.apache.openjpa.enhance.PCRegistry.copyKeyFieldsToObjectId(PCRegistry.java:169) at org.apache.openjpa.util.ApplicationIds.fromPKValues(ApplicationIds.java:224) at org.apache.openjpa.enhance.ReflectingPersistenceCapable.pcNewObjectIdInstance(ReflectingPersistenceCapable.java:277) at org.apache.openjpa.util.ApplicationIds.create(ApplicationIds.java:427) at org.apache.openjpa.kernel.BrokerImpl.persistInternal(BrokerImpl.java:2675) at org.apache.openjpa.kernel.BrokerImpl.persistAll(BrokerImpl.java:2521) ... 32 more Caused by: java.lang.IllegalArgumentException: Error while setting value org.model.TableB@982c7dfd of class org.model.TableB on field private java.lang.Long org.model.TableA_PK.tableB of instance org.model.TableA_PK@e426b053 by reflection. at org.apache.openjpa.enhance.Reflection.wrapReflectionException(Reflection.java:334) at org.apache.openjpa.enhance.Reflection.set(Reflection.java:540) ... 39 more 对象,我的测试类:

TableB

我有例外:

public class JpaTest {

    @Test
    public void test() {
        TableB tb = new TableB();
        tb.setName("testing");
        tb.setDate(new Date());

        TableA ta1 = new TableA();
        ta1.setFId(1);
        ta1.setItem("item1");
        ta1.setRelease("release1");
        ta1.setField1("f1");
        ta1.setField2("f2");

        TableA ta2 = new TableA();
        ta2.setFId(2);
        ta2.setItem("item2");
        ta2.setRelease("release2");
        ta2.setField1("F1");
        ta2.setField2("F2");

        List<TableA> alist = new ArrayList<TableA>();
        alist.add(ta1);
        alist.add(ta2);

        tb.setRows(alist);

        EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("rd-jpa");
        EntityManager em = entityManagerFactory.createEntityManager();
        EntityTransaction userTransaction = em.getTransaction();
        userTransaction.begin();
        em.persist(tb);
        userTransaction.commit();
        em.clear();
        em.close();
    }

为什么呢?我认为它首先会持续org.apache.openjpa.persistence.RollbackException: The transaction has been rolled back. See the nested exceptions for details on the errors that occurred. (...) Caused by: org.apache.openjpa.lib.jdbc.ReportingSQLException: ERROR: null value in column "b_id" violates not-null constraint ,然后tb中的每个元素都会知道获得的TableB.id(感谢rows类中的tableB字段)。这有什么问题?

如果我在坚持之前在Test中添加两行:

TableA

此异常将抛出:

ta1.setTableB(tb);
ta2.setTableB(tb);

(我需要自己在Caused by: java.lang.ClassCastException: org.model.TableB cannot be cast to java.lang.Number 设置tableB字段吗?)

如何坚持TableA对象?

编辑3:persistence.xml

TableB

1 个答案:

答案 0 :(得分:1)

这适用于我以下代码。更改了TableA_PK中的long tableB和TableA中的@JoinColumn。

TABLEA

@Entity 
@IdClass(TableA_PK.class)
public class TableA implements Serializable {
    @Id
    private int fId;
    @Id
    private String item;
    @Id
    private String release;
    @Id
    @ManyToOne
    @JoinColumn(name="b_id")
    private TableB tableB;
    @Column
    private String field1;
    @Column
    private String field2;

TABLEA_PK

public class TableA_PK implements Serializable {
    private int fId;
    private String item;
    private String release;
    private long tableB;

    public TableA_PK() {}
    //getters, setters, equals, hashCode methods

TABLEB

@Entity 
public class TableB implements Serializable {
   @Id
   @GeneratedValue
   private long id;
   @Column
   private String name;
   @Column
   private Date date;

   @OneToMany(mappedBy="tableB")
   private List<TableA> rows;

   public TableB() {}
   //getters, setters, equals, hashCode methods

评论后更新
遗憾的是,派生密钥不支持生成的值,并且在插入项之前不知道它。因此,您首先需要持久化tableB项,然后添加行。 请检查以下代码:

    TableB tableb = new TableB();
    tableb.setDate(new Date());
    tableb.setName("tableb2");
    em.persist(tableb);  // fills tableb id
    System.out.println(tableb); 
    TableA tableA = new TableA();
    tableA.setfId((int) new Date().getTime());
    tableA.setField1("field1");
    tableA.setField2("field2");
    tableA.setItem("item2");
    tableA.setRelease("1");
    tableA.setTableB(tableb);
    ArrayList<TableA> rows = new ArrayList<TableA>();
    rows.add(tableA);
    tableb.setRows(rows);
    em.merge(tableb);  // inserts tablea objects, you could also just persist tableA items