session.get()とsession.load()で異なります
多くの場合、Hibernate開発者がsession.get()とsession load()を組み合わせて使用していることに気付くでしょう。何が違うのか、いつどちらを使用すべきか疑問に思いますか?
session.get()とsession.load()で異なります
実際、両方の関数はもちろん、異なるメカニズムでオブジェクトを取得するために使用されます。
1. session.load()
-
データベースにアクセスすることなく、常に「proxy」(休止状態の用語)を返します。 Hibernateでは、proxyは与えられた識別子の値を持つオブジェクトです。そのプロパティはまだ初期化されていません。一時的な偽のオブジェクトのように見えます。
-
行が見つからない場合は、ObjectNotFoundExceptionがスローされます。
2. session.get()
-
常にhit the databaseであり、プロキシではなくデータベース行を表すオブジェクトである実際のオブジェクトを返します。
-
行が見つからない場合は、nullを返します。
パフォーマンスについてです
Hibernateは何らかの理由で何かを作成します。関連付けを行う場合、通常は関係を維持するために、データベースからオブジェクト(永続インスタンス)を取得して別のオブジェクトへの参照として割り当てます。 session.load()を使用する必要がある状況を理解するために、いくつかの例を見ていきましょう。
1. session.get()
たとえば、Stockアプリケーションでは、StockトランザクションとStockTransactionsが「1対多」の関係を持っている必要があります。株式トランザクションを保存する場合は、次のように宣言するのが一般的です
Stock stock = (Stock)session.get(Stock.class, new Integer(2)); StockTransaction stockTransactions = new StockTransaction(); //set stockTransactions detail stockTransactions.setStock(stock); session.save(stockTransactions);
出力
Hibernate: select ... from example.stock stock0_ where stock0_.STOCK_ID=? Hibernate: insert into example.stock_transaction (...) values (?, ?, ?, ?, ?, ?)
session.get()で、HibernateはデータベースにアクセスしてStockオブジェクトを取得し、StockTransactionへの参照として配置します。 ただし、この保存プロセスは非常に需要が高く、1時間あたり数千または数百万のトランザクションがある可能性があります。これは、ストックトランザクションレコードを保存するすべてのストックオブジェクトを取得するためにデータベースにアクセスするために必要だと思いますか? 結局のところ、StockTransactionへの参照として株式のIDが必要なだけです。
2. session.load()
上記のシナリオでは、session.load()が適切なソリューションになります。例を見てみましょう。
Stock stock = (Stock)session.load(Stock.class, new Integer(2)); StockTransaction stockTransactions = new StockTransaction(); //set stockTransactions detail stockTransactions.setStock(stock); session.save(stockTransactions);
出力
Hibernate: insert into example.stock_transaction (...) values (?, ?, ?, ?, ?, ?)
session.load()では、HibernateはStockオブジェクトを取得するためにデータベースにヒットせず(出力にselectステートメントはありません)、Stockプロキシオブジェクト(指定された識別値を持つ偽オブジェクト)を返します。 このシナリオでは、株式取引記録を保存するにはプロキシオブジェクトで十分です。
例外
例外の場合は、例を参照してください
session.load()
Stock stock = (Stock)session.load(Stock.class, new Integer(100)); //proxy //initialize proxy, no row for id 100, throw ObjectNotFoundException System.out.println(stock.getStockCode());
ID値がデータベースに存在しない場合でも、指定されたID値を持つプロキシオブジェクトを常に返します。 ただし、データベースからプロパティを取得してプロキシを初期化しようとすると、selectステートメントでデータベースにアクセスします。 行が見つからない場合、ObjectNotFoundExceptionがスローされます。
org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.example.common.Stock#100]
session.get()
//return null if not found Stock stock = (Stock)session.get(Stock.class, new Integer(100)); System.out.println(stock.getStockCode()); //java.lang.NullPointerException
ID値がデータベースで見つからない場合、常にnullを返します。
結論
常に正しい解決策が存在するわけではありません。その間の差異を理解し、アプリケーションで最も適切な修正方法を決定する必要があります。