我想坚持使用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
我得到的错误消息是因为hibernate无法映射T值;
引起:org.springframework.beans.BeanInstantiationException:无法实例化[org.hibernate.SessionFactory]:工厂方法'sessionFactory'引发异常;嵌套异常是org.hibernate.AnnotationException:属性domain.item.Attribute.value具有未绑定类型且没有显式目标实体。解决此通用用法问题或设置显式目标属性(例如@OneToMany(target =)或使用显式@Type
我只需要这个简单的表
提前感谢您提供解决此问题的任何帮助或建议。
答案 0 :(得分:2)
由于java类型擦除Type Erasure,您无法保留泛型T.类型T仅存在于源中,在运行时它的类型为Object。 hibernate doent知道如何在数据库中存储/呈现Object它可能是任何类型 - 实体,集合,嵌入对象,一些简单的对象 - 字符串,整数......
同样在关系数据库中,你不能在没有适当类型的情况下持久化java对象(你可以尝试序列化对象并将其保存为blob,并在java端反序列化它:) :)
将军:
如果它是实体:需要提供一个接口/超类而不是T,如果子类之间的差异很大,那么它只是一个空标记。
@ManyToOne(targetEntity = T_EntityClass.class) @JoinColumn(name =“”) 私人T值;
如果它不是实体 - 看起来像你的情况: 使用除value字段之外的所有字段创建抽象实体,并从此实体扩展子类 - 实现,如String,Integer ....
@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)
)
答案 1 :(得分:0)
sbjavateam,谢谢你的彻底解释。在我尝试实施AttributeConverter
之后,我得出了几乎相同的结论。我坚持将T value
转换为String。最终只使用instance of
来获取Object类型,但我无法映射其值。在您解释的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
。