我有以下两个表:
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
?您能为这种情况提供一些示例代码吗?
谢谢!
最佳答案
底部的工作解决方案
我想,我现在已经设法将所有东西放在一起。至少生成的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(...)
时,休眠提供: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;
}
休眠输出:
A a = aRepository.findById(...)
休眠:从* id =?的A中选择*。
a.getBMap().put("EN", someBObject)
休眠:从B中选择*其中a_id =?
aRepository.save(a)
休眠:插入B(a_id,locale,z)值(?,?,?)