我想映射一个Java Map,其中所有键值都存储在同一个表中。 与https://en.wikibooks.org/wiki/Java_Persistence/Relationships#Example_of_a_map_key_column_relationship_database类似的东西 但是密钥是一个对象,而不是一个简单的类型。
说我有一个实体“用户”
@Entity
public class User{
@Id
private String userId;
@OneToMany
@MapKeyClass(CalenderWeek.class)
private Map<CalenderWeek, WorkedTime> workedTimeMap;
关键的CalendarWeek就是这样的
@Embeddable
public class CalenderWeek {
int year;
Month month; // Month is the enum java.time.Month
WorkedTime会像
@Embeddable
public class WorkedTime {
private long workedHours;
相应的工作时间表应该是这样的
worked_time
user_id | year | month | worked_hours
---------|------|-------| ---
1 | 2017 | 11 | 42
是否有可能实现这一目标 或者我必须按照此处的描述进行操作 https://en.wikibooks.org/wiki/Java_Persistence/Relationships#Example_of_a_map_key_class_embedded_relationship_annotation
即有三张桌子。
答案 0 :(得分:2)
一般情况下,如果您想要地图,只需使用@ElementCollection
注释,如果要覆盖Embeddables中的某些列或关联,则使用{{1} } / @AttributeOverride
:
@AssociationOverride
根据您是否要覆盖键或值属性,分别为持久性提供程序添加这些前缀,以便能够重新区分差异。
答案 1 :(得分:0)
我假设您希望每月存储用户的工作时间+年。 查看结果表我建议不要使用Embeddable。你可以尝试这种方法:
@Entity
public class User{
@Id
private String id;
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<WorkedTime> workedTime;
加上后面的参考:
@Entity
public class WorkedTime {
@Id
private long id;
@ManyToOne
@JoinColumn(name = "user_id", nullable = false)
private User user;
private int year;
private Month month;
private long workedHours;
这将导致只有两个表。
答案 2 :(得分:0)
Maciej Kowalski的答案非常有用和正确。谢谢。
我只想在这里完成答案并稍微扩展一下,因为我最后使用了xml配置。 Annotated版本就像那样结束了
@Entity
public class UserWorklogAggregate {
@Id
private String userId;
@ElementCollection
@CollectionTable(
name = "worked_time",
joinColumns = @JoinColumn(name = "user_id")
)
@AttributeOverrides({
@AttributeOverride(name = "key.year", column = @Column(name = "year")),
@AttributeOverride(name = "key.week", column = @Column(name = "week")),
@AttributeOverride(name = "value.workedDuration", column = @Column(name = "worked_duration"))
})
private final Map<CalenderWeek, WorkedTime> workedTimeMap = new HashMap<>();
和xml版本
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping default-access="field" default-cascade="all">
<class name="org.whatever.UserWorklogAggregate" table="user_worklog_aggregate">
<id name="userId" length="10" column="user_id" />
<map name="workedTimeMap" table="worked_time" >
<key column="user_id" />
<composite-map-key class="org.whatever.CalenderWeek">
<key-property name="year" column="year"/>
<key-property name="week" column="week"/>
</composite-map-key>
<composite-element class="org.whatever.WorkedTime" >
<property name="workedDuration" column="worked_duration"/>
</composite-element>
</map>
</class>