gpt4 book ai didi

java - EclipseLink + JPA + 通用实体 + SINGLE_TABLE 继承

转载 作者:行者123 更新时间:2023-12-01 04:14:46 25 4
gpt4 key购买 nike

我想知道是否可以在 JPA 中定义一个通用实体(如我的情况 PropertyBase)并派生具体实体类(如 ShortProperty 和 StringProperty)并将它们与 SINGLE_TABLE 继承模式一起使用?

如果我尝试通过 EntityManager 提交新创建的 ElementModel 实例(请参阅 ElementModelTest),我总是会收到 NumberFormatException,表示“值”无法正确转换为 Short。奇怪的是,如果我将下面的所有类定义为我的测试用例类“ElementModelTest”的内部静态类,这似乎有效。

我需要改变什么才能使这项工作成功?

我正在使用 EclipseLink eclipselink-2.6.0.v20131019-ef98e5d。


public abstract class PersistableObject implements Serializable {

private String id = UUID.randomUUID().toString();
private Long version;

}


public abstract class PropertyBase<T> extends PersistableObject {

private String name;
private T value;

}


public class ShortProperty extends PropertyBase<Short> {
...
}


public class StringProperty extends PropertyBase<String> {
...
}


public class ElementModel extends PersistableObject {

private StringProperty name = new StringProperty();
private ShortProperty number = new ShortProperty();

}


public class ElementModelTest extends ModelTest<ElementModel> {

@Test
@SuppressWarnings("unchecked")
public void testSQLPersistence() {

final String PERSISTENCE_UNIT_NAME = getClass().getPackage().getName();
new File("res/db/test/" + PERSISTENCE_UNIT_NAME + ".sqlite").delete();

EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager em = factory.createEntityManager();

em.getTransaction().begin();

for (int i = 0; i < 10; ++i) {
ElementModel device = new ElementModel();
device.setName("ElementModel: " + i);
device.setNumber((short) i);
em.persist(device);
}

em.getTransaction().commit();
em.close();

}

}


<?xml version="1.0" encoding="UTF-8" ?>
<entity-mappings version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd">

<mapped-superclass
class="PersistableObject">
<attributes>
<id name="id">
<column name="id" />
</id>
<version name="version" access="PROPERTY">
<column name="version" />
</version>
</attributes>
</mapped-superclass>

<entity class="PropertyBase">
<table name="PropertyBase" />
<inheritance />
<discriminator-column name="type"/>
<attributes>
<basic name="name">
<column name="name" />
</basic>
<basic name="value">
<column name="value" />
</basic>
</attributes>
</entity>

<entity class="StringProperty">
<discriminator-value>StringProperty</discriminator-value>
</entity>

<entity class="ShortProperty">
<discriminator-value>ShortProperty</discriminator-value>
</entity>

<entity class="ElementModel">
<table name="ElementModel" />
<inheritance />
<discriminator-column name="type"/>
<attributes>
<one-to-one name="name">
<join-column name="name" referenced-column-name="id" />
<cascade>
<cascade-all />
</cascade>
</one-to-one>
<one-to-one name="number">
<join-column name="number" referenced-column-name="id" />
<cascade>
<cascade-all />
</cascade>
</one-to-one>
</attributes>
</entity>

</entity-mappings>

最佳答案

你的问题是PropertyBase<T>是一个具有字段 value 的实体是持久的。您的数据库需要将该字段类型映射到列类型,并且您拥有三个实体,它们的同一字段具有不同的 java 类型:PropertyBase<T>是通用的,它本身不知道它的类型 value字段是,StringProperty说它是一个字符串并且 ShortProperty说这是一个短片。所以这是一个冲突。

为了克服这个问题,你创建字段 value transient ,以及 PropertyBase<T> 的每个子类型(如 StringProperty )您可以使用不同的名称定义一个新的可持久属性,例如 StringProperty将有一个private String stringValue , ShortProperty将有一个private Short shortValue ,每个字段都会映射到不同的数据库列。

PS:我无法解释为什么当你创建所有类时它会起作用 static inner .

关于java - EclipseLink + JPA + 通用实体 + SINGLE_TABLE 继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19537255/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com