OpenJPA父子级联插入问题

时间:2016-05-18 08:16:06

标签: java jpa db2 openjpa

我有以下实体层次结构:

@Entity
@Table(name = "CNTC_RLTNSHP")
public class ContactRelationship  implements Serializable { // Parent
private static final long serialVersionUID = 1L;

@Id
@Column(name = "O_CNTC_RLTNSHP_ID", updatable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer contactRelationshipID;

@Column(name = "O_WRK_ID")
private Long odsID;

@OneToMany(mappedBy = "phoneContactRelationship", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, targetEntity = ContactRelationshipPhone.class)
private List<ContactRelationshipPhone> contactRelationshipPhones;

// ...

儿童

@Entity
@Table(name = "CNTC_RLTNSHP_PH")
public class ContactRelationshipPhone  implements Serializable {
private static final long serialVersionUID = 1L;

@EmbeddedId
private ContactRelationshipPhonePK id;

@Column(name = "CNTC_PH_NMBR_TXT")
private String contactPhoneNumber;

@Column(name = "PRMY_PH_INDCTR")
private String contactPrimaryPhoneIndicator;

@MapsId("contactRelationshipID")
@ManyToOne
@JoinColumn(name = "O_CNTC_RLTNSHP_ID", referencedColumnName = "O_CNTC_RLTNSHP_ID", insertable = false, updatable = false)
private ContactRelationship phoneContactRelationship;

public ContactRelationshipPhone() {
}

// ...

儿童PK

@Embeddable
public class ContactRelationshipPhonePK implements Serializable {
private static final long serialVersionUID = 1L;

@Column(name = "O_CNTC_RLTNSHP_ID")
private Integer contactRelationshipID;

@Column(name = "PH_TYP_CD")
private String phoneCode;

@Column(name = "PH_TYP_TXT")
private String phoneText;

public ContactRelationshipPhonePK() {
}   

// ...

生成的主键未在子类中设置,因此在子表中插入数据时会出现SQL异常。

异常

Exception in thread "main" <openjpa-2.2.3-SNAPSHOT-r422266:1715851 fatal store error> org.apache.openjpa.persistence.RollbackException: The transaction has been rolled back.  See the nested exceptions for details on the errors that occurred.
FailedObject: com.principal.scbu.ods.entity.worker.ContactRelationshipPhone@61b061b0
    at org.apache.openjpa.persistence.EntityManagerImpl.commit(EntityManagerImpl.java:594)
    at com.test.Test.main(Test.java:73)
Caused by: <openjpa-2.2.3-SNAPSHOT-r422266:1715851 fatal general error> org.apache.openjpa.persistence.PersistenceException: The transaction has been rolled back.  See the nested exceptions for details on the errors that occurred.
FailedObject: com.principal.scbu.ods.entity.worker.ContactRelationshipPhone@61b061b0
    at org.apache.openjpa.kernel.BrokerImpl.newFlushException(BrokerImpl.java:2352)
    at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:2189)
    at org.apache.openjpa.kernel.BrokerImpl.flushSafe(BrokerImpl.java:2087)
    at org.apache.openjpa.kernel.BrokerImpl.beforeCompletion(BrokerImpl.java:2005)
    at org.apache.openjpa.kernel.LocalManagedRuntime.commit(LocalManagedRuntime.java:81)
    at org.apache.openjpa.kernel.BrokerImpl.commit(BrokerImpl.java:1529)
    at org.apache.openjpa.kernel.DelegatingBroker.commit(DelegatingBroker.java:933)
    at org.apache.openjpa.persistence.EntityManagerImpl.commit(EntityManagerImpl.java:570)
    ... 1 more
Caused by: <openjpa-2.2.3-SNAPSHOT-r422266:1715851 fatal general error> org.apache.openjpa.persistence.PersistenceException: AN UPDATE, INSERT, OR SET VALUE IS NULL, BUT THE OBJECT COLUMN O_CNTC_RLTNSHP_ID CANNOT CONTAIN NULL VALUES {prepstmnt 1218201756 INSERT INTO XXX.CNTC_RLTNSHP_PH (PH_TYP_CD, PH_TYP_TXT, CNTC_PH_NMBR_TXT, PRMY_PH_INDCTR) VALUES (?, ?, ?, ?) [params=(null) null, (null) null, (String) E, (String) E]} [code=-407, state=23502]SQLCA OUTPUT[Errp=DSNXODM , Errd=12, 0, 0, -1, 0, 0]
AN UPDATE, INSERT, OR SET VALUE IS NULL, BUT THE OBJECT COLUMN O_CNTC_RLTNSHP_ID CANNOT CONTAIN NULL VALUES
THE DESCRIBE STATEMENT DOES NOT SPECIFY A PREPARED STATEMENT
THE EXECUTE STATEMENT DOES NOT IDENTIFY A VALID PREPARED STATEMENT
FailedObject: com.principal.scbu.ods.entity.worker.ContactRelationshipPhone@61b061b0
    at org.apache.openjpa.jdbc.sql.DBDictionary.narrow(DBDictionary.java:4991)
    at org.apache.openjpa.jdbc.sql.DBDictionary.newStoreException(DBDictionary.java:4957)
    at org.apache.openjpa.jdbc.sql.DB2Dictionary.newStoreException(DB2Dictionary.java:571)
    at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:136)
    at org.apache.openjpa.jdbc.sql.SQLExceptions.getStore(SQLExceptions.java:78)
    at org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flushAndUpdate(PreparedStatementManagerImpl.java:144)
    at org.apache.openjpa.jdbc.kernel.BatchingPreparedStatementManagerImpl.flushAndUpdate(BatchingPreparedStatementManagerImpl.java:79)
    at com.ibm.ws.persistence.jdbc.kernel.PreparedStatementManagerImpl.flushAndUpdate(PreparedStatementManagerImpl.java:63)
    at org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flushInternal(PreparedStatementManagerImpl.java:100)
    at org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flush(PreparedStatementManagerImpl.java:88)
    at org.apache.openjpa.jdbc.kernel.ConstraintUpdateManager.flush(ConstraintUpdateManager.java:550)
    at org.apache.openjpa.jdbc.kernel.ConstraintUpdateManager.flush(ConstraintUpdateManager.java:106)
    at org.apache.openjpa.jdbc.kernel.BatchingConstraintUpdateManager.flush(BatchingConstraintUpdateManager.java:59)
    at org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:113)
    at org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:78)
    at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.flush(JDBCStoreManager.java:732)
    at org.apache.openjpa.kernel.DelegatingStoreManager.flush(DelegatingStoreManager.java:131)
    ... 8 more
Caused by: org.apache.openjpa.lib.jdbc.ReportingSQLException: AN UPDATE, INSERT, OR SET VALUE IS NULL, BUT THE OBJECT COLUMN O_CNTC_RLTNSHP_ID CANNOT CONTAIN NULL VALUES {prepstmnt 1218201756 INSERT INTO XXXX.CNTC_RLTNSHP_PH (PH_TYP_CD, PH_TYP_TXT, CNTC_PH_NMBR_TXT, PRMY_PH_INDCTR) VALUES (?, ?, ?, ?) [params=(null) null, (null) null, (String) E, (String) E]} [code=-407, state=23502]
    at org.apache.openjpa.lib.jdbc.LoggingConnectionDecorator.wrap(LoggingConnectionDecorator.java:219)
    at org.apache.openjpa.lib.jdbc.LoggingConnectionDecorator.wrap(LoggingConnectionDecorator.java:195)
    at org.apache.openjpa.lib.jdbc.LoggingConnectionDecorator.access$1000(LoggingConnectionDecorator.java:59)
    at org.apache.openjpa.lib.jdbc.LoggingConnectionDecorator$LoggingConnection$LoggingPreparedStatement.executeUpdate(LoggingConnectionDecorator.java:1134)
    at org.apache.openjpa.lib.jdbc.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:275)
    at org.apache.openjpa.jdbc.kernel.JDBCStoreManager$CancelPreparedStatement.executeUpdate(JDBCStoreManager.java:1792)
    at org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.executeUpdate(PreparedStatementManagerImpl.java:268)
    at org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flushAndUpdate(PreparedStatementManagerImpl.java:119)
    ... 19 more

的persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
    version="2.0">

    <persistence-unit name="jpa-test" transaction-type="RESOURCE_LOCAL">
        <class>com.principal.scbu.ods.entity.worker.ContactRelationship</class>
        <class>com.principal.scbu.ods.entity.worker.ContactRelationshipPhone</class>
        <class>com.principal.scbu.ods.entity.worker.ContactRelationshipPhonePK</class>

        <properties>
            <property name="openjpa.ConnectionDriverName" value="com.ibm.db2.jcc.DB2Driver" />
            <property name="openjpa.ConnectionURL"
                value="jdbc:db2://host:port/dbname:retrieveMessagesFromServerOnGetMessage=true;" />
            <property name="openjpa.ConnectionUserName" value="*****" />
            <property name="openjpa.ConnectionPassword" value="*******" />              
            <property name="openjpa.jdbc.Schema" value="XXX" />
            <property name="openjpa.jdbc.DBDictionary" value="db2" />
            <property name="openjpa.TransactionMode" value="local" />
            <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
            <property name="openjpa.Compatibility"
                value="StrictIdentityValues=false,QuotedNumbersInQueries=true" />
            <property name="openjpa.RuntimeUnenhancedClasses" value="0" />
            <property name="openjpa.Log"
                value="DefaultLevel=WARN, Runtime=INFO, Tool=INFO, SQL=TRACE" />
            <property name="openjpa.jdbc.MappingDefaults"
                value="jpa(ForeignKeyDeleteAction=restrict, JoinForeignKeyDeleteAction=restrict)" />
            <property name="openjpa.jdbc.SchemaFactory" value="native(ForeignKeys=true)" />
            <property name="openjpa.ConnectionFactoryProperties" value="PrintParameters=true" />
        </properties>
    </persistence-unit>
</persistence>

我错过了什么?

2 个答案:

答案 0 :(得分:0)

相关列甚至没有出现在insert语句中:

INSERT INTO XXX.CNTC_RLTNSHP_PH 
      (PH_TYP_CD, PH_TYP_TXT, CNTC_PH_NMBR_TXT, PRMY_PH_INDCTR) 

如果您将其标记为insertable=false, updateable = false,那也许并不奇怪。

@MapsId("contactRelationshipID")
@ManyToOne
@JoinColumn(name = "O_CNTC_RLTNSHP_ID", referencedColumnName = "O_CNTC_RLTNSHP_ID", insertable = false, updatable = false)
private ContactRelationship phoneContactRelationship;

尝试删除这些属性。

提供您的更新,剩下的问题是您很可能不会设置您必须始终执行的关系的两个方面。

ContactRelationship  cr = new ContactRelationship  ();
ContactRelationshipPhone  crp = new ContactRelationshipPhone ();
cr.getContactRelationshipPhones.add(crp);
crp.setPhoneContactRelationship(cr);

答案 1 :(得分:0)

Alan Hay提供了很好的观点,但我不同意persistence.xml文件不相关。艾伦可能是对的,但看到使用的设置很有意思。 p.xml文件中有很多内容。我不喜欢的一件事是使用“openjpa.RuntimeUnenhancedClasses”。这应该删除,请参阅注释“此功能通常用于快速原型设计,但通常不建议用于生产。”在这个文档中:

http://openjpa.apache.org/builds/2.2.2/apache-openjpa/docs/manual#openjpa.RuntimeUnenhancedClasses

查看openjpa.Compatibility和openjpa.jdbc.MappingDefaults设置是否有所不同可能也很有趣。最终,正如Alan所说,你的代码创建/持久化实体在这里看是有价值的。