【问题标题】:Entity class cannot be cast to java.lang.Number实体类不能转换为 java.lang.Number
【发布时间】:2014-09-21 03:00:12
【问题描述】:

这个问题是这个问题的延续:Foreign key as a part of composite primary key and ManyToOne relationship in OpenJPA

OpenJPA 正在尝试将我的实体类 (TableB) 转换为其键的类型 (long)。为什么?

在字段rows 中没有任何元素的情况下保持TableB 对象可以正常工作。当向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>

【问题讨论】:

  • Persisting of TableB object without any elements in field rows works fine. The problem begins when 'm adding elements to rows. 因为你没有任何实体要持久化。
  • openJPA 将 Number 转换为 long,因为您的表的主键可能是 Numeric 类型。所以它转换为最大的java数字(很长)。我建议您使用Long 作为您的主键类型。所以它会完美地工作。
  • 首先去掉 openjpa.RuntimeUnenhancedClasses 属性。这很可能是您问题的根源。
  • 我在 persistence.xml 中没有任何属性运行它 - &lt;persistence-unit name="JPADepEJB"&gt;&lt;jta-data-source&gt;jdbc/jpatest&lt;/jta-data-source&gt;&lt;/persistence-unit&gt;。也尝试在单个事务中对其进行测试。

标签: java hibernate jpa orm openjpa


【解决方案1】:

尝试正确删除 openjpa.RuntimeUnenhancedClasses 属性和 enhance 您的实体。

【讨论】:

    猜你喜欢
    • 2022-01-22
    • 1970-01-01
    • 2014-07-31
    • 2016-12-15
    • 1970-01-01
    • 2016-06-10
    • 1970-01-01
    • 1970-01-01
    • 2022-01-14
    相关资源
    最近更新 更多