我想持久化到 DB 2 实体中:
-
属性
@Entity public class Attribute<T> { @Id @GeneratedValue(strategy = AUTO) Long id; @ManyToOne @JoinColumn(name = "item_id") Item item; String name; T value; boolean isTemplate; // skip setter and getter }
-
项目
public class Item { @Id @GeneratedValue(strategy = AUTO) Long id; @OneToMany(cascade = ALL) @JoinColumn(name= "item_id") List<Attribute> attributes; private boolean isTemplate; // skip setter and getter } in short Item 1-->* Attribute
-
我收到的错误消息,因为休眠无法映射 T 值;
原因:org.springframework.beans.BeanInstantiationException:无法实例化 [org.hibernate.SessionFactory]:工厂方法 'sessionFactory' 引发异常;嵌套异常为 org.hibernate.AnnotationException: Property domain.item.Attribute.value 具有未绑定类型,没有显式目标实体。解决此通用用法问题或设置显式目标属性(例如 @OneToMany(target=) 或使用显式@Type
-
我只需要这张简单的桌子
- 项目
| 编号:int | isTemplate:boolean | - 属性|
编号:int |名称:字符串 |类型:字符串(即:字符串,整数 - 基于>的值类型) |值:字符串 |fk_item_id |
- 项目
提前感谢您解决此问题的任何帮助或建议。
由于 java 类型擦除,您无法保留泛型 T。类型 T 仅存在于源中,运行时它是 Object 类型。Hibernate Doent知道如何在数据库中存储/呈现对象,它可能是任何类型 - 实体,集合,嵌入对象,一些简单的对象 - 字符串,整数.....
同样在关系数据库中,如果没有适当的类型,您将无法持久化 java 对象(您可以尝试序列化对象并将其保存为 blob,并在 java 端将其反序列化:) :)
常规:
-
如果 T 它是实体:需要提供一个接口/超类而不是 T,如果子类之间的差异很大,它只是一个空标记。
@ManyToOne(目标实体=T_EntityClass.class) @JoinColumn(名称 = ") 私有 T 值;
-
如果它不是实体 - 看起来像你的情况: 使用除值字段以外的所有字段创建抽象实体,并从该实体子实现扩展,如字符串,整数...。
@Entity @Inheritance(strategy = InheritanceType.JOINED) public abstract class Attribute<T> { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @ManyToOne @JoinColumn(name = "item_id") private Item item; @Column private String name; @Column boolean isTemplate; public abstract T getValue(); public abstract void setValue(T value); ........ }
字符串实现:
@Entity
public class AttributeStringValue extends Attribute<String>{
@Column
String value;
@Override
public String getValue() {
return value;
}
@Override
public void setValue(String value) {
this.value = value;
}
}
整数实现:
@Entity
public class AttributeIntegerValue extends Attribute<Integer>{
@Column
Integer value;
@Override
public Integer getValue() {
return value;
}
@Override
public void setValue(Integer value) {
this.value = value;
}
}
结果你有3个表:
create table attribute (
id bigint generated by default as identity,
is_template boolean,
name varchar(255),
item_id bigint,
primary key (id)
)
create table attribute_integer_value (
value integer,
id bigint not null,
primary key (id)
)
create table attribute_string_value (
value varchar(255),
id bigint not null,
primary key (id)
)
sbjavateam,感谢您的详尽解释。在我尝试实施AttributeConverter
后,我得出了几乎相同的结论.我坚持将T value
转换为字符串。它最终使用instance of
仅获取对象类型,但我无法映射其值。在您的解释Also in relational databases you can't persist java object without appropriate type
中对此进行了很好的解释。
我最终采用了与您几乎相同的方法来创建额外的类包装器,但Attribute<T>
真的是一个好主意......它给我带来了证明design your entity first clean and nice and do mapping latter
的武器库.