2017-03-08 175 views
1

我想映射一個Java映射表,其中所有鍵值存儲在同一個表中。 與https://en.wikibooks.org/wiki/Java_Persistence/Relationships#Example_of_a_map_key_column_relationship_database 類似的東西,但關鍵是一個對象,而不是一個簡單的類型。Jpa Hibernate映射鍵多列關係

說我有一個實體的 「用戶」

@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

即,三個用表。

回答

1

一般來說,如果你想有一個地圖ü只需使用@ElementCollection註釋,如果你想覆蓋一些列或協會從Embeddables然後使用@AttributeOverride/@AssociationOverride的:

@ElementCollection 
@AttributeOverrides({ 
@AttributeOverride(name="key.year", 
[email protected](name="YEAR1")), 
@AttributeOverride(name="value.workedHours", 
[email protected](name="WORKED_H")) 
}) 
private Map<CalenderWeek, WorkedTime> workedTimeMap; 

根據無論是要覆蓋鍵還是值屬性,都要分別爲持久性提供程序添加這些前綴,以便能夠重新識別差異。

+0

只是爲了讓它完成@CollectionTable( 名= 「worked_time」, joinColumns = @ JoinColumn(名=「user_id」) ) 也是需要的。 – fan

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; 

這將導致只有兩個表。

0

Maciej Kowalski的答案非常有用和正確。謝謝。

我只想在這裏完成答案,並稍微擴展它,因爲我在最後使用了xml配置。 的註釋版本結束這樣的

@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>