JPAでリレーションを管理するとき、最初はアノテーションでやろうとしたんですが、結局やり方がわからずコンストラクタ式をかいて対処してました。
外部キー制約があるやり方はしっていたんですが、ないときの対処法はわからずじまいでした。
が、いろいろ試してみたところアノテーションでさっくりいけることが判明。
メモしておきます。
多対多は試していないんですが、1対多となる2つのパターンは確認できました。
1対多
1つ目は注文テーブル(sample_order)と注文詳細テーブル(orderline)のようなパターン
この場合、
注文詳細テーブル側が注文テーブルに属しており、どの注文テーブルにひもづけられるのか?というidをもっていることが一般的です。(今回はorder_idとします。)
sample_order がidだけをもち、
orderlineはid,item,price,order_idだけのテーブルだとします。
ブログなんかでユーザー→そのユーザーのコメントなんかがこのパターンですね。
サンプルが一番わかりやすいと思うので下記に紹介します。
SampleOrder.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
@Entity @Table(name = "sample_order") @XmlRootElement @NamedQueries({ @NamedQuery(name = "SampleOrder.findAll", query = "SELECT s FROM SampleOrder s"), @NamedQuery(name = "SampleOrder.findById", query = "SELECT s FROM SampleOrder s WHERE s.id = :id")}) public class SampleOrder implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Basic(optional = false) @Column(name = "id") private Integer id; //↓ここでつないでいます。 @OneToMany @JoinColumn(name="order_id") private List<OrderLine> orderLines; //セッター、ゲッターなど } |
OrderLine.java(通常のエンティティを書けばよく、特別なことは書く必要なし)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
@Entity @Table(name = "order_line") public class OrderLine implements Serializable { @Id @GeneratedValue private Long id; private String item; private Integer price; private Integer order_id; //セッター、ゲッターなど } |
これだけでSampleOrderのエンティティを取得すると、同時にOrderlineも取得できます。
多対1
もう一つは注文詳細テーブル-商品テーブルパターンです。
注文詳細側が商品テーブルのidを別名(product_id)でもっているパターンです。
注文詳細側をid,order_id,prooduct_id
商品テーブル側をid,name,priceで構成されているとします。
その場合下記のようになります。
OrderLine.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
@Entity @Table(name = "order_line") public class OrderLine implements Serializable { @Id @GeneratedValue private Long id; @ManyToOne(targetEntity=Product.class) @JoinColumn(name="product_id",referencedColumnName = "id") private Product product; privte Int private Integer order_id;eger price; //セッター、ゲッターなど } |
Product.java(基本的にリレーションに関する情報はかかなくてOKです。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
@Entity @Table(name = "product") @XmlRootElement @NamedQueries({ @NamedQuery(name = "Product.findAll", query = "SELECT p FROM Product p"), @NamedQuery(name = "Product.findById", query = "SELECT p FROM Product p WHERE p.id = :id"), @NamedQuery(name = "Product.findByCategoryId", query = "SELECT p FROM Product p WHERE p.categoryId = :categoryId"), @NamedQuery(name = "Product.findByName", query = "SELECT p FROM Product p WHERE p.name = :name"), @NamedQuery(name = "Product.findByPrice", query = "SELECT p FROM Product p WHERE p.price = :price")}) public class Product implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Basic(optional = false) private Integer id; private String name; private Integer price; //セッター、ゲッターなど。 |
組み合わせることでSampleOrderを取得すればProductまで一気に取得できます。
長年の悩みがやっと解けました・・・が、半年前に気づけてればよかったです(汗)。
ただ、超簡単なSELECTのリレーションしかやってないのでinsertのときとかはまたいろいろと調べることになりそうです。