このステートメントは常にtrueです。 “コレクション変数にput inverse = true”を設定しますが、目立たないようにしてください。理由は、Hibernateのパフォーマンスを最適化するために不可欠です。

「逆」とは何ですか?

これはHibernateの中で最も混乱するキーワードですが、少なくとも私はそれを理解するのにかなり長い時間がかかりました。 ”

inverse

“キーワードは常にone-to-many



many-to-many ** の関係で宣言されます(many-to-oneはinverseキーワードを持たない)。その関係の

“inverse”は “relationship owner”に変更する必要がありますか?

Hibernateでは、「関係所有者」だけが関係を維持する必要があり、「inverse」キーワードは、関係を維持する所有者のどちら側を定義するために作成されます。しかし、 “逆”キーワード自体は冗長ではないので、キーワードを ”

relationship__owner

“に変更することをお勧めします。

要するに、inverse = “true”はこれが関係所有者であることを意味し、inverse = “false”(デフォルト)はそれがそうでないことを意味します。

1. 1対多の関係

これは

1対多

関係表の設計であり、STOCK表にはSTOCK

DAILY

RECORD表に多数のオカレンスがあります。


1対多の関係、title = "1対多数の関係 - 逆"、width = 554、height = 207

2.ハイバネーションの実装

XMLマッピングファイルのHibernate実装を参照してください。


File:Stock.java

public class Stock implements java.io.Serializable {
   ...
   private Set<StockDailyRecord> stockDailyRecords =
                        new HashSet<StockDailyRecord>(0);
   ...


File:StockDailyRecord.java

public class StockDailyRecord implements java.io.Serializable {
   ...
   private Stock stock;
   ...


File:Stock.hbm.xml

<hibernate-mapping>
    <class name="com.mkyong.common.Stock" table="stock" ...>
    ...
    <set name="stockDailyRecords" table="stock__daily__record" fetch="select">
        <key>
            <column name="STOCK__ID" not-null="true"/>
        </key>
        <one-to-many class="com.mkyong.common.StockDailyRecord"/>
    </set>
    ...


File:StockDailyRecord.hbm.xml

<hibernate-mapping>
  <class name="com.mkyong.common.StockDailyRecord" table="stock__daily__record" ...>
  ...
  <many-to-one name="stock" class="com.mkyong.common.Stock">
       <column name="STOCK__ID" not-null="true"/>
  </many-to-one>
  ...

3. inverse = true/false

逆キーワードは、1対多の関係で適用されます。これは、 “stockDailyRecords”関係を更新する必要がありますか?


File:Stock.hbm.xml

    <class name="com.mkyong.common.Stock" table="stock" ...>
    ...
    <set name="stockDailyRecords" table="stock__daily__record" inverse="{true/false}" fetch="select">
        <key>
            <column name="STOCK__ID" not-null="true"/>
        </key>
        <one-to-many class="com.mkyong.common.StockDailyRecord"/>
    </set>
    ...

  • 1。 inverse = “true” **

セット変数のinverse = “true”の場合、 “stock

daily

record”はリレーションシップ所有者なので、Stockはリレーションシップを更新しません。

<class name="com.mkyong.common.Stock" table="stock" ...>
    ...
    <set name="stockDailyRecords" table="stock__daily__record" inverse="true" >

  • 2。 inverse = “false” **

set変数のinverse = “false”(デフォルト)の場合は、 “stock”がリレーション所有者であり、Stockがリレーションシップを更新することを意味します。

<class name="com.mkyong.common.Stock" table="stock" ...>
    ...
    <set name="stockDailyRecords" table="stock__daily__record" inverse="false" >

以下の例をご覧ください:

4. inverse = “false”例

キーワード “inverse”が定義されていない場合、inverse = “false”が使用されます。

<!--Stock.hbm.xml-->
<class name="com.mkyong.common.Stock" table="stock" ...>
    ...
    <set name="stockDailyRecords" table="stock__daily__record" inverse="false">

それは、 “株”が関係の所有者であり、それが関係を維持することを意味します。

  • 例を挿入する…​ **

“Stock”オブジェクトが保存されると、Hibernateは3つのSQL文、2つの挿入、1つの更新を生成します。

    session.beginTransaction();

    Stock stock = new Stock();
    stock.setStockCode("7052");
    stock.setStockName("PADINI");

    StockDailyRecord stockDailyRecords = new StockDailyRecord();
    stockDailyRecords.setPriceOpen(new Float("1.2"));
    stockDailyRecords.setPriceClose(new Float("1.1"));
    stockDailyRecords.setPriceChange(new Float("10.0"));
    stockDailyRecords.setVolume(3000000L);
    stockDailyRecords.setDate(new Date());

    stockDailyRecords.setStock(stock);
    stock.getStockDailyRecords().add(stockDailyRecords);

    session.save(stock);
    session.save(stockDailyRecords);

    session.getTransaction().commit();


出力…​

Hibernate:
    insert
    into
        mkyongdb.stock
        (STOCK__CODE, STOCK__NAME)
    values
        (?, ?)
Hibernate:
    insert
    into
        mkyongdb.stock__daily__record
        (STOCK__ID, PRICE__OPEN, PRICE__CLOSE, PRICE__CHANGE, VOLUME, DATE)
    values
        (?, ?, ?, ?, ?, ?)
Hibernate:
    update
        mkyongdb.stock__daily__record
    set
        STOCK__ID=?
    where
        RECORD__ID=?

ストックはリレーションシップ所有者であるため、 ”

stock

daily

record.STOCK__ID

“をSet変数(stockDailyRecords)を使用して更新します。

  • 注** 3番目のステートメントは実際には必要ありません。

  • アップデート例…​ **

“Stock”オブジェクトが更新されると、Hibernateは挿入と更新の2つのSQL文を生成します。

    session.beginTransaction();

    Stock stock = (Stock)session.get(Stock.class, 57);

    StockDailyRecord stockDailyRecords = new StockDailyRecord();
    stockDailyRecords.setPriceOpen(new Float("1.2"));
    stockDailyRecords.setPriceClose(new Float("1.1"));
    stockDailyRecords.setPriceChange(new Float("10.0"));
    stockDailyRecords.setVolume(3000000L);
    stockDailyRecords.setDate(new Date());

    stockDailyRecords.setStock(stock);
    stock.getStockDailyRecords().add(stockDailyRecords);

    session.save(stockDailyRecords);
    session.update(stock);

    session.getTransaction().commit();


出力…​

Hibernate:
    insert
    into
        mkyongdb.stock__daily__record
        (STOCK__ID, PRICE__OPEN, PRICE__CLOSE, PRICE__CHANGE, VOLUME, DATE)
    values
        (?, ?, ?, ?, ?, ?)
Hibernate:
    update
        mkyongdb.stock__daily__record
    set
        STOCK__ID=?
    where
        RECORD__ID=?

  • 注意** もう一度、3番目のステートメントは必要ありません。

5. inverse = “true”例

キーワード “inverse = true”が定義されている場合:

<!--Stock.hbm.xml-->
<class name="com.mkyong.common.Stock" table="stock" ...>
    ...
    <set name="stockDailyRecords" table="stock__daily__record" inverse="true">

さて、 ”

stockDailyRecords

“は関係所有者であり、 “stock”はその関係を維持しないことを意味します。

  • 例を挿入する…​ **

“Stock”オブジェクトが保存されると、Hibernateは2つのSQL挿入ステートメントを生成します。

    session.beginTransaction();

    Stock stock = new Stock();
    stock.setStockCode("7052");
    stock.setStockName("PADINI");

    StockDailyRecord stockDailyRecords = new StockDailyRecord();
    stockDailyRecords.setPriceOpen(new Float("1.2"));
    stockDailyRecords.setPriceClose(new Float("1.1"));
    stockDailyRecords.setPriceChange(new Float("10.0"));
    stockDailyRecords.setVolume(3000000L);
    stockDailyRecords.setDate(new Date());

    stockDailyRecords.setStock(stock);
    stock.getStockDailyRecords().add(stockDailyRecords);

    session.save(stock);
    session.save(stockDailyRecords);

    session.getTransaction().commit();

__出力…​

Hibernate:
    insert
    into
        mkyongdb.stock
        (STOCK__CODE, STOCK__NAME)
    values
        (?, ?)
Hibernate:
    insert
    into
        mkyongdb.stock__daily__record
        (STOCK__ID, PRICE__OPEN, PRICE__CLOSE, PRICE__CHANGE, VOLUME, DATE)
    values
        (?, ?, ?, ?, ?, ?)

  • アップデート例…​ **

“Stock”オブジェクトが更新されると、Hibernateは1つのSQL文を生成します。

    session.beginTransaction();

    Stock stock = (Stock)session.get(Stock.class, 57);

    StockDailyRecord stockDailyRecords = new StockDailyRecord();
    stockDailyRecords.setPriceOpen(new Float("1.2"));
    stockDailyRecords.setPriceClose(new Float("1.1"));
    stockDailyRecords.setPriceChange(new Float("10.0"));
    stockDailyRecords.setVolume(3000000L);
    stockDailyRecords.setDate(new Date());

    stockDailyRecords.setStock(stock);
    stock.getStockDailyRecords().add(stockDailyRecords);

    session.save(stockDailyRecords);
    session.update(stock);

    session.getTransaction().commit();


出力…​

Hibernate:
    insert
    into
        mkyongdb.stock__daily__record
        (STOCK__ID, PRICE__OPEN, PRICE__CLOSE, PRICE__CHANGE, VOLUME, DATE)
    values
        (?, ?, ?, ?, ?, ?)

  • inverse vs cascade ** 逆数とカスケードを比較するのが好きですが、どちらも全く異なる概念です。

結論

あなたのHibernateコードを最適化するためには “inverse”を理解することが不可欠です。上記の “inverse = falseの挿入と更新の例”のような多くの不要な更新文を避けるのに役立ちます。最後に、inverse = “true”を覚えてみてください。これは、関係を処理する関係所有者であることを意味します。