2.2.5.3.3. Many-to-many 多対多
<2.2.5.3.3. Many-to-many | 目次 | 2.2.5.4. Transitive persistence with cascading>
2.2.5.3.3.1. Definition
多対多関連は @ManyToMany アノテーションで定義されるよ。@JoinTable アノテーションで関連テーブルと結合条件を書かないといけないよ。関連が双方向の場合、一方が親になって、一方が反対の終端となるよ(たとえば、関連テーブルの関連する値を更新しても、無視されるよ)
@Entity public class Employer implements Serializable { @ManyToMany( targetEntity=org.hibernate.test.metadata.manytomany.Employee.class, cascade={CascadeType.PERSIST, CascadeType.MERGE} ) @JoinTable( name="EMPLOYER_EMPLOYEE", joinColumns=@JoinColumn(name="EMPER_ID"), inverseJoinColumns=@JoinColumn(name="EMPEE_ID") ) public Collection getEmployees() { return employees; } ... }
@Entity public class Employee implements Serializable { @ManyToMany( cascade = {CascadeType.PERSIST, CascadeType.MERGE}, mappedBy = "employees", targetEntity = Employer.class ) public Collection getEmployers() { return employers; } }
すでに多くの記述や、関連の属性の詳細を示してきたよね。@JoinTable の記述の詳細に入ろう。これは、name と、結合カラムの列(アノテーションの配列は{A,B,C}で定義するよ)、反対の結合カラムの列を定義するよ。後の二つのものは、Employee(または反対側) の主キーを参照する関連テーブルのカラムだよ。
上で見たように、もう一方では物理マッピングを定義してはいけないよ。親側のプロパティ名を引数に取る 単純な mappedBy が二つを結び付けるよ。
2.2.5.3.3.2. Default values
他のアノテーションのように、多対多関連でもほとんどの値は推測されるよ。単方向の多対多で物理マッピングが定義されないと、次のルールが適応されるよ。テーブル名は親テーブル名、_、もう一方のテーブル名を連結したものになるよ。親テーブルを参照する外部キー名は、親テーブル名、_、親テーブルの主キー名を連結したものになって、もう一方のテーブルを参照する外部キー名は、親プロパティ名、_、そのテーブルの主キー名を連結したものになるよ。単方向の一対多関連と同じルールだよ。
@Entity public class Store { @ManyToMany(cascade = CascadeType.PERSIST) public Set<City> getImplantedIn() { ... } } @Entity public class City { ... //no bidirectional relationship }
結合テーブルに Store_City が使われるよ。Store_id カラムは Store テーブルへの外部キーになるよ。implantedIn_id カラムは City テーブルへの外部キーだよ。
双方向の多対多で物理マッピングがないと次のルールが適応されるよ。テーブル名は、親テーブル名、_、もう一方のテーブル名だよ。親テーブルを参照する外部キー名は、別側のプロパティ名、_、親テーブルの主キー名を連結したもので、もう一方のテーブルを参照する外部キー名は、親側のプロパティ名、_、別側の主キー名になるよ。これは、単方向の一対多関連と同じルールだよ*1。
@Entity public class Store { @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}) public Set<Customer> getCustomers() { ... } } @Entity public class Customer { @ManyToMany(mappedBy="customers") public Set<Store> getStores() { ... } }
Store_Customer が結合テーブル名になるよ。stores_id カラムは Store テーブルへの外部キーで、customers_id は Customer テーブルへの外部キーになるよ。<2.2.5.3.3. Many-to-many | 目次 | 2.2.5.4. Transitive persistence with cascading>
*1:訳注:原文では単方向とあるが、双方向の一対多では?