Mybatis【20】--Mybatis遅延ロードはどのように処理しますか?
16119 ワード
注意:コードは
関連オブジェクトのロードタイプ
mybatisの関連オブジェクトのクエリーselect文の実行タイミングは、3種類に分けられ、直接ロード、侵入ロード、深さ遅延ロードに分けられます.
1.ダイレクトロード
プライマリ・ロード・オブジェクトのselect文を実行すると、関連オブジェクトのselect文がすぐに実行されます.
2.侵入式遅延負荷
プライマリ・ロード・オブジェクトに対するクエリーを実行する場合、関連オブジェクトのクエリーは実行されませんが、プライマリ・ロード・オブジェクトの詳細にアクセスすると、すぐに関連オブジェクトのselectクエリーが実行されます.つまり、関連オブジェクトのクエリー実行は、プライマリ・ロード・オブジェクトの詳細アクセスに侵入し、関連オブジェクトの詳細がプライマリ・ロード・オブジェクトの詳細に侵入し、その一部として現れたことが理解できます.
3.深さ遅延ロード
プライマリ・ロード・オブジェクトに対するクエリーを実行する場合、関連オブジェクトに対するクエリーは実行されず、プライマリ・ロード・オブジェクトの詳細にアクセスする場合、関連オブジェクトのselectクエリーも実行されず、本当に関連オブジェクトの詳細にアクセスする場合にのみ、関連オブジェクトに対するselectクエリーが実行されます.
注意:遅延ロードの最も基本的な要件は、関連オブジェクトのクエリーとプライマリ・ロード・オブジェクトのクエリーがそれぞれ2つの文に配置されている必要があります.マルチテーブル接続クエリーは、複数のテーブルを1つのテーブルに接続するクエリーに相当するため、クエリーを分割することはできません.一度にテーブルの内容をクエリーします.
遅延ロードは、一対多、一対一、多対一、多対多の関連クエリーに適用できます.
たとえば、前の
対応するエンティティークラス:
プライマリプロファイル
対応する
使用するツールクラス:
クエリーの直接ロード
怠惰ロードの構成については、
ユニットテストが
その結果、2つの
侵入遅延負荷
遅延ロードスイッチをオンにする必要がある(
1.
結果は次のとおりです.sqlは1つしかありません.
その結果、関連オブジェクト
デプスディレイロード
遅延ローディングスイッチ
1.
2.
結果は次のとおりです.
3.
結果は、
ロードモード
lazyLoadingEnabled
aggressiveLazyLoading
ダイレクトロード
falseでなければなりません.デフォルトはfalseです.
何でもlazyLoadingEnabledがfalseなら直接ロード
侵入遅延負荷
trueでなければなりません
trueでなければなりません
デプスディレイロード
trueでなければなりません
falseでなければなりません.デフォルトはfalseです.
【作者紹介】:秦懐、公衆号【秦懐雑貨店】作者、技術の道は一時的ではなく、山が高く水が長く、たとえゆっくりしていても、走っても止まらない.個人の書く方向:Javaのソースコードの解析、JDBC、Mybatis、Spring、redis、分布式、剣はOfferを指して、LeetCodeなど、真剣に1篇の文章を書いて、タイトル党が好きではありませんて、派手なことが好きではありませんて、大部分はシリーズの文章を書いて、私が書いたのがすべて完全に正しいことを保証することができなくて、しかし私が書いたのはすべて実践あるいは資料を探すことを保証します.漏れや間違いは、指摘してください.
2020年に何を書きましたか?
オープンソースプログラミングノート
平日の時間は貴重で、夜と週末の時間を使って書くことしかできません.私に注目して、一緒に成長しましょう.
GitHub
に管理されています.住所はhttps://github.com/Damaer/Mybatis-Learning
、プロジェクトはmybatis-16-lazyload
です.自分で取る必要があります.maven環境とmysql
環境を配置する必要があります(sql
文はresource
の下のtest.sql
にあります).役に立つと思います.小さな星を点けます.docsify
ドキュメントアドレス:https://damaer.github.io/Mybatis-Learning/#/
mybatis
の怠惰なロードは、遅延ロードとも呼ばれ、関連クエリーを行う際に、設定された遅延規則に従って関連オブジェクトに対するselect
クエリーを遅延させ、遅延ロードはデータベース圧力を効果的に低減することができる.遅延ロードは関連オブジェクトにのみ遅延設定があり、プライマリ・ロード・オブジェクトはクエリー文を直接実行します.関連オブジェクトのロードタイプ
mybatisの関連オブジェクトのクエリーselect文の実行タイミングは、3種類に分けられ、直接ロード、侵入ロード、深さ遅延ロードに分けられます.
1.ダイレクトロード
プライマリ・ロード・オブジェクトのselect文を実行すると、関連オブジェクトのselect文がすぐに実行されます.
2.侵入式遅延負荷
プライマリ・ロード・オブジェクトに対するクエリーを実行する場合、関連オブジェクトのクエリーは実行されませんが、プライマリ・ロード・オブジェクトの詳細にアクセスすると、すぐに関連オブジェクトのselectクエリーが実行されます.つまり、関連オブジェクトのクエリー実行は、プライマリ・ロード・オブジェクトの詳細アクセスに侵入し、関連オブジェクトの詳細がプライマリ・ロード・オブジェクトの詳細に侵入し、その一部として現れたことが理解できます.
3.深さ遅延ロード
プライマリ・ロード・オブジェクトに対するクエリーを実行する場合、関連オブジェクトに対するクエリーは実行されず、プライマリ・ロード・オブジェクトの詳細にアクセスする場合、関連オブジェクトのselectクエリーも実行されず、本当に関連オブジェクトの詳細にアクセスする場合にのみ、関連オブジェクトに対するselectクエリーが実行されます.
注意:遅延ロードの最も基本的な要件は、関連オブジェクトのクエリーとプライマリ・ロード・オブジェクトのクエリーがそれぞれ2つの文に配置されている必要があります.マルチテーブル接続クエリーは、複数のテーブルを1つのテーブルに接続するクエリーに相当するため、クエリーを分割することはできません.一度にテーブルの内容をクエリーします.
遅延ロードは、一対多、一対一、多対一、多対多の関連クエリーに適用できます.
たとえば、前の
demo
を使用して、minister
とcountry
の関係をクエリーします.データベースは次のようになります.#
CREATE DATABASE `test` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
#
CREATE TABLE `test`.`student` ( `sid` INT(10) NOT NULL AUTO_INCREMENT ,`sname` VARCHAR(20) NOT NULL ,PRIMARY KEY(`sid`)) ENGINE = MyISAM;
CREATE TABLE `test`.`course` ( `cid` INT(10) NOT NULL AUTO_INCREMENT ,`cname` VARCHAR(20) NOT NULL ,PRIMARY KEY(`cid`)) ENGINE = MyISAM;
CREATE TABLE `test`.`middle` (
`id` INT(10) NOT NULL AUTO_INCREMENT ,`studentId` INT(10) NOT NULL ,`courseId` INT(10) NOT NULL ,PRIMARY KEY(`id`)) ENGINE = MyISAM;
#
INSERT INTO `course` (`cid`, `cname`) VALUES ('1', 'JAVA') ;
INSERT INTO `course` (`cid`, `cname`) VALUES ('2', 'C++') ;
INSERT INTO `course` (`cid`, `cname`) VALUES ('3', 'JS') ;
INSERT INTO `student` (`sid`, `sname`) VALUES ('1', 'Jam') ;
INSERT INTO `student` (`sid`, `sname`) VALUES ('2', 'Lina') ;
INSERT INTO `middle` (`id`, `studentId`, `courseId`) VALUES ('1', '1', '1');
INSERT INTO `middle` (`id`, `studentId`, `courseId`) VALUES ('2', '1', '2');
INSERT INTO `middle` (`id`, `studentId`, `courseId`) VALUES ('3', '2', '1');
INSERT INTO `middle` (`id`, `studentId`, `courseId`) VALUES ('4', '2', '3');
対応するエンティティークラス:
Country.class
public class Country {
private Integer cid;
private String cname;
private Set ministers;
public Integer getCid() {
return cid;
}
public void setCid(Integer cid) {
this.cid = cid;
}
public String getName() {
return cname;
}
public void setName(String cname) {
this.cname = cname;
}
public Set getMinisters() {
return ministers;
}
public void setMinisters(Set ministers) {
this.ministers = ministers;
}
@Override
public String toString() {
return "Country [cid=" + cid + ", cname=" + cname + ", ministers="
+ ministers + "]";
}
}
Minister.class
:リーダーエンティティクラスpublic class Minister {
private Integer mid;
private String mname;
@Override
public String toString() {
return "Minister [mid=" + mid + ", mname=" + mname + "]";
}
public Integer getMid() {
return mid;
}
public void setMid(Integer mid) {
this.mid = mid;
}
public String getMname() {
return mname;
}
public void setMname(String mname) {
this.mname = mname;
}
}
プライマリプロファイル
mybatis.xml
:
mapper.xml
ファイル:
対応する
sql
インタフェース:public interface ICountryDao {
Country selectCountryById(int cid);
}
使用するツールクラス:
public class MyBatisUtils {
private static SqlSessionFactory sqlSessionFactory;
public static SqlSession getSqlSession() {
InputStream is;
try {
is = Resources.getResourceAsStream("mybatis.xml");
if (sqlSessionFactory == null) {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
}
return sqlSessionFactory.openSession();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
クエリーの直接ロード
怠惰ロードの構成については、
mybatis.xml
ファイルの中で
を使用するだけでいいです.怠惰ロードには総スイッチがあり、lazyloadingEnabled
、false
に設定すれば遅延ロードをオフにすることができます.それは直接クエリーをロードすることです.
と
の間に配置される.
ユニットテストが
country
対象である場合: @Test
public void TestselectCountryById(){
Country country=dao.selectCountryById(1);
}
その結果、2つの
sql
が表示され、country
のクエリーに加えて、minister
の関連オブジェクトとともにクエリーされます.これは直接ロードです.簡単で乱暴です.使用するかどうかにかかわらず、まず関連クエリーをロードします.[service] 2018-07-17 09:59:00,796 - dao.ICountryDao.selectCountryById -491 [main] DEBUG dao.ICountryDao.selectCountryById - ==> Preparing: select cid,cname from country where cid=?
[service] 2018-07-17 09:59:00,823 - dao.ICountryDao.selectCountryById -518 [main] DEBUG dao.ICountryDao.selectCountryById - ==> Parameters: 1(Integer)
[service] 2018-07-17 09:59:00,838 - dao.ICountryDao.selectMinisterByCountry -533 [main] DEBUG dao.ICountryDao.selectMinisterByCountry - ====> Preparing: select mid,mname from minister where countryId=?
[service] 2018-07-17 09:59:00,838 - dao.ICountryDao.selectMinisterByCountry -533 [main] DEBUG dao.ICountryDao.selectMinisterByCountry - ====> Parameters: 1(Integer)
[service] 2018-07-17 09:59:00,849 - dao.ICountryDao.selectMinisterByCountry -544 [main] DEBUG dao.ICountryDao.selectMinisterByCountry - <==== Total: 2
[service] 2018-07-17 09:59:00,850 - dao.ICountryDao.selectCountryById -545 [main] DEBUG dao.ICountryDao.selectCountryById - <== Total: 1
侵入遅延負荷
遅延ロードスイッチをオンにする必要がある(
true
)と、侵入式ロードスイッチをオンにする必要がある(true
)
1.
country
のみを検索する場合、country
のクエリーのみが実行され、関連クエリーminister
は実行されません. @Test
public void TestselectCountryById(){
Country country=dao.selectCountryById(1);
}
結果は次のとおりです.sqlは1つしかありません.
[service] 2018-07-17 14:30:55,471 - dao.ICountryDao.selectCountryById -902 [main] DEBUG dao.ICountryDao.selectCountryById - ==> Preparing: select cid,cname from country where cid=?
[service] 2018-07-17 14:30:55,494 - dao.ICountryDao.selectCountryById -925 [main] DEBUG dao.ICountryDao.selectCountryById - ==> Parameters: 1(Integer)
[service] 2018-07-17 14:30:55,590 - dao.ICountryDao.selectCountryById -1021 [main] DEBUG dao.ICountryDao.selectCountryById - <== Total: 1
country
のプロパティをクエリーしますが、minister
のプロパティをクエリーしない場合: @Test
public void TestselectCountryById(){
Country country=dao.selectCountryById(1);
System.out.println(country.getCid());
}
その結果、関連オブジェクト
minister
にロードされます.これが侵入遅延ロードです.[service] 2018-07-17 14:32:37,959 - dao.ICountryDao.selectCountryById -724 [main] DEBUG dao.ICountryDao.selectCountryById - ==> Preparing: select cid,cname from country where cid=?
[service] 2018-07-17 14:32:37,979 - dao.ICountryDao.selectCountryById -744 [main] DEBUG dao.ICountryDao.selectCountryById - ==> Parameters: 1(Integer)
[service] 2018-07-17 14:32:38,170 - dao.ICountryDao.selectCountryById -935 [main] DEBUG dao.ICountryDao.selectCountryById - <== Total: 1
[service] 2018-07-17 14:32:38,171 - dao.ICountryDao.selectMinisterByCountry -936 [main] DEBUG dao.ICountryDao.selectMinisterByCountry - ==> Preparing: select mid,mname from minister where countryId=?
[service] 2018-07-17 14:32:38,171 - dao.ICountryDao.selectMinisterByCountry -936 [main] DEBUG dao.ICountryDao.selectMinisterByCountry - ==> Parameters: 1(Integer)
[service] 2018-07-17 14:32:38,173 - dao.ICountryDao.selectMinisterByCountry -938 [main] DEBUG dao.ICountryDao.selectMinisterByCountry - <== Total: 2
1
デプスディレイロード
遅延ローディングスイッチ
lazyLoadingEnabled
をオンにする必要があり(true
)、同時に侵入ローディングスイッチaggressivelazyLoading
をオフにする必要がある(false
)
1.
country
のみがクエリされた場合、country
のみがクエリされ、minister
はクエリされません.ユニットテストコード: @Test
public void TestselectCountryById(){
Country country=dao.selectCountryById(1);
}
[service] 2018-07-17 14:20:38,608 - dao.ICountryDao.selectCountryById -1271 [main] DEBUG dao.ICountryDao.selectCountryById - ==> Preparing: select cid,cname from country where cid=?
[service] 2018-07-17 14:20:38,631 - dao.ICountryDao.selectCountryById -1294 [main] DEBUG dao.ICountryDao.selectCountryById - ==> Parameters: 1(Integer)
[service] 2018-07-17 14:20:38,980 - dao.ICountryDao.selectCountryById -1643 [main] DEBUG dao.ICountryDao.selectCountryById - <== Total: 1
2.
country
のプロパティにアクセスしても、関連クエリのminister
はロードされません. @Test
public void TestselectCountryById(){
Country country=dao.selectCountryById(1);
System.out.println(country.getCid());
}
結果は次のとおりです.
[service] 2018-07-17 14:24:03,004 - org.apache.ibatis.transaction.jdbc.JdbcTransaction -686 [main] DEBUG org.apache.ibatis.transaction.jdbc.JdbcTransaction - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@cb51256]
[service] 2018-07-17 14:24:03,030 - dao.ICountryDao.selectCountryById -712 [main] DEBUG dao.ICountryDao.selectCountryById - ==> Preparing: select cid,cname from country where cid=?
[service] 2018-07-17 14:24:03,078 - dao.ICountryDao.selectCountryById -760 [main] DEBUG dao.ICountryDao.selectCountryById - ==> Parameters: 1(Integer)
[service] 2018-07-17 14:24:03,160 - dao.ICountryDao.selectCountryById -842 [main] DEBUG dao.ICountryDao.selectCountryById - <== Total: 1
3.
country
プロパティministerを問い合わせると、 @Test
public void TestselectCountryById(){
Country country=dao.selectCountryById(1);
System.out.println(country.getMinisters());
}
結果は、
minister
のクエリが実行され、この時点で本格的なminister
クエリがロードされます.[service] 2018-07-17 14:26:55,913 - dao.ICountryDao.selectCountryById -1540 [main] DEBUG dao.ICountryDao.selectCountryById - ==> Preparing: select cid,cname from country where cid=?
[service] 2018-07-17 14:26:55,943 - dao.ICountryDao.selectCountryById -1570 [main] DEBUG dao.ICountryDao.selectCountryById - ==> Parameters: 1(Integer)
[service] 2018-07-17 14:26:56,161 - dao.ICountryDao.selectCountryById -1788 [main] DEBUG dao.ICountryDao.selectCountryById - <== Total: 1
[service] 2018-07-17 14:26:56,162 - dao.ICountryDao.selectMinisterByCountry -1789 [main] DEBUG dao.ICountryDao.selectMinisterByCountry - ==> Preparing: select mid,mname from minister where countryId=?
[service] 2018-07-17 14:26:56,163 - dao.ICountryDao.selectMinisterByCountry -1790 [main] DEBUG dao.ICountryDao.selectMinisterByCountry - ==> Parameters: 1(Integer)
[service] 2018-07-17 14:26:56,168 - dao.ICountryDao.selectMinisterByCountry -1795 [main] DEBUG dao.ICountryDao.selectMinisterByCountry - <== Total: 2
[Minister [mid=2, mname=bbb], Minister [mid=1, mname=aaa]]
ロードモード
lazyLoadingEnabled
aggressiveLazyLoading
ダイレクトロード
falseでなければなりません.デフォルトはfalseです.
何でもlazyLoadingEnabledがfalseなら直接ロード
侵入遅延負荷
trueでなければなりません
trueでなければなりません
デプスディレイロード
trueでなければなりません
falseでなければなりません.デフォルトはfalseです.
【作者紹介】:秦懐、公衆号【秦懐雑貨店】作者、技術の道は一時的ではなく、山が高く水が長く、たとえゆっくりしていても、走っても止まらない.個人の書く方向:Javaのソースコードの解析、JDBC、Mybatis、Spring、redis、分布式、剣はOfferを指して、LeetCodeなど、真剣に1篇の文章を書いて、タイトル党が好きではありませんて、派手なことが好きではありませんて、大部分はシリーズの文章を書いて、私が書いたのがすべて完全に正しいことを保証することができなくて、しかし私が書いたのはすべて実践あるいは資料を探すことを保証します.漏れや間違いは、指摘してください.
2020年に何を書きましたか?
オープンソースプログラミングノート
平日の時間は貴重で、夜と週末の時間を使って書くことしかできません.私に注目して、一緒に成長しましょう.