欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

目錄

柚子快報(bào)激活碼778899分享:尚硅谷MyBatis 基礎(chǔ)筆記

柚子快報(bào)激活碼778899分享:尚硅谷MyBatis 基礎(chǔ)筆記

http://yzkb.51969.com/

MyBatis 筆記

文章目錄

MyBatis 筆記【1】配置文件【2】JDK Logging【3】Log4j【4】Log4j2【5】SLF4j【6】整合日志【7】SQL參數(shù)【8】${} / #{} 區(qū)別【9】MyBatis中DML操作【10】MyBatis中DQL操作【11】分頁(yè)查詢(xún)【12】模糊查詢(xún)【13】別名【14】結(jié)果填充【15】接口綁定【16】主鍵回填【17】動(dòng)態(tài)SQL【18】常用注解【19】多表查詢(xún)【20】延遲加載【21】緩存【23】四大核心接口介紹及執(zhí)行流程【24】自定義插件【25】執(zhí)行器類(lèi)型【26】執(zhí)行原理

【1】配置文件

PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-config.dtd">

【2】JDK Logging

package com.bjsxt;

import java.util.logging.*;

/**

* JDK自帶的日志 存在于java.util.logging包中

*/

public class TestJDKLogging {

public static void main(String[] args) throws Exception {

// 創(chuàng)建日志處理對(duì)象

Logger logger = Logger.getLogger("JDKLogger");

// 設(shè)置級(jí)別

logger.setLevel(Level.FINEST);

// 創(chuàng)建控制臺(tái)日志處理器

ConsoleHandler consoleHandler = new ConsoleHandler();

// 設(shè)置格式

consoleHandler.setFormatter(new SimpleFormatter());

// 設(shè)置日志級(jí)別

consoleHandler.setLevel(Level.FINEST);

// 增加到日志處理器

logger.addHandler(consoleHandler);

/*// 獲取控制臺(tái)日志處理器

Handler[] handlers = logger.getHandlers();

// 數(shù)組的0下標(biāo)就是控制器處理器

Handler handler = handlers[0];

// 設(shè)置控制臺(tái)日志級(jí)別

handler.setLevel(Level.FINEST);*/

// 創(chuàng)建一個(gè)文件日志處理器, 參數(shù)就是保存日志信息的文件名

FileHandler fileHandler = new FileHandler("jdk_log.log");

// 設(shè)置日志內(nèi)容的格式

fileHandler.setFormatter(new SimpleFormatter());

// 設(shè)置日志級(jí)別

fileHandler.setLevel(Level.FINEST);

// 把創(chuàng)建好的文件日志處理器,增加到日志處理對(duì)象中

logger.addHandler(fileHandler);

// 日志處理器,可以把日志信息輸出到控制臺(tái)和文件中

logger.finest("最詳細(xì)的日志");

logger.fine("詳細(xì)日志");

logger.warning("警告日志");

logger.info("標(biāo)準(zhǔn)消息日志");

logger.severe("嚴(yán)重錯(cuò)誤日志");

}

}

【3】Log4j

log4j

log4j

1.2.17

# log4j中定義的級(jí)別:fatal(致命錯(cuò)誤) > error(錯(cuò)誤) >warn(警告) >info(普通信息) >debug(調(diào)試信息)>trace(跟蹤信息)

# 定義Log4j中的Logger工具中有什么handler。 第一個(gè)DEBUG代表的是日志的級(jí)別。 后續(xù)每個(gè)單詞是一個(gè)handler名稱(chēng)

log4j.rootLogger = DEBUG , console , D

# log4j.logger是固定的,a.b.c是命名空間的名字可以只寫(xiě)一部分。

# 是mybatis中要使用日志的時(shí)候,必須提供的配置。

# 代表sql配置文件的namespace相應(yīng)的sql,執(zhí)行的時(shí)候,是否輸出日志,及日志的級(jí)別。

# 如:namespace="a.b" , log4j.logger.a.b=XXX級(jí)別。 那么 a.b.*所有的sql運(yùn)行的時(shí)候,都輸出日志。建議

# 如:namespace="a.b" , log4j.logger.a=XXX級(jí)別, 那么 a.*.*所有的sql運(yùn)行,都輸出日志。不建議

# 如果有多個(gè)namespace都需要輸出日志。定義若干行即可

log4j.logger.a=TRACE

log4j.logger.a.b=TRACE

log4j.logger.a.c=TRACE

### console ###

# 開(kāi)始定義console名稱(chēng)的handler

# console handler的類(lèi)型

log4j.appender.console = org.apache.log4j.ConsoleAppender

# console handler輸出的日志到哪里。 System.out 控制臺(tái)

log4j.appender.console.Target = System.out

# console輸出日志的時(shí)候,格式是什么樣的。是Pattern格式。 正則表達(dá)式格式

log4j.appender.console.layout = org.apache.log4j.PatternLayout

# 具體的格式正則規(guī)則。 %p 線(xiàn)程|進(jìn)程 %-d 時(shí)間 {yyyy-MM-dd HH\:mm\:ss} 具體的格式 %C 類(lèi)名輸出日志的類(lèi)型名 %m 輸出的日志文本 %n回車(chē)

log4j.appender.console.layout.ConversionPattern = [%p] [%-d{yyyy-MM-dd HH\:mm\:ss}] %C.%M(%L) | %m%n

### log file ###

log4j.appender.D = org.apache.log4j.DailyRollingFileAppender

# 文件日志handler,記錄日志到哪一個(gè)文件

log4j.appender.D.File = D:/log4j.log

# 是否是追加寫(xiě)入到日志文件

log4j.appender.D.Append = true

# 只能升級(jí)別,不能降

# 名字是D的handler,自定義日志級(jí)別是什么。

log4j.appender.D.Threshold = INFO

log4j.appender.D.layout = org.apache.log4j.PatternLayout

log4j.appender.D.layout.ConversionPattern = [%p] [%-d{yyyy-MM-dd HH\:mm\:ss}] %C.%M(%L) | %m%n

package com.bjsxt;

import org.apache.log4j.Logger;

/**

* 測(cè)試Log4j

* 要求classpath下,必須有配置文件log4j.properties。且必須在classpath下。不能有其他目錄。

*/

public class TestLog4j {

public static void main(String[] args) {

Logger logger = Logger.getLogger(TestLog4j.class);

// 輸出各種日志

logger.info("info日志");

logger.warn("waring日志");

logger.error("error日志");

logger.debug("debug日志");

}

}

【4】Log4j2

org.apache.logging.log4j

log4j-core

2.17.2

package com.bjsxt;

import org.apache.logging.log4j.LogManager;

import org.apache.logging.log4j.Logger;

/**

* 測(cè)試Log4j2

*/

public class TestLog4j2 {

public static void main(String[] args) {

Logger logger = LogManager.getLogger(TestLog4j2.class);

// 輸出日志

logger.debug("debug信息");

logger.info("info");

logger.warn("waring");

logger.error("error");

logger.fatal("fatal");

}

}

【5】SLF4j

SLF4j是日志的接口聲明,不參與日志的具體實(shí)現(xiàn)。需要配合其他日志具體實(shí)現(xiàn)工具包才能進(jìn)行使用。每次添加其他日志工具包時(shí),不要忘記SLF4j整合這個(gè)日志的依賴(lài)。

SLF4J支持多種日志實(shí)現(xiàn),但是在項(xiàng)目中整合依賴(lài)最好只有一個(gè),否則會(huì)出現(xiàn)警告

org.slf4j

slf4j-api

1.7.36

org.slf4j

slf4j-log4j12

1.7.36

log4j

log4j

1.2.17

org.slf4j

slf4j-api

1.7.36

org.apache.logging.log4j

log4j-slf4j-impl

2.17.2

org.apache.logging.log4j

log4j-core

2.17.2

# Log4j配置

log4j.rootLogger=ERROR, stdout

# log4j.logger是固定的,a.b.c是命名空間的名字可以只寫(xiě)一部分。

log4j.logger.a.b.c=TRACE

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

public class Test {

public static void main(String[] args) {

Logger logger = LoggerFactory.getLogger(Test.class);

logger.trace("trace");

logger.debug("debug");

logger.info("info");

logger.warn("warn");

logger.error("error");

}

}

【6】整合日志

MyBatis框架內(nèi)置日志工廠(chǎng)。日志工廠(chǎng)負(fù)責(zé)自動(dòng)加載項(xiàng)目中配置的日志。MyBatis支持以下日志,當(dāng)存在多個(gè)日志工具時(shí),嚴(yán)格按照從上往下順序使用,且只會(huì)使用一個(gè)

- SLF4J

- Apache Commons Logging

- Log4j 2

- Log4j (deprecated since 3.5.9)

- JDK logging

【7】SQL參數(shù)

PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

insert into people values(default,#{suiyixie})

PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

insert into tb_user(id, name) values(#{u1.id}, #{u2.name})

【8】${} / #{} 區(qū)別

#{} 被解析為?,用在設(shè)置列的值或條件值時(shí),也可以使用在分頁(yè)等需要設(shè)置具體值的情況

${} 表示字符串拼接,用在動(dòng)態(tài)設(shè)置表名和動(dòng)態(tài)設(shè)置列名的情況下

PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

insert into ${tableName} (${idColumn}, ${nameColumn}) values (#{id}, #{name})

【9】MyBatis中DML操作

操作mapper標(biāo)簽SqlSession方法名新增insert(String)、insert(String,Object)修改update(String)、update(String,Object)刪除delete(String)、delete(String,Object)

在MyBatis中,增刪改底層使用的邏輯是同一個(gè)。那么在沒(méi)有特定需求的時(shí)候,可以使用update實(shí)現(xiàn)增刪改的所有功能。也就是標(biāo)簽用update, 方法用update。

雖然方便,但不推薦。語(yǔ)義不明確,后期維護(hù)的時(shí)候,成本高。

【10】MyBatis中DQL操作

SqlSession方法名解釋說(shuō)明selectOne()查詢(xún)一行數(shù)據(jù)時(shí),返回值為Object。如果沒(méi)有查詢(xún)到返回Null,但是不能查詢(xún)到多行會(huì)報(bào)錯(cuò)。selectList()當(dāng)查詢(xún)多行數(shù)據(jù)時(shí),返回值為L(zhǎng)ist。如果沒(méi)有查詢(xún)到返回長(zhǎng)度為零的List對(duì)象。selectMap()查詢(xún)多行數(shù)據(jù)時(shí),把其中某列結(jié)果當(dāng)做key,每行結(jié)果為ValueselectCursor()使用游標(biāo)查詢(xún)時(shí)使用,在大量數(shù)據(jù)時(shí)可以代替分頁(yè)select()萬(wàn)能方法,需要自己定義結(jié)果處理器

package com.bjsxt.utils;

import org.apache.ibatis.io.Resources;

import org.apache.ibatis.session.SqlSessionFactory;

import org.apache.ibatis.session.SqlSessionFactoryBuilder;

/**

* 工具類(lèi)型

*/

public final class MyBatisUtils {

// 會(huì)話(huà)工廠(chǎng)

private static SqlSessionFactory sqlSessionFactory;

/**

* 初始化代碼塊,只允許一次,類(lèi)加載時(shí)運(yùn)行

*/

static {

// 創(chuàng)建會(huì)話(huà)工廠(chǎng)

try {

sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis.cfg.xml"));

} catch (Exception e) {

e.printStackTrace();

// 拋出異常,代表工廠(chǎng)創(chuàng)建失敗,后續(xù)的獲取會(huì)話(huà),訪(fǎng)問(wèn)數(shù)據(jù)庫(kù),都不可使用。

// 讓代碼終止

throw new ExceptionInInitializerError(e);

}

}

/**

* 私有構(gòu)造方法,禁止外部創(chuàng)建對(duì)象

*/

private MyBatisUtils() {

}

/**

* 獲取工廠(chǎng)的工具方法

*

* @return

*/

public static SqlSessionFactory getFactory() {

return sqlSessionFactory;

}

}

package com.bjsxt;

import com.bjsxt.pojo.User;

import com.bjsxt.utils.MyBatisUtils;

import org.apache.ibatis.cursor.Cursor;

import org.apache.ibatis.executor.result.DefaultResultHandler;

import org.apache.ibatis.session.SqlSession;

import org.junit.Test;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

/**

* 查詢(xún)

*/

public class TestSelect {

/**

* 查詢(xún)方法

*

* selectOne selectList 最多 。 必須掌握

* selectMap 次之。 建議掌握

* selectCursor 再次。 了解

* select 最少。 聽(tīng)說(shuō)

* 上述方法的使用頻率,就是定義順序。

*/

/**

* 查詢(xún)多行數(shù)據(jù)

*/

/**

* 使用select方法查詢(xún)多行數(shù)據(jù)

* void select(String statement[, Object parameter], ResultHandler handler);

* ResultHandler參數(shù) - 處理查詢(xún)結(jié)果的處理器。查詢(xún)的結(jié)果從處理器中獲取。

* 是一個(gè)接口。只有唯一的一個(gè)方法 void handleResult(ResultContext context)

* ResultContext中,有方法,可以獲取一個(gè)對(duì)象。ResultContext,就是查詢(xún)的一行數(shù)據(jù)。

* 獲取的對(duì)象,就是這行數(shù)據(jù)轉(zhuǎn)換后的Java對(duì)象。

* MyBatis給接口ResultHandler提供了若干實(shí)現(xiàn)類(lèi),select方法的底層實(shí)現(xiàn)就是selectList。

* select方法,只能查詢(xún)多行數(shù)據(jù),且返回List集合。

* 如果需要做特殊定制處理,可以給接口增加新的實(shí)現(xiàn)類(lèi)。

* 使用的ResultHandler實(shí)現(xiàn)類(lèi)型模式是DefaultResultHandler

*

* 使用頻率最低。幾乎不用。

*/

@Test

public void testSelect() {

SqlSession session = MyBatisUtils.getFactory().openSession();

DefaultResultHandler resultHandler = new DefaultResultHandler();

session.select("user.mapper.selectAll", resultHandler);

// 查詢(xún)結(jié)果后,從ResultHandler中獲取結(jié)果

List list = resultHandler.getResultList();

list.forEach(obj -> {

System.out.println(obj);

});

session.close();

}

/**

* 使用selectCursor查詢(xún)多行數(shù)據(jù)

* Cursor selectCursor(String statement[, Object parameter])

* MyBatis 中 selectCursor方法返回的游標(biāo),就是JDBC查詢(xún)結(jié)果游標(biāo)。

*

* 游標(biāo)特性: 在MyBatis中,使用Cursor游標(biāo)獲取結(jié)果前,不能關(guān)閉SqlSession。否則拋出異常。

* 1. 必須保證連接未關(guān)閉。

* 2. 必須保證會(huì)話(huà)未結(jié)束。 會(huì)話(huà)是一個(gè)持續(xù)的,有狀態(tài)的,連接或數(shù)據(jù)對(duì)象。

* 如: 連接會(huì)話(huà), Connection, 是一個(gè)持續(xù)的,不關(guān)閉一直可以使用。 有狀態(tài)的, connection創(chuàng)建后,關(guān)閉前,操作都是有狀態(tài)的,

* connection是跟著操作一起變化的, 是可能有數(shù)據(jù)變動(dòng)的。

* 如: 數(shù)據(jù)會(huì)話(huà), HttpSession。請(qǐng)求到來(lái),創(chuàng)建會(huì)話(huà),相應(yīng)返回,連接斷開(kāi),關(guān)閉。連接關(guān)閉,會(huì)話(huà)還存在。

*

* 為什么不能關(guān)閉會(huì)話(huà)后,再迭代Cursor。

* Cursor中數(shù)據(jù),不再Java的管理內(nèi)存中,在數(shù)據(jù)庫(kù)的管理內(nèi)存中。

* 每次迭代Cursor中的一條數(shù)據(jù),必須連接數(shù)據(jù)庫(kù),從數(shù)據(jù)庫(kù)管理的內(nèi)存中,把數(shù)據(jù)讀取到Java管理的內(nèi)存中,再使用。

*

* Cursor - 游標(biāo)

* JDBC查詢(xún)數(shù)據(jù)庫(kù)時(shí),返回的結(jié)果ResultSet中,保存查詢(xún)結(jié)果數(shù)據(jù)的,就是游標(biāo)。

* 查詢(xún)的SQL沒(méi)有變化。

*

* 不常用

* 查詢(xún)的數(shù)據(jù)結(jié)果數(shù)量特別多,對(duì)Java代碼運(yùn)行的電腦內(nèi)存壓力非常大,且對(duì)查詢(xún)結(jié)果只做部分處理時(shí),使用。

*/

@Test

public void testSelectCursor() {

Map params = new HashMap<>();

params.put("start", 100);

params.put("end", 1000);

SqlSession session = MyBatisUtils.getFactory().openSession();

// 查詢(xún)?nèi)繑?shù)據(jù)

Cursor cursor = session.selectCursor("user.mapper.selectAll");

// 條件查詢(xún)部分?jǐn)?shù)據(jù)

Cursor cursor1 = session.selectCursor("user.mapper.selectRangeId", params);

session.close();

cursor.forEach(user -> {

System.out.println(user);

});

cursor1.forEach(user -> {

System.out.println(user);

});

}

/**

* 使用 selectMap 查詢(xún)多行數(shù)據(jù)

* Map selectMap(String statement[, Object parameter], String keyColumnName)

* keyColumnName 參數(shù) - 使用哪一個(gè)字段的值作為返回結(jié)果Map集合的key。

*/

@Test

public void testSelectMap() {

// 使用字段name的值作為key

SqlSession session = MyBatisUtils.getFactory().openSession();

// 查詢(xún)?nèi)?/p>

Map map1 = session.selectMap("user.mapper.selectAll", "name");

Map params = new HashMap<>();

params.put("start", 100);

params.put("end", 1000);

// 根據(jù)主鍵范圍查詢(xún)

Map map2 = session.selectMap("user.mapper.selectRangeId", params, "name");

session.close();

System.out.println(map1.size());

for (Map.Entry entry : map1.entrySet()) {

System.out.println("key = " + entry.getKey() + " ; value = " + entry.getValue());

}

System.out.println(map2.size());

for (Map.Entry entry : map2.entrySet()) {

System.out.println("key = " + entry.getKey() + " ; value = " + entry.getValue());

}

}

/**

* 使用 selectList查詢(xún)多行數(shù)據(jù)

* List selectList(String statement[, Object parameter]);

* 特性:

* 1. 查詢(xún)無(wú)結(jié)果,返回size() = 0的 集合對(duì)象

* 2. 查詢(xún)有結(jié)果,返回size() = 查詢(xún)結(jié)果行數(shù)的 集合對(duì)象。

*/

@Test

public void testSelectAll() {

SqlSession session = MyBatisUtils.getFactory().openSession();

List users = session.selectList("user.mapper.selectAll");

System.out.println(users.size());

users.forEach(user -> {

System.out.println(user);

});

}

@Test

public void testSelectRangeId() {

Map params = new HashMap<>();

params.put("start", 10);

params.put("end", 100);

SqlSession session = MyBatisUtils.getFactory().openSession();

List list1 = session.selectList("user.mapper.selectRangeId", params);

System.out.println(list1.size());

list1.forEach(u -> {

System.out.println(u);

});

params.put("start", -10);

params.put("end", -1);

List list2 = session.selectList("user.mapper.selectRangeId", params);

System.out.println(list2.size());

list2.forEach(user -> {

System.out.println(user);

});

}

/**

* 查詢(xún)一行數(shù)據(jù)

* 調(diào)用方法 : T selectOne(String statement[, Object parameter])

* 方法特性:

* 1. 查詢(xún)結(jié)果不存在,返回null

* 2. 查詢(xún)結(jié)果只有一行,返回對(duì)象

* 3. 查詢(xún)結(jié)果多于一行,拋出異常

*/

@Test

public void testSelectById() {

SqlSession session = MyBatisUtils.getFactory().openSession();

User user = session.selectOne("user.mapper.selectById", 1000);

System.out.println(user);

session.close();

}

@Test

public void testSelectByName() {

String name = "劉備";

SqlSession session = MyBatisUtils.getFactory().openSession();

User u1 = session.selectOne("user.mapper.selectByName", name);

System.out.println(u1);

name = "大小姐";

User u2 = session.selectOne("user.mapper.selectByName", name);

System.out.println(u2);

name = "張三";

User u3 = session.selectOne("user.mapper.selectByName", name);

System.out.println(u3);

}

}

PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

【11】分頁(yè)查詢(xún)

RowBounds是MyBatis中提供的一種"假分頁(yè)"實(shí)現(xiàn)方式。對(duì)從數(shù)據(jù)庫(kù)中查詢(xún)到的結(jié)果進(jìn)行截取。所以如果數(shù)據(jù)庫(kù)中數(shù)據(jù)量特別大的時(shí)候可能會(huì)出現(xiàn)OOM等問(wèn)題

但是由于RowBounds不需要考慮底層數(shù)據(jù)庫(kù)是什么,且使用簡(jiǎn)單,所以對(duì)于一些數(shù)據(jù)量不是特別大的應(yīng)用還是有人選擇使用的

在SqlSession中select、selectMap、selectList中通過(guò)方法重載都提供了一個(gè)帶有RowBounds

/**

* 分頁(yè)查詢(xún):

* 分頁(yè)查詢(xún)的種類(lèi)|方式(面試題):

* 1. 物理分頁(yè),使用分頁(yè)查詢(xún)語(yǔ)法實(shí)現(xiàn)分頁(yè)查詢(xún)。如:MySQL數(shù)據(jù)庫(kù)中的limit; SqlServer數(shù)據(jù)庫(kù)中的top; Oracle數(shù)據(jù)庫(kù)中的rownum+子查詢(xún)

* 可移植性差,和數(shù)據(jù)庫(kù)耦合,因?yàn)椴煌臄?shù)據(jù)庫(kù)軟件,分頁(yè)語(yǔ)法不同。

* 相對(duì)效率更好,因?yàn)閿?shù)據(jù)庫(kù)的分頁(yè)是有特殊優(yōu)化的,是數(shù)據(jù)庫(kù)廠(chǎng)商優(yōu)化的。且網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)少,更可靠。

* 2. 邏輯分頁(yè),不使用分頁(yè)查詢(xún)語(yǔ)法,是查詢(xún)?nèi)繑?shù)據(jù),在內(nèi)存中,使用某種邏輯,分頁(yè)返回。

* 特點(diǎn)和物理分頁(yè)相反。

* MyBatis中的分頁(yè)實(shí)現(xiàn):

* 1. 物理分頁(yè),使用分頁(yè)語(yǔ)法實(shí)現(xiàn)分頁(yè)查詢(xún)。

* 2. RowBounds分頁(yè),是邏輯分頁(yè)的一種實(shí)現(xiàn)。底層基于Cursor實(shí)現(xiàn)。

* 查詢(xún)后,依次遍歷Cursor,按照分頁(yè)的需求,找到對(duì)應(yīng)的若干數(shù)據(jù),之后關(guān)閉Cursor,返回分頁(yè)結(jié)果。

*/

/**

* RowBounds分頁(yè)

* selectList

* 不推薦使用,相對(duì)效率較低。

*/

@Test

public void testRowBounds() {

SqlSession session = MyBatisUtils.getFactory().openSession();

int page = 1;

int rows = 3;

RowBounds rowBounds = new RowBounds((page - 1) * rows, rows);

List users = session.selectList("user.mapper.selectAll", null, rowBounds);

users.forEach(user -> {

System.out.println(user);

});

System.out.println("====================================================");

page = 7;

rowBounds = new RowBounds((page - 1) * rows, rows);

users = session.selectList("user.mapper.selectAll", null, rowBounds);

users.forEach(user -> {

System.out.println(user);

});

}

功能實(shí)現(xiàn)

package com.bjsxt.result;

import com.bjsxt.pojo.Student;

import java.io.Serializable;

import java.util.List;

import java.util.Objects;

/**

* 分頁(yè)查詢(xún)結(jié)果類(lèi)型

*/

public class PageResult implements Serializable {

// 當(dāng)前是第幾頁(yè)

private int currPage;

// 一共多少行數(shù)據(jù)

private int total;

// 當(dāng)前頁(yè)要顯示的數(shù)據(jù)集合

private List list;

// 每頁(yè)多少行數(shù)據(jù)

private int pageSize;

/**

* 增加推導(dǎo)屬性,一共多少頁(yè)。 可選

* JavaScript 中,可以使用Math.ceil(total / pageSize) 向上取整計(jì)算總計(jì)頁(yè)數(shù)

*/

public void setPages(int pages) {

}

public int getPages() {

return total % pageSize == 0 ? total / pageSize : (total / pageSize + 1);

}

public PageResult() {

}

@Override

public boolean equals(Object o) {

if (this == o) return true;

if (o == null || getClass() != o.getClass()) return false;

PageResult that = (PageResult) o;

return currPage == that.currPage && total == that.total && pageSize == that.pageSize && Objects.equals(list, that.list);

}

public int getPageSize() {

return pageSize;

}

public void setPageSize(int pageSize) {

this.pageSize = pageSize;

}

@Override

public int hashCode() {

return Objects.hash(currPage, total, list);

}

public int getCurrPage() {

return currPage;

}

public void setCurrPage(int currPage) {

this.currPage = currPage;

}

public int getTotal() {

return total;

}

public void setTotal(int total) {

this.total = total;

}

public List getList() {

return list;

}

public void setList(List list) {

this.list = list;

}

}

package com.bjsxt.service;

import com.bjsxt.param.MyParam;

import com.bjsxt.result.PageResult;

import java.util.Map;

public interface StudentService {

/**

* 分頁(yè)查詢(xún)

* @param param 查詢(xún)條件,由Servlet處理后傳入

* @return 自定義一個(gè)結(jié)果類(lèi)型返回。

* 分頁(yè)結(jié)果需要內(nèi)容有:

* 1. 第幾頁(yè)

* 2. 總計(jì)多少行數(shù)據(jù)

* 3. 一共多少頁(yè)

* 4. 當(dāng)前頁(yè)要顯示的數(shù)據(jù)集合

*/

PageResult selectByPage(MyParam param);

}

package com.bjsxt.service.impl;

import com.bjsxt.dao.StudentDao;

import com.bjsxt.dao.impl.StudentDaoImpl;

import com.bjsxt.param.MyParam;

import com.bjsxt.pojo.Student;

import com.bjsxt.result.PageResult;

import com.bjsxt.service.StudentService;

import java.util.List;

/**

* 服務(wù)邏輯實(shí)現(xiàn)類(lèi)型

*/

public class StudentServiceImpl implements StudentService {

// 需要的數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)對(duì)象

private StudentDao studentDao = new StudentDaoImpl();

/**

* 分頁(yè)查詢(xún)

* @param param 查詢(xún)條件,由Servlet處理后傳入

* @return

*/

@Override

public PageResult selectByPage(MyParam param) {

// 查詢(xún)當(dāng)前頁(yè)要顯示的數(shù)據(jù)集合

List students = studentDao.selectByPage(param);

// 查詢(xún)總計(jì)多少行數(shù)據(jù)

int total = studentDao.selectCount(param);

// 根據(jù)查詢(xún)結(jié)果,創(chuàng)建要返回的結(jié)果

PageResult pageResult = new PageResult();

pageResult.setCurrPage(param.getPageNum());

pageResult.setPageSize(param.getPageSize());

pageResult.setList(students);

pageResult.setTotal(total);

// 返回

return pageResult;

}

}

package com.bjsxt.controller;

import com.bjsxt.param.MyParam;

import com.bjsxt.result.PageResult;

import com.bjsxt.service.StudentService;

import com.bjsxt.service.impl.StudentServiceImpl;

import com.fasterxml.jackson.databind.ObjectMapper;

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

/**

* 分頁(yè)查詢(xún)學(xué)生的Servlet 控制器

*/

@WebServlet("/getStudent")

public class StudentPageServlet extends HttpServlet {

private StudentService studentService = new StudentServiceImpl();

/**

* servlet 服務(wù)方法

* 參數(shù)字符集問(wèn)題:

* 1. 檢查JSP的字符集

* 2. 檢查Servlet中的請(qǐng)求字符集

* 3. 檢查請(qǐng)求方式是否是POST。request.setCharacterEncoding只對(duì)請(qǐng)求體中的數(shù)據(jù)生效

*

* HTTP協(xié)議的請(qǐng)求頭,默認(rèn)字符集永遠(yuǎn)是ISO-8859-1。除非修改Tomcat中的server.xml配置文件,增加URIEncoding配置

* 請(qǐng)求頭參數(shù),絕大多數(shù)處理方案是:解碼再編碼

*

* @param req

* @param resp

* @throws ServletException

* @throws IOException

*/

@Override

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

req.setCharacterEncoding("UTF-8");

// 處理請(qǐng)求參數(shù),

// 如果未傳遞參數(shù) http://localhost:80/,返回結(jié)果是null

// 如果傳遞參數(shù)未賦值 http://localhost:80/pageNum=&pageSize&name&address,返回結(jié)果是空字符串 ""

// 分頁(yè)的頁(yè)碼

String pageNum = req.getParameter("pageNum");

// 分頁(yè)后的每頁(yè)行數(shù)

String pageSize = req.getParameter("pageSize");

// 姓名模糊查詢(xún)條件

String name = req.getParameter("name");

byte[] nameBytes = name.getBytes("ISO-8859-1"); // 把字符串按照指定字符集,解碼成字節(jié)數(shù)組

name = new String(nameBytes, "UTF-8"); // 把字節(jié)數(shù)組,按照指定的字符集,編碼成字符串。

// 地址模糊查詢(xún)條件

String address = req.getParameter("address");

address = new String(address.getBytes("ISO-8859-1"), "UTF-8");

// 維護(hù)查詢(xún)條件對(duì)象

MyParam param = new MyParam();

param.setName((name == null || "".equals(name) ? null : name));

param.setAddress((address == null || "".equals(address)) ? null : address);

param.setPageNum((pageNum == null || "".equals(pageNum)) ? 1 : Integer.parseInt(pageNum));

param.setPageSize((pageSize == null || "".equals(pageSize)) ? 2 : Integer.parseInt(pageSize));

// 查詢(xún)

PageResult pageResult = studentService.selectByPage(param);

// 向客戶(hù)端輸出的是一個(gè)對(duì)象,使用JSON格式的字符串描述這個(gè)對(duì)象。

// 設(shè)置響應(yīng)頭

resp.setContentType("application/json; charset=UTF-8");

// 設(shè)置相應(yīng)輸出流中的字符集

resp.setCharacterEncoding("UTF-8");

// 使用Jackson,把Java對(duì)象轉(zhuǎn)換成JSON格式的字符串。

// 創(chuàng)建Jackson中的對(duì)象和JSON互相轉(zhuǎn)換的工具對(duì)象。

ObjectMapper objectMapper = new ObjectMapper();

// 把java對(duì)象,轉(zhuǎn)換成JSON格式的字符串

String json = objectMapper.writeValueAsString(pageResult);

// PrintWriter resp.getWriter()

// 所有的IO輸出流的 PrintWriter & PrintStream,都有方法print和println

resp.getWriter().println(json);

// 刷新輸出流的緩沖區(qū)

resp.getWriter().flush();

}

}

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

Title

姓名:   

地址:   

序號(hào)姓名地址操作

【12】模糊查詢(xún)

/**

* 模糊查詢(xún)

* SQL: select 字段 from 表格 where 字段 like ?

* 條件是: _xxx xxx_ _xx_ %xxx xxx% %xxx% _xxx% %xxx_

* _ : 是一個(gè)字符

* % : 是若干字符

*

* MyBatis中 #{}內(nèi)不可以寫(xiě) '' 。所以模糊查詢(xún)需要做特殊處理。

* #{'%' + name + '%'}

*/

@Test

public void testLike3() {

/*

* 借助數(shù)據(jù)庫(kù)的字符串拼接函數(shù),實(shí)現(xiàn)模糊查詢(xún)。

* 缺點(diǎn)是: 需要了解數(shù)據(jù)庫(kù)的函數(shù),且不同的數(shù)據(jù)庫(kù)函數(shù)未必相同。

* 優(yōu)點(diǎn): 更加符合開(kāi)發(fā)邏輯。且沒(méi)有SQL注入隱患

* 推薦的模糊查詢(xún)方式

*/

String arg = "d";

SqlSession session = MyBatisUtils.getFactory().openSession();

List users = session.selectList("user.mapper.selectByLike3", arg);

users.forEach(user -> {

System.out.println(user);

});

session.close();

}

@Test

public void testLike2() {

/*

* 使用MyBatis中的${}實(shí)現(xiàn)字符串拼接??梢员苊鈪?shù)傳遞過(guò)程中的拼接問(wèn)題。

* 但是可能有SQL注入隱患。 String arg = "d%' or 1 = 1 or name like '%n";

*/

String arg = "d";

SqlSession session = MyBatisUtils.getFactory().openSession();

List users = session.selectList("user.mapper.selectByLike2", arg);

users.forEach(user -> {

System.out.println(user);

});

session.close();

}

@Test

public void testLike1() {

/*

* 需要傳遞參數(shù)時(shí),拼接必要的占位符,也就是 % 或 _

*/

String arg = "d";

SqlSession session = MyBatisUtils.getFactory().openSession();

List users = session.selectList("user.mapper.selectByLike", "%" + arg + "%");

users.forEach(user -> {

System.out.println(user);

});

session.close();

}

【13】別名

PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-config.dtd">

MyBatis框架中內(nèi)置了一些常見(jiàn)類(lèi)型的別名。這些別名不需要配置

別名映射的類(lèi)型別名映射的類(lèi)型別名映射的類(lèi)型_bytebytestringStringdateDate_longlongbyteBytedecimalBigDecimal_shortshortlongLongbigdecimalBigDecimal_intintshortShortobjectObject_integerintintIntegermapMap_doubledoubleintegerIntegerhashmapHashMap_floatfloatdoubleDoublelistList_booleanbooleanfloatFloatarraylistArrayListbooleanBooleancollectionCollectioniteratorIterator

【14】結(jié)果填充

在MyBatis框架中,查詢(xún)結(jié)果處理方案(結(jié)果填充|結(jié)果映射)有若干種:

1. 自動(dòng)映射 auto mapping : 當(dāng)

優(yōu)勢(shì): 一切自定義,靈活。

缺點(diǎn): 配置增加

3. 駝峰對(duì)下劃線(xiàn) 很少使用

因?yàn)镴ava命名習(xí)慣 駝峰; 數(shù)據(jù)庫(kù)命名習(xí)慣 下劃線(xiàn)。因?yàn)檫@種常見(jiàn)的命名習(xí)慣很通用。所以MyBatis提供自動(dòng)的駝峰對(duì)下劃線(xiàn)映射。

需要在mybatis.cfg.xml中開(kāi)啟這種功能。

優(yōu)勢(shì): 按照常見(jiàn)命名習(xí)慣自動(dòng)映射

缺點(diǎn): 要求表格命名和類(lèi)型命名必須要個(gè)遵循常見(jiàn)命名習(xí)慣,并一一對(duì)應(yīng)。

【15】接口綁定

MyBatis提供自動(dòng)的接口實(shí)現(xiàn)能力。稱(chēng)為接口綁定。

命名習(xí)慣:

每個(gè)框架或技術(shù),都有各自的命名習(xí)慣。

MyBatis技術(shù)中,數(shù)據(jù)訪(fǎng)問(wèn)層(持久層)接口命名習(xí)慣是 XxxMapper。

正式工作開(kāi)發(fā)中,數(shù)據(jù)訪(fǎng)問(wèn)層(持久層)接口命名習(xí)慣是 XxxDao, XxxDAO

接口綁定的規(guī)則:

1. 必要規(guī)則: 必須遵守的規(guī)則,有兩條

1.1 SQL配置文件namespace,必須和對(duì)應(yīng)的要生成實(shí)現(xiàn)的接口的全命名完全相同,大小寫(xiě)敏感。

1.2 SQL配置文件中,編寫(xiě)SQL語(yǔ)句的標(biāo)簽id,必須和對(duì)應(yīng)的接口中的方法名完全相同,大小寫(xiě)敏感。

2. 可選規(guī)則: 可以遵守的規(guī)則,遵守可以簡(jiǎn)化mybatis.cfg.xml中的配置。 有兩條

2.1 SQL配置文件存放的位置,和對(duì)應(yīng)的接口所在的包完全相同。

2.2 SQL配置文件的文件名(不包含后綴),和對(duì)應(yīng)的接口的類(lèi)型名完全相同。

遵守這兩個(gè)可選規(guī)則,可以在mybatis.cfg.xml中,使用一次性配置所有的SQL配置文件。

接口綁定中的參數(shù)傳遞:

1. 一個(gè)參數(shù)

1.1 傳遞簡(jiǎn)單參數(shù)。 SQL配置文件中的占位變量命名隨意。框架不檢查。

1.2 傳遞Map參數(shù)。 SQL配置文件中的占位變量名必須是Map中的key。

1.3 傳遞自定義類(lèi)型對(duì)象(POJO實(shí)體)。 SQL配置文件中的占位變量名必須和類(lèi)型的屬性名(property或field)一致。

2. 多個(gè)參數(shù)

注意: 使用注解了argM的形式就不能使用了,需要通過(guò)注解中名稱(chēng)或paramN的方式調(diào)用

2.1 傳遞多個(gè)簡(jiǎn)單參數(shù)。 要求SQL配置文件中的占位變量必須按照框架要求定義。

2.1.1 如果接口的方法參數(shù),使用的注解@Param("")定義參數(shù)名,則占位變量名必須是注解的屬性值,或param1,param2,param3等。 推薦的方式

2.1.2 如果接口的方法參數(shù),不使用注解,則占位變量名必須是 param1,param2或 arg0, arg1 等。不推薦的方式。面試可能問(wèn)。

2.2 傳遞多個(gè)參數(shù),帶有Map或自定義類(lèi)型對(duì)象。 要求SQL配置文件的占位變量必須按照框架要求定義。

2.2.1 如果接口方法參數(shù),使用注解,可以使用 #{注解屬性.key}|#{注解屬性.屬性名} 或者 #{param1.key} | #{param1.屬性名}

2.2.2 如果接口方法參數(shù),不使用注解,可以使用 #{arg0.key} | #{arg0.屬性名} 或者 #{param1.key} | #{param1.屬性名}

多參數(shù)傳遞

int insert1(@Param("id") Integer id, @Param("name") String name);

int insert2(Integer id, String name);

int insert3(@Param("myMap") Map map, @Param("peo") People people);

int insert4(Map map, People people);

insert into tb_people(id, name) values(#{param1}, #{name})

insert into tb_people(id, name) values(#{arg0}, #{param2})

insert into tb_people(id, name) values(#{param1.id}, #{peo.name})

insert into tb_people(id, name) values(#{arg0.id}, #{param2.name})

【16】主鍵回填

insert into tb_people(id, name) values(default, #{name})

【17】動(dòng)態(tài)SQL

動(dòng)態(tài)SQL在MyBatis中是基于標(biāo)簽實(shí)現(xiàn)的。

1. if標(biāo)簽。判斷標(biāo)簽。根據(jù)某boolean值,或結(jié)果為boolean的表達(dá)式(布爾表達(dá)式)動(dòng)態(tài)判斷。

在MyBatis的SQL配置文件中,可以寫(xiě)OGNL表達(dá)式。語(yǔ)法類(lèi)似JSP中的EL表達(dá)式。在各種標(biāo)簽中使用,得到需要的結(jié)果。

2. choose標(biāo)簽。選擇標(biāo)簽。類(lèi)似java語(yǔ)法中是switch case。根據(jù)多個(gè)不同的判斷邏輯,選擇某一個(gè)分支。

3. trim標(biāo)簽。為標(biāo)簽體中的文本去除前后綴或增加前后綴。先刪除前后綴,再增加前后綴

4. where標(biāo)簽。用在SQL語(yǔ)句的where子句動(dòng)態(tài)處理中。如果標(biāo)簽中存在文本,則增加where子句。如果標(biāo)簽中不存在文本,則不增加where子句。

where標(biāo)簽,有動(dòng)態(tài)識(shí)別能力,如果標(biāo)簽內(nèi)的文本以and或者or開(kāi)頭,自動(dòng)刪除前綴and或or。

5. set標(biāo)簽。用在update語(yǔ)句中的標(biāo)簽。動(dòng)態(tài)增加set子句。 有自動(dòng)識(shí)別能力,如果標(biāo)簽內(nèi)的文本以','結(jié)尾,自動(dòng)刪除后綴','。

6. forEach標(biāo)簽。用于循環(huán)集合的標(biāo)簽。常用于,批量新增,范圍in|not in查詢(xún)等。

要循環(huán)的變量: 命名方式有

1. 使用注解@Param("名字"), 推薦使用

2. arg0, collection, list 可用于List, Collection

3. arg0, array 可用于 []

close="循環(huán)內(nèi)容的結(jié)束字符串" item="循環(huán)過(guò)程的變量名" separator="每次循環(huán)時(shí)間隔符">

close=")" item="a" separator=","> #{a}

循環(huán)遍歷后的結(jié)果文本是: (?, ?, ?)

7. bind 標(biāo)簽,用于綁定修改后的特定數(shù)據(jù)的。常用于模糊查詢(xún)處理。

8. sql和include標(biāo)簽。 sql標(biāo)簽,定義SQL語(yǔ)句片段。 include標(biāo)簽,引用定義好的SQL語(yǔ)法片段。

常用于定義字段列表,或復(fù)雜的判斷邏輯。

如:

數(shù)十個(gè)字段

復(fù)雜到不向再寫(xiě)一次的判斷邏輯

十幾個(gè)if,+不同的查詢(xún)條件

if

choose

trim

where

set

update people

name=#{name},

address=#{address},

id=#{id}

where id = #{id}

foreach

insert into tb_people(id, name)

#{p.id},#{p.name}

/**

* 根據(jù)參數(shù),in查詢(xún)部分?jǐn)?shù)據(jù)

*

* @param ids

* @return

*/

List selectByForEach(@Param("ids") List ids);

/**

* 批量新增

*

* @param list

* @return

*/

int insertBatch(List list);

bind

sql 和 include

id,name,address

【18】常用注解

注解功能@Insert新增@Delete刪除@Update修改@Select查詢(xún)@Results / @Result結(jié)果映射@SelectKey主鍵回填@InsertProvider調(diào)用SQL構(gòu)建器。新增專(zhuān)用@DeleteProvider調(diào)用SQL構(gòu)建器。刪除專(zhuān)用@UpdateProvider調(diào)用SQL構(gòu)建器。修改專(zhuān)用@SelectProvider調(diào)用SQL構(gòu)建器。查詢(xún)專(zhuān)用@Param定義參數(shù)的名稱(chēng)

常用注解:

1. 新增

@Insert("sql語(yǔ)句")

注解中處理參數(shù)的方式,和SQL配置文件中的方式完全相同。但是此注解沒(méi)有動(dòng)態(tài)SQL標(biāo)簽的功能。

1.1 主鍵回填

@SelectKey(statement="sql", before=真假, keyProperty="主鍵屬性名"[, keyColumn="查詢(xún)主鍵的字段名"], resultType=類(lèi)型)

2. 更新

@Update("sql"), 和SQL配置文件采用相同的參數(shù)處理方案。

3. 刪除

@Delete("sql")

4. 查詢(xún)

@Select("sql")

使用注解時(shí),返回結(jié)果類(lèi)型,默認(rèn)就是方法的返回值類(lèi)型或返回值集合的泛型或Map。 相當(dāng)于SQL配置文件中的

select addr.id, addr.province, addr.city, addr.address, cus.id as cusId, cus.name, cus.username, cus.password from

tb_address addr left join tb_customer cus on addr.customer_id = cus.id

select="com.bjsxt.mapper.CustomerMapper.selectById"

column="{id = customer_id}">

PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

ofType="Address">

ofType="Address" select="com.bjsxt.mapper.AddressMapper.selectAddrByCustomer"

column="{customerId = id}">

package com.bjsxt.test;

import com.bjsxt.mapper.AddressMapper;

import com.bjsxt.mapper.CustomerMapper;

import com.bjsxt.pojo.Address;

import com.bjsxt.pojo.Customer;

import com.bjsxt.utils.MyBatisUtils;

import org.apache.ibatis.session.SqlSession;

import org.junit.Before;

import org.junit.Test;

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

public class TestAssociation {

private SqlSession session;

private AddressMapper addressMapper;

private CustomerMapper customerMapper;

@Before

public void before(){

session = MyBatisUtils.getFactory().openSession();

addressMapper = session.getMapper(AddressMapper.class);

customerMapper = session.getMapper(CustomerMapper.class);

}

@Test

public void testAssociation1(){

List

list = addressMapper.selectAll1();

for (Address address : list){

System.out.println(address);

System.out.println(address.getCustomer());

System.out.println("====================================================");

}

}

@Test

public void testAssociation(){

List

list = addressMapper.selectAll();

// for(Address address : list){

// System.out.println(address);

// //System.out.println(address.getCustomer());

// System.out.println("==========================================================");

// }

}

}

package com.bjsxt.test;

import com.bjsxt.mapper.CustomerMapper;

import com.bjsxt.pojo.Address;

import com.bjsxt.pojo.Customer;

import com.bjsxt.utils.MyBatisUtils;

import org.apache.ibatis.session.SqlSession;

import org.junit.Before;

import org.junit.Test;

import java.util.List;

public class TestCollection {

private SqlSession session;

private CustomerMapper customerMapper;

@Before

public void before() {

session = MyBatisUtils.getFactory().openSession();

customerMapper = session.getMapper(CustomerMapper.class);

}

@Test

public void testCollection1() {

List list = customerMapper.selectAll1();

for (Customer customer : list) {

System.out.println(customer);

for (Address address : customer.getAddressList()) {

System.out.println(address);

}

System.out.println("=================================================");

}

}

@Test

public void testCollection() {

List list = customerMapper.selectAll();

for (Customer customer : list) {

System.out.println(customer);

for (Address address : customer.getAddressList()) {

System.out.println(address);

}

System.out.println("==============================================================");

}

}

}

【20】延遲加載

延遲加載只能出現(xiàn)在多表聯(lián)合查詢(xún)的N+1方式中

表示當(dāng)執(zhí)行當(dāng)前方法時(shí),是否立即執(zhí)行關(guān)聯(lián)方法的SQL

全局配置從3.4.1版本開(kāi)始需要在MyBatis置文件里面配置lazyLoadingEnabled=true即可在當(dāng)前項(xiàng)目所有N+1的位置開(kāi)啟延遲加載

局部配置需要在collection或association標(biāo)簽中配置fetchType屬性。fetchType可取值:lazy(延遲加載)和eager(立即加載)

當(dāng)配置了fetchType屬性后,全局settings的配置被覆蓋,對(duì)于當(dāng)前標(biāo)簽以fetchType屬性值為準(zhǔn)

javaType="Dept"

select="com.bjsxt.mapper.DeptMapper.selectById"

column="e_d_id"

fetchType="lazy">

屬性名解釋說(shuō)明可取值默認(rèn)值lazyLoadingEnabled延遲加載的全局開(kāi)關(guān)。當(dāng)開(kāi)啟時(shí),所有關(guān)聯(lián)對(duì)象都會(huì)延遲加載。 特定關(guān)聯(lián)關(guān)系中可通過(guò)設(shè)置 fetchType 屬性來(lái)覆蓋該項(xiàng)的開(kāi)關(guān)狀態(tài)。true | falsefalseaggressiveLazyLoading開(kāi)啟時(shí),任一方法的調(diào)用都會(huì)加載該對(duì)象的所有延遲加載屬性。 否則,每個(gè)延遲加載屬性會(huì)按需加載(參考 lazyLoadTriggerMethods)。true | falsefalse (在 3.4.1 及之前的版本中默認(rèn)為 true)

【21】緩存

[1] 一級(jí)緩存

會(huì)話(huà)級(jí)緩存、線(xiàn)程級(jí)緩存,默認(rèn)開(kāi)啟一級(jí)緩存

要求:必須使用同一個(gè)會(huì)話(huà)、執(zhí)行同一條SQL、使用完全相同的參數(shù)

一級(jí)緩存中的數(shù)據(jù)保存流程:

1. 執(zhí)行SQL,查詢(xún)數(shù)據(jù)

2. 查詢(xún)結(jié)果保存到一級(jí)緩存中

[2] 二級(jí)緩存

會(huì)話(huà)工廠(chǎng)緩存、進(jìn)程級(jí)緩存。

要求:必須使用同一個(gè)會(huì)話(huà)工廠(chǎng),執(zhí)行同一條SQL,使用完全相同的參數(shù),且在事務(wù)結(jié)束后,才能使用的緩存。實(shí)體必須實(shí)現(xiàn)接口Serializable

二級(jí)緩存可能保存在內(nèi)存,也可能保存在文件中。MyBatis使用Object輸出/輸入流,實(shí)現(xiàn)文件和內(nèi)存的緩存數(shù)據(jù)讀寫(xiě)。

二級(jí)緩存中的數(shù)據(jù)保存流程:

1. 執(zhí)行SQL,查詢(xún)數(shù)據(jù)

2. 查詢(xún)結(jié)果保存到一級(jí)緩存中

3. 提交/回滾/關(guān)閉會(huì)話(huà),刷新一級(jí)緩存到二級(jí)緩存

4. 查詢(xún)同樣的SQL,且使用同樣的參數(shù),使用二級(jí)緩存

[3] 注意

開(kāi)發(fā)時(shí),只用一級(jí)緩存。不用二級(jí)緩存。由于二級(jí)緩存,相對(duì)性能低,安全差。

二級(jí)緩存是以 namespace 為單位的,不同 namespace 下的操作互不影響

查詢(xún)數(shù)據(jù)順序 二級(jí)-->一級(jí)--->數(shù)據(jù)庫(kù)--->把數(shù)據(jù)保存到一級(jí),當(dāng)sqlsession關(guān)閉或者提交的時(shí)候,把數(shù)據(jù)刷入到二級(jí)緩存中

[4] 只讀緩存(readonly=true)

配置的目的是優(yōu)化查詢(xún)性能,確保緩存不被寫(xiě)入,但它不會(huì)影響數(shù)據(jù)庫(kù)的提交操作。數(shù)據(jù)庫(kù)中的數(shù)據(jù)會(huì)按照提交操作進(jìn)行實(shí)際的修改。

提交操作對(duì)數(shù)據(jù)庫(kù)的數(shù)據(jù)進(jìn)行實(shí)際更改,不管緩存是否配置為只讀。

MyBatis 通過(guò)自動(dòng)清除相關(guān)緩存來(lái)確保數(shù)據(jù)的一致性,使得提交操作后的數(shù)據(jù)在下次查詢(xún)時(shí)能夠得到正確的反映。

select e_id,e_name,e_d_id from emp

public class MyPageHelper {

protected static Integer pageStart;// 分頁(yè)起始行

protected static Integer pageSize;// 查詢(xún)條數(shù)

public static void startPage(int pageStartArg,int pageSizeArg){

pageStart = pageStartArg;

pageSize = pageSizeArg;

}

}

package com.bjsxt.interceptor;

import org.apache.ibatis.executor.statement.StatementHandler;

import org.apache.ibatis.mapping.BoundSql;

import org.apache.ibatis.plugin.*;

import org.apache.ibatis.reflection.MetaObject;

import org.apache.ibatis.reflection.SystemMetaObject;

import java.sql.Connection;

import java.util.Properties;

// 必須有的注解

/**

* @Intercepts 表示當(dāng)前是一個(gè)攔截器。

* @Signature 表示簽名。

* type:攔截器主要攔截的類(lèi)型.可以是四大核心接口。

* method:攔截type中的哪個(gè)方法

* args:method對(duì)應(yīng)方法的參數(shù)。這個(gè)很重要,因?yàn)镴ava支持方法重載,不設(shè)置參數(shù)可能無(wú)法精確到具體的方法

*/

@Intercepts(value = {@Signature(

type = StatementHandler.class,

method = "prepare",

args = {Connection.class,Integer.class}

)})

public class MyPageHelperInterceptor implements Interceptor {

// 這個(gè)方法的作用:實(shí)現(xiàn)攔截業(yè)務(wù)

// 對(duì)于自定義分頁(yè)插件來(lái)說(shuō),這個(gè)方法的作用就是在后面拼接limit x,y

@Override

public Object intercept(Invocation invocation) throws Throwable {

// 獲取攔截的對(duì)象

StatementHandler target = (StatementHandler) invocation.getTarget();

// 獲取SQL綁定器

BoundSql boundSql = target.getBoundSql();

// 獲取SQL語(yǔ)句

String sql = boundSql.getSql();

// 判斷是否已經(jīng)設(shè)置了分頁(yè)條件

if(MyPageHelper.pageStart!=null&&MyPageHelper.pageSize!=null) {

// 注意limit前面空格

sql += " limit " +MyPageHelper.pageStart+","+MyPageHelper.pageSize;

}

// 把修改后的SQL重新放回去

MetaObject metaObject = SystemMetaObject.forObject(target);

// 第一個(gè)參數(shù)為固定值,表示綁定的SQL

metaObject.setValue("parameterHandler.boundSql.sql",sql);

// 放行繼續(xù)執(zhí)行

return invocation.proceed();

}

@Override

public Object plugin(Object target) {

// System.out.println(target.getClass().getName()); 通過(guò)輸出可以查詢(xún)執(zhí)行此方法時(shí)目標(biāo)對(duì)象

// 每次調(diào)用四大核心接口都會(huì)調(diào)用此方法,只需要對(duì)StatementHandler進(jìn)行處理

if(target instanceof StatementHandler){

return Plugin.wrap(target,this);

}

return target;

}

@Override

public void setProperties(Properties properties) {

// 獲取到后面配置插件時(shí)的屬性,設(shè)定屬性名為dialect(方言),這個(gè)屬性是自定義的。

System.out.println(properties.getProperty("dialect"));

}

}

public class Test {

public static void main(String[] args) throws IOException {

InputStream is = Resources.getResourceAsStream("mybatis.cfg.xml");

SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);

SqlSession session = factory.openSession();

EmpMapper empMapper = session.getMapper(EmpMapper.class);

// 設(shè)置分頁(yè)條件代碼必須放在調(diào)用SQL上面

MyPageHelper.startPage(0,2);

List list = empMapper.selectAllpage();

System.out.println(list);

session.close();

}

}

【25】執(zhí)行器類(lèi)型

【26】執(zhí)行原理

柚子快報(bào)激活碼778899分享:尚硅谷MyBatis 基礎(chǔ)筆記

http://yzkb.51969.com/

好文推薦

評(píng)論可見(jiàn),查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀(guān)點(diǎn)和立場(chǎng)。

轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19313330.html

發(fā)布評(píng)論

您暫未設(shè)置收款碼

請(qǐng)?jiān)谥黝}配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪(fǎng)問(wèn)

文章目錄