1前書き

この簡単なHibernateチュートリアルでは、JPAアノテーションを使用した1対多マッピングの例(XMLの代替)について説明します。

また、双方向の関係とは何か、それらがどのように矛盾を引き起こす可能性があるのか​​、そして「所有」という概念がどのように役立つかについても学びます。


2説明

簡単に言うと、** 1対多マッピングとは、テーブル内の1つの行が別のテーブル内の複数の行にマップされることを意味します。

次のエンティティ関係図を見て、1対多の関連付けを確認しましょう。

リンク:/uploads/C-1-300×110.png%20300w[]

この例では、カートシステムを実装します。カートシステムには、各カート用のテーブルと各商品用のテーブルがあります。 ** 1つのカートには

many

個のアイテムを含めることができるので、ここでは1対多のマッピングがあります。

これがデータベースレベルで機能する方法は、

cart

テーブルの主キーとして

cart

id

を持ち、さらに

items

の外部キーとして


cart

idを持つことです。

そして、私たちがコードでそれを行う方法は

@ OneToMany

を使うことです。

データベース内の関係を反映するように

Cart

クラスを

Items

オブジェクトにマッピングしましょう。

public class Cart {

   //...

    @OneToMany(mappedBy="cart")
    private Set<Items> items;

   //...
}


@ ManyToOne

を使用して

Items



Cart

への参照を追加し、これをhttps://docs.jboss.org/hibernate/orm/4.1/manuals/en-US/html/ch07.html#collections-bidirectional[[双方向]の関係。

Bidirectional

は、


carts

から

items

に、そして

items


から

carts

にアクセスできることを意味します。


mappedBy

プロパティは、子クラスの親クラスを表すために使用している変数をHibernateに伝えるために使用します。

次のテクノロジとライブラリは、1対多の関連付けを実装するサンプルHibernateアプリケーションを開発するために使用されます。


  • JDK

    1.8以降


  • 休止状態

    4以降


  • Maven

    3以降


  • MySQL

    サーバー5.6以降


3セットアップ


3.1. データベース設定

以下は

Cart

テーブルと

Items

テーブルのデータベーススクリプトです。 one-to-many__マッピングには外部キー制約を使います。

CREATE TABLE `Cart` (
  `cart__id` int(11) unsigned NOT NULL AUTO__INCREMENT,
  PRIMARY KEY (`cart__id`)
) ENGINE=InnoDB AUTO__INCREMENT=5 DEFAULT CHARSET=utf8;

CREATE TABLE `Items` (
  `id` int(11) unsigned NOT NULL AUTO__INCREMENT,
  `cart__id` int(11) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `cart__id` (`cart__id`),
  CONSTRAINT `items__ibfk__1` FOREIGN KEY (`cart__id`) REFERENCES `Cart` (`cart__id`)
) ENGINE=InnoDB AUTO__INCREMENT=7 DEFAULT CHARSET=utf8;

データベースの設定は完了しました。Hibernateサンプルプロジェクトの作成に進みましょう。


3.2. Mavenの依存関係

次にHibernateとMySQLドライバの依存関係を

pom.xml

ファイルに追加します。Hibernateの依存関係はJBossロギングを使用し、自動的に推移的な依存関係として追加されます。

  • Hibernateバージョン5


    _。2.7。最終

    _

  • MySQLドライバのバージョン

    6.0.5


Hibernate

およびhttps://検索の最新バージョンについては、Maven中央リポジトリーにアクセスしてください。 maven.org/classic/#search%7Cga%7C1%7Ca%3A%22mysql-connector-java%22[MySQL]依存関係。


3.3. 休止状態の設定

これがHibernateの設定です。

<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver__class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.password">root</property>
        <property name="hibernate.connection.url">
          jdbc:mysql://localhost:3306/setup</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="hibernate.current__session__context__class">thread</property>
        <property name="hibernate.show__sql">true</property>
    </session-factory>
</hibernate-configuration>


3.4.

HibernateAnnotationUtil

クラス


HibernateAnnotationUtil

クラスを使用して、新しいHibernate設定ファイルを参照するだけです。

private static SessionFactory sessionFactory;

private SessionFactory buildSessionFactory() {

    Configuration configuration = new Configuration();
    configuration.configure("hibernate-annotation.cfg.xml");
    System.out.println("Hibernate Annotation Configuration loaded");

    ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
      .applySettings(configuration.getProperties()).build();
    System.out.println("Hibernate Annotation serviceRegistry created");

    SessionFactory sessionFactory
      = configuration.buildSessionFactory(serviceRegistry);

    return sessionFactory;
}

public SessionFactory getSessionFactory() {
    if(sessionFactory == null) sessionFactory = buildSessionFactory();
    return sessionFactory;
}


4モデル

マッピング関連の設定は、モデルクラスのJPAアノテーションを使用して行われます。

@Entity
@Table(name="CART")
public class Cart {

   //...

    @OneToMany(mappedBy="cart")
    private Set<Items> items;

   //getters and setters
}


mappedBy

変数をマッピングするために使用される

Items

クラスでプロパティを定義するために

@ OneToMany

アノテーションが使用されていることに注意してください。そのため、

Items

クラスに ”

cart

“という名前のプロパティがあります。

@Entity
@Table(name="ITEMS")
public class Items {

   //...
    @ManyToOne
    @JoinColumn(name="cart__id", nullable=false)
    private Cart cart;

    public Items() {}

   //getters and setters
}


@ ManyToOne

アノテーションは

Cart

クラス変数に関連付けられていることに注意することが重要です。

@ JoinColumn

アノテーションはマップされた列を参照します。


5実行中

テストプログラムでは、Hibernate Sessionを取得し、

one-to-many

アソシエーションを実装するデータベースにモデルオブジェクトを保存するための

main

()メソッドを持つクラスを作成します。

sessionFactory = HibernateAnnotationUtil.getSessionFactory();
session = sessionFactory.getCurrentSession();
System.out.println("Session created");

tx = session.beginTransaction();

session.save(cart);
session.save(item1);
session.save(item2);

tx.commit();
System.out.println("Cart ID=" + cart.getId());
System.out.println("item1 ID=" + item1.getId()
  + ", Foreign Key Cart ID=" + item.getCart().getId());
System.out.println("item2 ID=" + item2.getId()
+ ", Foreign Key Cart ID=" + item.getCart().getId());

これは私たちのテストプログラムの出力です:

Session created
Hibernate: insert into CART values ()
Hibernate: insert into ITEMS (cart__id)
  values (?)
Hibernate: insert into ITEMS (cart__id)
  values (?)
Cart ID=7
item1 ID=11, Foreign Key Cart ID=7
item2 ID=12, Foreign Key Cart ID=7
Closing SessionFactory


6.

@ ManyToOne

アノテーション

セクション2で説明したように、

@ ManyToOne

アノテーションを使用して

一対多

の関係を指定できます。

Many-to-one

マッピングとは、このエンティティの多くのインスタンスが別のエンティティの1つのインスタンスにマッピングされることを意味します – **


art


art


art @


  • @ ManyToOne

    アノテーションを使用すると、双方向の関係も作成できます。** これについては、次のいくつかのサブセクションで詳しく説明します。


6.1. 矛盾と所有権

ここで、

Cart



Items

を参照していても、

Items



Cart

を参照していない場合、

私たちの関係は一方向になります

。オブジェクトも自然な一貫性を持ちます。

しかし、私たちの場合、関係は双方向であり、** 矛盾の可能性があります。

開発者が

item1



cart

に、

item2



cart2

に追加したいが、

cart2



item2

の間の参照が矛盾するように間違えている状況を想像してみてください。

Cart cart1 = new Cart();
Cart cart2 = new Cart();

Items item1 = new Items(cart1);
Items item2 = new Items(cart2);
Set<Items> itemsSet = new HashSet<Items>();
itemsSet.add(item1);
itemsSet.add(item2);
cart1.setItems(itemsSet);//wrong!

上記のように、

item2



cart2を参照し、


cart2は

item2を参照していません。

  • Hibernateは

    item2

    をデータベースに保存するにはどうすればよいですか?

私たちは、関係の「卑劣な側」という考えを使用してこの曖昧さを解決します – 所有側に属する参照が優先され、データベースに保存されます。


6.2. 所有側としての

items


2.9項のhttp://download.oracle.com/otndocs/jcp/persistence-2.0-fr-eval-oth-JSpec/[JPA仕様]に記載されているように、**

many-to-oneとマークすることをお勧めします所有側としてのside

言い換えれば、

__項目





own側、


Cart

はその反対側になります。

では、どうやってこれを達成したのでしょうか。


Cart

クラスに

mappedBy

属性を含めることで、それを反対側としてマークします。

同時に、

Items.cart

フィールドに

@ ManyToOne

というアノテーションを付けて、

Items

を所有側にしています。

「矛盾」の例に戻ると、Hibernateは**

item2

の参照がより重要であり、__item2の参照をデータベースに保存することを認識しています。

結果を確認しましょう。

item1 ID=1, Foreign Key Cart ID=1
item2 ID=2, Foreign Key Cart ID=2


cart

はスニペットで

item2

を参照していますが、

item2



cart2

への参照はデータベースに保存されます。

** 6.3. 所有側としての


_cart

_

「1対多」の側を所有側として、「多対1」の側を逆側としてマークすることもできます。

これは推奨される方法ではありませんが、先に進んで試してみましょう。

以下のコードスニペットは、所有者側として

1対多

側の実装を示しています。

public class ItemsOIO {

   // ...
    @ManyToOne
    @JoinColumn(name = "cart__id", insertable = false, updatable = false)
    private CartOIO cart;
   //..
}

public class CartOIO {

   //..
    @OneToMany
    @JoinColumn(name = "cart__id")//we need to duplicate the physical information
    private Set<ItemsOIO> items;
   //..
}


mappedBy

要素を削除し、

Many-to-one @JoinColumn



insertable



updatable



false

に設定したことに注目してください。

同じコードを実行した場合、結果は逆になります。

item1 ID=1, Foreign Key Cart ID=1
item2 ID=2, Foreign Key Cart ID=1

上記のように、今

item2



cart.

に属しています


7. 結論

JPAアノテーションを使用してHibernate ORMおよびMySQLデータベースとの1対多の関係を実装するのがいかに簡単かを説明しました。

また、双方向の関係と所有側の概念の実装方法についても学びました。

このチュートリアルのソースコードはhttps://github.com/eugenp/tutorials/tree/master/persistence-modules/spring-hibernate4[GitHub上で動く]にあります。