此问题是此问题的延续:Foreign key as a part of composite primary key and ManyToOne relationship in OpenJPA
OpenJPA正在将我的实体类(TableB
)转换为其键的类型(long
)。为什么呢?
在字段TableB
中没有任何元素的rows
对象的持久工作正常。在向rows
添加元素时,问题就开始了。
TableA.class:
package org.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
@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;
public TableA() {
}
public int getfId() {
return fId;
}
public void setfId(int fId) {
this.fId = fId;
}
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
public String getRelease() {
return release;
}
public void setRelease(String release) {
this.release = release;
}
public TableB getTableB() {
return tableB;
}
public void setTableB(TableB tableB) {
this.tableB = tableB;
}
public String getField1() {
return field1;
}
public void setField1(String field1) {
this.field1 = field1;
}
public String getField2() {
return field2;
}
public void setField2(String field2) {
this.field2 = field2;
}
}
TableA_PK.class:
package org.model;
import java.io.Serializable;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
public class TableA_PK implements Serializable {
private int fId;
private String item;
private String release;
private long tableB;
public TableA_PK() {
}
public int getfId() {
return fId;
}
public void setfId(int fId) {
this.fId = fId;
}
public String getItem() {
return item;
}
public void setItem(String item) {
this.item = item;
}
public String getRelease() {
return release;
}
public void setRelease(String release) {
this.release = release;
}
public long getTableB() {
return tableB;
}
public void setTableB(long tableB) {
this.tableB = tableB;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj == this) {
return true;
}
if (obj.getClass() != getClass()) {
return false;
}
TableA_PK rhs = (TableA_PK) obj;
return new EqualsBuilder().append(fId, rhs.fId).append(item, rhs.item)
.append(release, rhs.release).append(tableB, rhs.tableB)
.isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder().append(fId).append(item).append(release)
.append(tableB).toHashCode();
}
}
TableB.class:
package org.model;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
@Entity
public class TableB implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column
private String name;
@Column
private Date date;
@OneToMany(mappedBy = "tableB", cascade = CascadeType.PERSIST)
private List<TableA> rows;
public TableB() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public List<TableA> getRows() {
return rows;
}
public void setRows(List<TableA> rows) {
this.rows = rows;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj == this) {
return true;
}
if (obj.getClass() != getClass()) {
return false;
}
TableB rhs = (TableB) obj;
return new EqualsBuilder().append(id, rhs.id).append(name, rhs.name)
.append(date, rhs.date).isEquals();
}
@Override
public int hashCode() {
return new HashCodeBuilder().append(id).append(name).append(date)
.toHashCode();
}
}
JpaTest.class:
package org.model;
import java.util.ArrayList;
import java.util.Date;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import org.junit.Test;
public class JpaTest {
@Test
public void test() {
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("rd-jpa");
EntityManager em = entityManagerFactory.createEntityManager();
EntityTransaction userTransaction = em.getTransaction();
userTransaction.begin();//BEGIN TRANSACTION 1.
TableB tableb = new TableB();
tableb.setDate(new Date());
tableb.setName("tableb2");
em.persist(tableb); // fills tableb id
userTransaction.commit(); //COMMIT 1
userTransaction = em.getTransaction();
userTransaction.begin();//BEGIN TRANSACTION 2.
TableA tableA = new TableA();
tableA.setfId(665);
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.persist(tableb);
userTransaction.commit();
em.clear();
em.close();
}
}
运行JpaTest后的堆栈跟踪:
<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:2648)
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.model.JpaTest.test(JpaTest.java:37)
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
的persistence.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<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" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="rd-jpa" transaction-type="RESOURCE_LOCAL">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<class>org.model.TableA</class>
<class>org.model.TableB</class>
<properties>
<property name="openjpa.ConnectionURL"
value="jdbc:postgresql://localhost:5432/mydb" />
<property name="openjpa.ConnectionDriverName" value="org.postgresql.Driver" />
<property name="openjpa.ConnectionUserName" value="postgres" />
<property name="openjpa.ConnectionPassword" value="postgres" />
<property name="openjpa.DynamicEnhancementAgent" value="true" />
<property name="openjpa.RuntimeUnenhancedClasses" value="supported" />
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)" />
</properties>
</persistence-unit>
</persistence>
的pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>jpa</groupId>
<artifactId>jpa</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source />
<target />
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.openjpa</groupId>
<artifactId>openjpa-maven-plugin</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3.2</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.3-1102-jdbc41</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
</dependencies>
</project>