我有以下两张表:
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
中引用行的ID(A
)加上locale
。这意味着:A
中的每个条目都可以在表0..*
中包含B
个条目,每个条目都具有不同的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
?
您能为此方案提供一些示例代码吗?
谢谢!
答案 0 :(得分:1)
我想,我现在已经把事情放在了一起。至少生成的SQL表看起来是正确的,但我仍然需要弄清楚如何完成Cascaded Saving ......
@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)
并且不想从中读取任何数据。但现在没关系。
现在我只想弄清楚如何让Cascaded Saving工作。在做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;
}
休眠输出:
A a = aRepository.findById(...)
a.getBMap().put("EN", someBObject)
aRepository.save(a)