我有以下两张表:
TABLE A:
INT id
VARCHAR x
PRIMARY KEY (id)
TABLE B:
INT a_id
VARCHAR locale
VARCHAR z
PRIMARY KEY (a_id, locale)
这基本上是一个简单的OneToMany关系。表B
包含表A
中被引用行的id (a_id
)加上一个locale
。这意味着:A
中的每个条目都可以在表B
中包含0..*
条目,每个条目都具有不同的locale
值。
我有以下两个类,它们应该表示这些表:
@Entity
@Table(name="A")
class A {
@Id
@Column(name="id")
int id;
@Column(name="x")
String x;
@OneToMany(mappedBy="a") // ???
@MapKey... // ???
Map<String, B> bMap;
}
@Entity
@Table(name="B")
class B {
@ManyToOne
@JoinColumn(name="a_id")
A a;
@Column(name="locale")
String locale;
@Column(name="z")
String z;
}
现在缺少了两件事:
Map<String, B> bMap
的注释。我只是不知道我应该使用@MapKey
还是@MapKeyColumn
,以及如何映射到这个复合键。如果我应该/不得不使用@OneToMany
B
类需要一个复合键。我应该使用@EmbeddedId
还是@IdClass
?您能为这个场景提供一些示例代码吗?
谢谢!
发布于 2014-03-22 07:25:44
底部工作溶液
我想,我现在已经把事情做好了。至少生成的SQL表看起来是正确的,尽管我仍然需要弄清楚如何实现级联保存.
@Entity
@Table(name="A")
public class A {
@Id @GeneratedValue(strategy=GenerationType.AUTO)
long id;
@Column(name="x")
String x;
@OneToMany(mappedBy="id.a", cascade=CascadeType.ALL, orphanRemoval=true)
@MapKey(name="id.locale")
Map<String, B> bMap = new HashMap<String, B>();
}
@Entity
@Table(name="B")
public class B {
@EmbeddedId
BPK id;
@Column(name="z")
String z;
}
@Embeddable
public class BPK implements Serializable {
@ManyToOne
@JoinColumn(name="a_id")
A a;
@Column(name="locale")
String locale;
// equals + hashcode
}
调用aRepository.findById(...)
时,Hibernates提供:
Hibernate: select * from A a where a.id=?
这是正确的。
但是,如果我调用aEntity.getBMap()
,它总是获取整个映射,即使我只想使用aEntity.getBMap().put("EN", someBObject)
,也不想从中读取任何数据。但这暂时没问题。
现在我只想弄清楚如何让级联储蓄开始工作。当我做aEntity.getBMap().put("EN", someBObject); aRepository.save(eEntity);
的时候
org.hibernate.id.IdentifierGenerationException: null id generated for:class B
我想我只是错过了一些@EmbeddedId
的设置,或者是字段。
终于解决了:
级联存储不知何故不适用于@EmbeddedId
组合密钥。所以我想了想,我可以用@ElementCollection
!:)
代替。
所以我终于做到了:
@Entity
@Table(name="A")
public class A {
@Id @GeneratedValue(strategy=GenerationType.AUTO)
long id;
@Column(name="x")
String x;
@ElementCollection
@CollectionTable(name="B", joinColumns=@JoinColumn(name="a_id"))
@MapKeyColumn(name="locale")
Map<String, B> bMap = new HashMap<String, B>();
}
@Embeddable
public class B {
@Column(name="z")
String z;
}
Hibernate输出:
A a = aRepository.findById(...)
a.getBMap().put("EN", someBObject)
aRepository.save(a)
https://stackoverflow.com/questions/22573654
复制