MyBatisフレームワーク実行プロセス:
1. mybatis構成ファイル、sqlmapconfig.xml(名前は修正されていない)の構成
2。構成ファイルを介してMyBatisランニング環境をロードし、SQLSessionFactoryセッションファクトリを作成します
SQLSessionFactoryは、実際に使用されたときにシングルトンの方法で使用されます。
3. sqlsessionFactoryを介してSQLSessionを作成します
SQLSessionは、ユーザー指向のインターフェイス(動作データベースメソッドを提供)です。実装オブジェクトはスレッドインセンスです。 SQLSessionのアプリケーションシナリオはメソッド本体内にあることをお勧めします。
4. SQLSessionメソッドを呼び出して、データを操作します。
トランザクションをコミットする必要がある場合は、sqlsessionのcommit()メソッドを実行する必要があります。
5.リソースをリリースし、SQLSessionを閉鎖します
マッパーエージェント開発方法(推奨)
Mapperインターフェイス(つまり、DAOインターフェイス)を作成する必要があるプログラマのみ
プログラマーは、mapper.xml(ファイルのマッピング)とmapper.javaを作成する際に開発仕様に従う必要があります。
1。mapper.xmlの名前空間は、mapper.javaクラスのフルパスです。
2。mappper.xmlのステートメントのIDは、mappper.javaのメソッド名と同じです。
3. mapper.xmlのステートメントのパラメータ型は、入力パラメーターのタイプとmapper.javaメソッドの入力パラメーターのタイプを指定します。
4. mapper.xmlのステートメントの結果の結果は、mapper.javaメソッドの出力タイプと戻り値タイプを指定します。
この記事の内容:
注文製品データモデルを分析します。
高度なマッピング:(学習)
1対1のクエリ、1対多、および多くのクエリを実装します。
読み込み遅延
クエリキャッシュ
レベル1キャッシュ
レベル2キャッシュ(MyBatisレベル2キャッシュの使用シナリオを理解)
mybatis and spirng統合(マスター)
リバースエンジニアリング(使用できます)
製品データモデルを注文します
データモデル分析のアイデア
1。各テーブルに記録されているデータコンテンツ
モジュールごとに各テーブルに記録されたコンテンツに精通していることは、システムの要件(関数)の学習プロセスと同等です。
2。各テーブルの重要なフィールド設定
空ではないフィールド、外部キーフィールド
3.データベースレベルのテーブル間の関係
外国のキー関係
4。テーブル間のビジネス関係
テーブル間のビジネス関係を分析するときは、特定のビジネスの重要性に基づいて分析する必要があります。
データモデル分析
ユーザーテーブルユーザー:
購入した製品のユーザー情報を記録します
注文表:注文
ユーザーが作成した注文を記録します(アイテムを購入する注文)
注文の詳細:OrderDetail:
注文の詳細情報、つまり購入の情報を記録します
製品リスト:アイテム
記録された製品情報
テーブル間のビジネス関係:
テーブル間のビジネス関係を分析するときは、特定のビジネスの重要性に基づいて分析する必要があります。
最初に、データレベル間の関係があるテーブル間のビジネス関係を分析します。
USREと注文:
ユーザー--->注文:ユーザーは複数の注文を作成できます。
注文 - >ユーザー:注文は1人のユーザー、1対1のみによって作成されます
注文と注文:
注文> OrderDetail:注文には複数の注文の詳細を含めることができます。1つの注文は複数のアイテムを購入できるため、各アイテムの購入情報はOrderDetail、1対Many関係に記録されます。
注文>注文:注文の詳細は、1つの注文でのみ含めることができます。
OrderDetailとItemsm:
OrderDetail - > itemsms:1つの注文の詳細は、1つの製品情報のみに対応しています。
アイテム> OrderDetail:製品は複数の注文の詳細に含めることができます。
次に、テーブル間にデータベースレベルに関連していないビジネス関係があるかどうかを分析します。
注文とアイテム:
注文とアイテムの関係は、注文テーブルを介して確立できます。
ユーザーとアイテム:他のテーブルを介して多くの関係を構成する
1対1のクエリ
要件:注文情報をクエリし、注文を作成するためのクエリユーザー情報をクエリします
resultTypeを使用してクエリします
SQLステートメントの使用に関する考慮事項
クエリのプライマリテーブルを決定します:注文テーブル
クエリの関連テーブルを決定します:ユーザーテーブル
協会のクエリは内部リンクまたは外部リンクを使用しますか?
注文テーブルには外部キー(user_id)があるため、外部キーアソシエーションを介してユーザーテーブルを照会することで1つのレコードのみを見つけることができ、内部リンクを使用できます。
select orders。*、user.username、user.sex、user.address fromeders、user where where where arder.user_id = user.id
pojo(orderscustom.java)を作成する
上記のSQLクエリの結果をPOJOにマップします。これには、すべてのクエリ列名を含める必要があります。
元のOrders.javaはすべてのフィールドをマップすることはできず、新しく作成されたPojoが必要です。
多くのクエリフィールドを含むPOクラスを継承するPOクラスを作成します。
Ordersmappercustom.xml
Ordersmappercustom.java
テストクラスを作成します
Ordersmappercustom.javaファイルを右クリック> [新規]> [その他]> [Junitテストケース]> [テストする関数]を選択します
次のコードをOrdersmappercustomtest.javaに書き込みます。
public class rossionmappercustomtest {private sqlsessionfactory sqlsessionfactory; //この方法は、@beforepublic void setup()を実行することです。 resources.getResourceasStream(リソース); //セッションファクトリを作成してMyBatis構成でパスファイル情報sqlSessionFactory = new sqlsessionFactoryBuilder()。build(inputstream);}@testpublic void testfindordersuser()throws Exception {sqlSession sqlsession = SQLSESSIONSESSIONS = SQLSESSIONSESSIONSOPENS() Ordersmappercustom Ordersmappercustom = sqlsession.getMapper(Ordermappercustom.class); // Call Mapper Method List <Ordercustom> list = Ordersmappercustom.findordersuser(); system.out.println(list); sqlsession.close();};};resultmapを使用して照会します
SQLステートメント:SQLは同じ結果を実装しました
結果マップマッピングを使用するためのアイデア
結果マップを使用して、クエリ結果の注文情報を注文オブジェクトにマッピングし、注文クラスにユーザー属性を追加し、関連するクエリユーザー情報をOrdersオブジェクトのユーザー属性にマッピングします。
注文クラスにユーザー属性を追加します
Ordersmappercustom.xml
結果マップを定義します
Tyep:クエリ全体の結果を特定のクラスにマッピングすることを意味します。
ID:データベーステーブルのクエリ列の一意の識別子、注文情報の一意の識別子を表します。一意の識別子を形成する複数の列がある場合、複数のIDを構成します。
列:データベーステーブルの注文情報の一意の識別列
プロパティ:注文情報の一意の識別列によって注文にマッピングされたプロパティはどれですか?
関連:個々のオブジェクトを照会するための情報をマップするために使用されます
プロパティ:関連するクエリのユーザー情報をにマッピングするために注文するプロパティ
Javatype:ユーザーにマッピングしたプロパティ
<! - 関連するユーザーのresultmapは、クエリ全体のcn.itcast.mybatis.po.ordersの結果をマップします。一意の識別子を形成する複数の列がある場合、複数のidcolumnを構成します:注文情報の一意の識別列:注文情報の一意の識別子列によってマッピングされます。列= "note" Property = note/> <! - マッピングされた関連ユーザー情報を構成 - > <! - 関連する情報単一オブジェクトプロパティ:関連するクエリのユーザー情報をマップする注文のプロパティ - > <associateプロパティ= "user" javatype = "cn.itcast.mybatis.po.user" javatype:ユーザーにマッピングしたプロパティ - > <id column = "user_id" property = "id"/> <result column = "username" property "username"/> <result column = "sex" property = "sex"/> <result colummen
ステートメント定義
Ordersmappercustom.java
テストコード
@testpublic void testfindordersuserresultmap()スロー例外{sqlsession sqlsession = sqlsessionfactory.opensession(); //プロキシオブジェクトの作成マッピングマッパーストム= sqlsession.getmapper(ordersmapcustom.class); Ordermappercustom.findordersuserresultmap(); system.out.println(list); sqlsession.close();}resultTypeおよびresultMapは、1対1のクエリの概要を実装します
resultType:resultTypeを使用して実装するのは比較的簡単です。クエリ列名がPOJOに含まれていない場合、マッピングを完了するには、列名の対応する属性を追加する必要があります。
クエリ結果に特別な要件がない場合は、resultTypeを使用することをお勧めします。
結果マップ:結果マップは個別に定義する必要がありますが、これは少し面倒です。クエリ結果に特別な要件がある場合、ResultMapを使用すると、関連するクエリマッピングPOJOの属性が完了できます。
resultMapは怠zyなロードを実装できますが、resultTypeは怠zyなロードを実装できません。
1対多くのクエリ
要件:注文と注文の詳細情報をクエリします。
SQLステートメント
メインクエリテーブルを決定します:注文テーブル
関連するクエリテーブルを決定します:詳細テーブルを注文します
1対1のクエリに基づいて、注文詳細リストアソシエーションを追加するだけです。
selectOorders。*、user.username、user.sex、user.address、orderdetail.id orderdetail_id、orderdetail.items_id、orderdetail.items_num、orderdetail.orders_idfromorders、user、orderdetail where ards.user_id = user.id anddetail
分析:resultTypeを使用して、上記のクエリ結果をpojoにマッピングすると、注文情報は複製です。
要件:注文マッピングでは、重複したレコードは発生できません。
list <OrderDetail> OrderDetails Orders.javaクラスのプロパティを追加します。
最後に、注文情報は注文にマッピングされ、注文に対応する注文の詳細は注文のOrderDetailsプロパティにマッピングされます。
マッピングされた注文数は2です(注文情報は繰り返されません)
各注文のOrderDetailsプロパティは、注文に対応する注文の詳細を保存します。
注文属性属性を注文に追加するJavaを追加します
Ordersmappercustom.xml
結果マップ定義
注文情報とユーザー情報のマッピングを構成せずに、拡張継承を使用します
コレクション:複数のレコードを照会して、協会のクエリのコレクションオブジェクトにマップする
プロパティ:Associationクエリを複数のレコードにマッピングします。
oftype:リストコレクション属性のpojoにマップするタイプを指定します
<! - 注文と注文の詳細の結果マップは拡張機能を使用して継承され、注文情報とユーザー情報のマッピングを構成する必要はありません - > <resultmap type = "cn.itcast.mybatis.orders" id = "OrdersandOrderDetailResultmap" extendss = "extersultmap"注文情報とユーザー情報のマッピングを構成 - > <! - 注文情報の注文協会のクエリには複数の詳細があります。コレクションを使用してコレクションをマップするには:複数のレコードをコレクションオブジェクトプロパティにマッピング:マップアソシエーションクエリを複数のレコードにCN.ITCAST.MYBATIS.PO.ORDERSにマップします。注文の詳細の識別子cn.itcast.mybatis.po.orderdetail - > <id column = "orderdetail_id" property = "id"/> <result column = "items_id" property = "itemsid"/> <result colummen
Ordersmappercustom.java
テストコード:
@testpublic void testfindordersandordorderdetailresultmap()スロー例外{sqlsession sqlsession = sqlsessionfactory.opensession(); //プロキシオブジェクトの作成Mappercustom = sqlsession.getMapper(OrdersMaptercustom.clipper < Ordermappercustom.findordersandordorderdetailResultmap(); system.out.println(list); sqlsession.close();}まとめ
MyBatisは、ResultMapのコレクションを使用して、関連するクエリの複数のレコードをリストコレクションプロパティにマッピングします。
resultTypeを使用した実装:
注文の詳細のマッピング注文の注文では、自分で処理し、ダブルループを使用してレコードを横断し、重複した記録を削除し、注文の詳細を注文に配置する必要があります。
多くのクエリ
要件:ユーザーとユーザーの購入情報をクエリします。
SQLステートメント
クエリメインテーブルは次のとおりです。ユーザーテーブル
関連表:ユーザーと製品は直接関連していないため、注文と注文の詳細を通じて関連しているため、協会のテーブル:注文、注文、アイテムは
注文を選択します。*、user.username、user.sex、user.address、orderdetail.id orderdetail_id、orderdetail.items_id、roderdetail.items_num、orderdetail.orders_id、アイテムuser.id and orderdetail.orders_id = Orders.id and Orderdetail.items_id = items.id
マッピングのアイデア
ユーザー情報をユーザーにマップします。
ユーザークラスに注文リスト属性リスト<DordersList <DorderSlistを追加して、ユーザーが作成した注文をOrderSlistにマッピングする
注文詳細リストプロパティリスト<OrderDetail> OrderDetialsは注文のマップをマップします
注文の詳細に対応するアイテムをアイテムにマッピングするために、順序付けのアイテムプロパティを追加します
Ordersmappercustom.xml
結果マップ定義
<! - ユーザーと購入した製品をクエリします - > <resultmap type = "cn.itcast.mybatis.user" id = "useranditemsresresultmap"> <! - ユーザー情報 - > <id column = "user_id" property = "id"/> <result column = "username" property "/> <result列="プロパティ= "アドレス"/> <! - 情報を注文するユーザーは複数の注文に対応し、コレクションマッピングを使用します - > <collectionプロパティ= "orderslist" oftype = "cn.itcast.mybatis.po.orders"> <id column = "id" id "/> <result column =" user_id "" userid "プロパティ= "createTime"/> <result column = "note" property = "note"/> <! - 注文詳細を含む1つの注文 - > <コレクションプロパティ= "orderdetails" oftype = "cn.itcast.mybatis.po.orderdetail"プロパティ= "itemsnum"/> <result column = "order_id" property = "orderid"/> <! - 注文の詳細は製品に対応します - > <Associationプロパティ= "items" javatype = "cn.itcast.mybatis.items"> <id column = "items_id" property = "id/> <result colummad =" untresd_name = ""/< Property = "detail"/> <result column = "items_price"プロパティ= "価格"/> </association> </collection> </collection> </resultmap>
Ordersmappercustom.java
テストコード:
@testpublic void testfinduseranditemsresultmap()スロー例外{sqlsession sqlsession = sqlsessionfactory.opensession(); //プロキシオブジェクトの作成命令mappercustom = sqlsession.getmapper(rosdersmactom.class); Ordermappercustom.finduseranditemsResultMap(); system.out.println(list); sqlsession.close();}多くのクエリの概要
ユーザーが購入した製品情報の詳細なリストはチェックされます(ユーザー名、ユーザーアドレス、製品名、購入時間、購入数)
上記の要件に応じて、resultTypeを使用してクエリレコードを拡張されたpojoにマッピングします。これは、詳細リストの機能を実装するのが非常に簡単です。
1対Manyは、次のように、多くの人から多数の特別なケースです。
ユーザーが購入した製品情報を照会する場合、ユーザーと製品の関係は多目的な関係です。
要件1:
クエリフィールド:ユーザーアカウント、ユーザー名、ユーザー性別、製品名、製品価格(最も一般的)
エンタープライズ開発の一般的な詳細リスト、ユーザーが購入した製品の詳細なリスト、
resultTypeを使用して、上記のクエリ列をPOJO出力にマッピングします。
要件2:
クエリフィールド:ユーザーアカウント、ユーザー名、購入されたアイテムの数量、製品の詳細(詳細を表示するためのマウス)
結果マップを使用して、ユーザーの購入した製品の詳細リストをユーザーオブジェクトにマップします。
要約:
ResultMapの使用は、複数のリストを含むリストに特別な要件をマッピングするなど、クエリ結果マッピングに特別な要件を持つ関数のためのものです。
resultTypeおよびresultmapの概要
resultType:
効果:
クエリの結果をマップして、SQL列名pojo属性名の一貫性に従ってpojoにマップします。
機会:
ユーザーが製品の詳細を購入し、関連するすべてのクエリ情報をページに表示する場合など、詳細なレコードの一般的な表示では、resultTypeを使用して各レコードをマップできます。
Pojoに撃ち、フロントエンドページでリスト(リストのPojo)をトラバースします。
結果マップ:
アソシエーションとコレクションを使用して、1対1で1対1の高度なマッピングを完了します(結果には特別なマッピング要件があります)。
協会:
効果:
関連するクエリ情報をPojoオブジェクトにマップします。
機会:
関連する情報のクエリを容易にするために、関連する注文情報を使用して、次のようなユーザーオブジェクトのPOJO属性にマッピングできます。
resultTypeを使用することは、クエリ結果をpojoオブジェクトのpojo属性にマップすることはできません。結果セットクエリを通過するニーズに応じて、resultTypeまたはresultMapを使用するかどうかを選択します。
コレクション:
効果:
関連するクエリ情報をリストコレクションにマップします。
機会:
トラバーサルアソシエーション情報のクエリを促進するために、コレクションを使用して、ユーザー許可スコープモジュールのクエリとモジュールのメニューをクエリするなど、コレクションをリストコレクションにマッピングできます。コレクションを使用して、モジュールリストをマップしてモジュールオブジェクトのメニューリスト属性をマッピングできます。これの目的は、クエリ結果セットのトラバーサルクエリを促進することでもあります。
resultTypeを使用する場合、クエリ結果をリストコレクションにマップすることはできません。
読み込み遅延
ResultMapは、高度なマッピングを実装できます(アソシエーションとコレクションを使用して、1対1のマッピングを実装します)。協会とコレクションには、怠zyなロード機能があります。
必要:
注文が照会され、ユーザー情報が関連付けられている場合。最初に要件を満たすために注文情報を照会した場合、ユーザー情報をクエリする必要がある場合にユーザー情報を照会します。需要のユーザー情報のクエリは、負荷が遅れています。
読み込みの遅延:単一のテーブルからの最初のクエリ、そして必要に応じて関連するテーブルからのクエリは、単一のテーブルのクエリが複数のテーブルを照会するよりも速くなるため、データベースのパフォーマンスを大幅に改善します。
関連性を使用して、怠zyな読み込みを実装します
要件:クエリの注文とアソシエイトクエリユーザー情報
ordresmappercustom.xml
2つのマッパーメソッドに対応するステートメントを定義する必要があります。
1.注文情報のみ
select * from注文
アソシエーションを使用して、クエリ順序のステートメントでの次の満足度(Associate Queryユーザー情報)の読み込みを遅らせる(実行)
2。関連するクエリユーザー情報
user_idは、上記の注文情報クエリでuser_idをフォローしてユーザー情報を照会するために使用されます
usermapper.xmlでfinduserbyidを使用します
上記は最初にfindordersuserlazyloadingを実行し、ユーザーを照会する必要がある場合、finduserbyidを実行すると、遅延ロードと実行が結果マップの定義を介して構成されます。
結果マップの読み込みを遅らせます
協会で選択を使用して、レイジーロードによって実行されるステートメントのIDを指定します。
<! - lazy loaded resultmap-> <resultmap type = "cn.itcast.mybatis.po.orders" id = "orderserlazyloadingresultmap"> <! - 注文情報のマッピング構成 - > <id column = "id" property = "id"/> <result column = "userid"/> <ructs columnid "/>>>>>> <result columm列= "createtime" property = "createTime"/> <result column = "note" bote = "note"/> <! - 注文情報のマッピング構成 - > <id column = "id" property = "user_id"プロパティ= "userid"/> <result列= "number" jumber = "number"/> <result column = "createTime"
選択:怠zyなロードのために実行されるステートメントのIDを指定します(user_idに基づいてユーザー情報を照会するステートメント)
usermapper.xmlでfinduserbyidを使用して、ユーザーID(user_id)ユーザー情報に基づいてクエリを完了します。 finduserbyidがこのマッパーにない場合は、その前に名前空間を追加する必要があります。
列:ユーザー情報クエリに関連付けられた注文情報の列はuser_idです
AssociationクエリのSQLは、次のように理解されます。
[注文]を選択してください。(Orders.user_id = user.idのユーザーからユーザー名を選択します。ユーザーからusers.user_id = user.id)sexfrom Orders - > <associateプロパティ= "user" javatype = "cn.itcast.mybatis.po.user" select = "cn.it.mybatis.mybatis.mapper. column = "user_id"> <! - ユーザー情報のレイジーロード - > </association> </resultmap>
Orderesmappercustom.java
テストのアイデア:
1.上記のマッパーメソッド(FindOrderSuserLazyLoading)を実行し、cn.itcast.mybatis.mapper.ordersmappercustomでfindordersuserlazyloadingを呼び出します。
2。プログラムでは、前のステップでQueryed <Orders>を通過します。 Getuserメソッドを注文して呼び出すと、怠zyなロードを開始します。
3.読み込み遅延、Usermapper.xmlのfinduserbyidメソッドを呼び出して、ユーザー情報を取得します。
怠zyな負荷構成
MyBatisはデフォルトで怠zyなロードを有効にしないため、sqlmapconfig.xmlで構成する必要があります。
mybatisコア構成ファイルで構成:
項目説明許容値のデフォルト値を設定します
lazyloadingEnabledグローバルに怠zyなロードを設定します。 「false」に設定すると、関連するすべてのものが初期化され、ロードされます。真または偽
AggressivelazyLoading「True」に設定すると、怠zyなロードオブジェクトはすべての怠zyなプロパティによってロードされる場合があります。それ以外の場合、各プロパティは必要に応じてロードされます。 trueまたはfalse true
sqlmapconfig.xmlの構成:
テストコード
遅延荷重について考えています
MyBatisが提供する関連性とコレクションを使用せずに怠zyなロードを達成する方法は?
実装方法は次のとおりです。
2つのマッパーメソッドを定義します。
1。注文リストをクエリします
2。ユーザーIDに基づくユーザー情報をクエリします
実装のアイデア:
最初に最初のマッパーメソッドを確認し、注文情報リストを取得します
プログラム(サービス)で、必要に応じて2番目のマッパーメソッドを呼び出して、ユーザー情報を照会します。
要するに、Lazy Loading Methodを使用して、単純なSQL(できれば単一のテーブルで、クエリを関連付けることもできます)を照会し、必要に応じて関連するクエリの他の情報をロードします。
クエリキャッシュ
MyBatisは、データ圧力を軽減し、データベースのパフォーマンスを改善するためのクエリキャッシュを提供します。
MyBaitsは、第1レベルのキャッシュとセカンドレベルのキャッシュを提供します。
レベル1キャッシュは、SQLSessionレベルのキャッシュです。データベースを操作するときは、SQLSessionオブジェクトを構築する必要があり、キャッシュデータを保存するためにオブジェクトにデータ構造(ハッシュマップ)があります。さまざまなSQLSesions間のキャッシュされたデータ領域(ハッシュマップ)は、互いに影響しません。
セカンダリキャッシュはマッパーレベルのキャッシュです。複数のSQLSessionsが同じマッパーのSQLステートメントを操作します。複数のsqlsessionsは、セカンダリキャッシュを共有できます。セカンダリキャッシュはCrossSQLSessionです。
なぜキャッシュを使用するのですか?
キャッシュにデータがある場合、データベースから取得する必要はありません。これにより、システムのパフォーマンスが大幅に向上します。
レベル1キャッシュ
第1レベルのキャッシュ作業原則
ユーザーID 1を使用してユーザー情報のクエリを初めて開始したとき、最初に、キャッシュにID 1のユーザー情報があるユーザー情報があるかどうかを調べます。そうでない場合は、データベースからユーザー情報をクエリします。
ユーザー情報を取得し、ユーザー情報を最初のレベルのキャッシュに保存します。
SQLSessionがコミット操作を実行し(挿入、更新、削除を実行)、SQLSessionで第1レベルのキャッシュをクリアします。これの目的は、キャッシュを最新の情報を保存し、汚い読みを避けることです。
ユーザーID 1を使用してユーザー情報のクエリを2回目に開始したとき、最初に、キャッシュにID 1のユーザー情報があるユーザー情報があるかどうかを調べます。キャッシュに1つある場合、キャッシュからユーザー情報を直接取得します。
レベル1キャッシュテスト
MyBatisは、デフォルトで最初のレベルのキャッシュをサポートしており、構成ファイルで構成する必要はありません。
上記のレベル1のキャッシュ原則の手順に従って、テストします。
//ordersmappercusntomtest.java@testpublic void testcache1()throws exception {sqlsession sqlsession = sqlsessionfactory.opensession(); //プロキシオブジェクトUsermapper usermapper = sqlsession.getmapper(usermapper.class // ID 1のユーザーはQueryユーザーユーザー1 = usermapper.finduserbyid(1); system.out.println(user1); // sqlsessionがコミット操作を実行する場合(挿入、更新、削除を実行)、sqlsessionの第1レベルのキャッシュをクリアします。これの目的は、キャッシュを最新の情報を保存し、汚い読みを避けることです。 // user1の情報user1.setusername( "test user22");を更新します。 usermapper.updateuser(user1); //コミット操作を実行してcache sqlsession.commit(); // 2番目の要求を開始し、id 1 user2 = usermapper.finduserbyid(1); system.out.println(user2); sqlsession.close();}レベル1キャッシュアプリケーション
正式な開発は、MyBatisとSpringを統合することであり、トランザクションはサービスで管理されています。
サービス方法には、多くのマッパーメソッド呼び出しが含まれます。
サービス{//実行を開始するときは、トランザクションを開始してSQLSessionオブジェクトを作成します//初めてMapperのメソッドを呼び出しますfinduserbyid(1)//セル2回目のMapperのメソッド(1)、1レベルのキャッシュからデータを取得する//メソッドは終了します。同じユーザー情報を照会するために2つのサービスコールを実行すると、セッションメソッドが終了するため、最初のレベルのキャッシュに移動しません。SQLSessionは閉じられ、第1レベルのキャッシュがクリアされます。
レベル2キャッシュ
原理
まず、MyBatisの第2レベルのキャッシュを有効にします。
sqlsession1 querysユーザーIDを使用してユーザー情報1。ユーザー情報を照会する場合、クエリデータはセカンダリキャッシュに保存されます。
SQLSESSION3が同じマップでSQLを実行する場合、コミット送信を実行し、マッパーの下のセカンダリキャッシュ領域のデータをクリアします。
SQLSESSION2は、ユーザーID 1を使用してユーザー情報を照会し、キャッシュにデータがあるかどうかを見つけます。存在する場合、データはキャッシュから直接取得されます。
二次キャッシュと一次キャッシュの違いは大きいです。二次キャッシュの範囲は大きいです。複数のSQLSessionsは、Usermapperのセカンダリキャッシュ領域を共有できます。
UserMapperにはセカンダリキャッシュ領域(名前空間で細分化された)があり、他のマッパーには独自のセカンダリキャッシュ領域(名前空間で細分化されています)もあります。
各名前空間マッパーには2番目のキャッシュ領域があります。 2つのマッパーの名前空間が同じ場合、2つのマッパーは、データがSQLによって実行されるときに同じ2番目のキャッシュ領域を持ちます。
レベル2キャッシュをオンにします
MyBaitsの第2レベルのキャッシュは、マッパー範囲レベルです。 sqlmapconfig.xmlの第2レベルのキャッシュのメインスイッチを設定することに加えて、特定のmapper.xmlで2レベルのキャッシュも有効にする必要があります。
コア構成ファイルsqlmapconfig.xmlに追加されました
<name = "cacheenabled" value = "true"/>を設定します
説明許可値デフォルト値
この構成ファイルの下にあるすべてのキャッシュのグローバルなオン/オフ設定。真または偽
usermapper.xmlのセカンダリキャッシュをオンにし、usermapper.xmlのSQL実行はキャッシュ領域(HashMap)に保存されます。
Pojoクラスに電話して、シリアル化インターフェイスを実装してください
キャッシュされたデータを抽出するために、二次キャッシュされたデータストレージメディアは多様でメモリが異なるため、敏arialialization操作が実行されます。
レベル2キャッシュテスト
@testpublic void testcache2()スロー例外{sqlsession sqlsession1 = sqlsessionfactory.opensession(); sqlsession sqlsessionfactory.opensession(); sqlsession sqlsession3 = sqlsessionfactory.opensession(); sqlsession1.getMapper(usermapper.class); //最初のリクエストを開始し、ID 1ユーザー1 = usermapper1.finduserbyid(1); system.out.println(user1); //ここで緊密な操作を実行し、Sqlsession sqlsessionのsqlsessionのsqlsessionのデータを作成し、sqlsessionのsqlsessionのデータを作成し、 commit()operation usermapper usermapper3 = sqlsession3.getmapper(usermapper.class); user user = usermapper3.finduserbyid(1); user.setUsername( "zhang mingming"); usermapper3.updateuser(user); sqlsession3.commit(); sqlsession3.close(); usermapper usermapper2 = sqlsession2.getMapper(usermapper.class); // id 1ユーザーをユーザーに照会するために2番目のリクエストを送信します。UseCache構成
ステートメントでusecache = falseの設定は、現在のSelectステートメントのセカンダリキャッシュを無効にする可能性があります。つまり、各クエリはSQLを照会します。デフォルトは真です。つまり、SQLはセカンダリキャッシュを使用します。
<select id = "findOrderListResultMap" resultMap = "OrderSusermap" usecache = "false">
概要:クエリごとに、最新のデータSQLが必要です。 usecache = falseに設定し、二次キャッシュを無効にします。
キャッシュを更新します
キャッシュをクリアするだけです
マッパーの同じ名前空間では、操作データを他の挿入、更新、または削除した場合、キャッシュを更新する必要があり、キャッシュが更新されない場合は、汚い読み取りが発生します。
flushcache =” true”プロパティをステートメント構成に設定します。デフォルトでは、それは本当です。つまり、キャッシュが更新されます。 Falseに変更された場合、更新されません。キャッシュを使用する場合、データベーステーブルのクエリデータを手動で変更すると、Dirty Readが発生します。
<挿入id = "insertuser" parametertype = "cn.itcast.mybatis.po.user" flushcache = "true">
概要:一般的に、コミット操作を実行した後、キャッシュを更新する必要があります。 flushcache = trueとは、キャッシュを更新することを意味します。これは、データベースの汚れを避けることができます。
mybatis統合ehcache
ehcache是一个分布式缓存框架。
分布缓存
我们系统为了提高系统并发,性能、一般对系统进行分布式部署(集群部署方式)
不使用分布缓存,缓存的数据在各各服务单独存储,不方便系统开发。所以要使用分布式缓存对缓存数据进行集中管理。
mybatis无法实现分布式缓存,需要和其它分布式缓存框架进行整合。
整合ehcache方法(掌握)
mybatis提供了一个cache接口,如果要实现自己的缓存逻辑,实现cache接口开发即可。
mybatis和ehcache整合,mybatis和ehcache整合包中提供了一个cache接口的实现类。
mybatis默认实现cache类是:
加入ehcache包
整合ehcache
配置mapper中cache中的type为ehcache对cache接口的实现类型。
加入ehcache的配置文件(在classpath下配置ehcache.xml)
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"><diskStore path="F:/develop/ehcache" /><defaultCache maxElementsInMemory="1000" maxElementsOnDisk="10000000"eternal="false" overflowToDisk="false" timeToIdleSeconds="120"timeToLiveSeconds="120" diskExpiryThreadIntervalSeconds="120"memoryStoreEvictionPolicy="LRU"></defaultCache></ehcache>
属性说明:
diskStore:指定数据在磁盘中的存储位置。
defaultCache:当借助CacheManager.add(“demoCache”)创建Cache时,EhCache便会采用<defalutCache/>指定的的管理策略
以下属性是必须的:
maxElementsInMemory - 在内存中缓存的element的最大数目
maxElementsOnDisk - 在磁盘上缓存的element的最大数目,若是0表示无穷大
eternal - 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断
overflowToDisk - 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上
以下属性是可选的:
timeToIdleSeconds - 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大
timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大
diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区.
diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。
diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每个120s,相应的线程会进行一次EhCache中数据的清理工作
memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)
二级应用场景
对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,提高访问速度,业务场景比如:耗时较高的统计分析sql、电话账单查询sql等。
实现方法如下:通过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,比如设置为30分钟、60分钟、24小时等,根据需求而定。
二级缓存局限性
mybatis二级缓存对细粒度的数据级别的缓存实现不好,比如如下需求:对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品信息,此时如果使用mybatis的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息,因为mybaits的二级缓存区域以mapper为单位划分,当一个商品信息变化会将所有商品信息的缓存数据全部清空。解决此类问题需要在业务层根据需求对数据有针对性缓存。