2017-03-08 10 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がWorkedTimeが

@Embeddable 
public class WorkedTime { 
    private long workedHours; 

が働いて対応するようになり、この

@Embeddable 
public class CalenderWeek { 
    int year; 
    Month month; // Month is the enum java.time.Month 

ようなものになるだろうがあるとタイムテーブルはこのようになります

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

すなわち、3つのテーブルで、ここで説明したように、私はそれをしなければならない行うことです。

答えて

1

あなたは地図を持つようにしたい場合はuは単に@ElementCollectionアノテーションを使用して、埋込み可能から列または団体の一部を上書きしたい場合は、あなたが@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

のように終わった注釈付きバージョン(名= "user_id") ) も必要です。 – fan

0

月間+ 1年間のユーザーの勤務時間を保存したいとします。 結果表を見ると、埋め込み型を使用しないことをお勧めします。あなたは、このアプローチを試みることができる:

@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設定を使用したので、ここで答えを完成させて少し拡張したいと思います。 ちょうどそれが@CollectionTable( 名= "worked_time"、 joinColumns = @ JoinColumnを完成させるためにその

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