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

首頁綜合 正文
目錄

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

柚子快報激活碼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】分頁查詢【12】模糊查詢【13】別名【14】結(jié)果填充【15】接口綁定【16】主鍵回填【17】動態(tài)SQL【18】常用注解【19】多表查詢【20】延遲加載【21】緩存【23】四大核心接口介紹及執(zhí)行流程【24】自定義插件【25】執(zhí)行器類型【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)建日志處理對象

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

// 設(shè)置級別

logger.setLevel(Level.FINEST);

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

ConsoleHandler consoleHandler = new ConsoleHandler();

// 設(shè)置格式

consoleHandler.setFormatter(new SimpleFormatter());

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

consoleHandler.setLevel(Level.FINEST);

// 增加到日志處理器

logger.addHandler(consoleHandler);

/*// 獲取控制臺日志處理器

Handler[] handlers = logger.getHandlers();

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

Handler handler = handlers[0];

// 設(shè)置控制臺日志級別

handler.setLevel(Level.FINEST);*/

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

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

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

fileHandler.setFormatter(new SimpleFormatter());

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

fileHandler.setLevel(Level.FINEST);

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

logger.addHandler(fileHandler);

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

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

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

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

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

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

}

}

【3】Log4j

log4j

log4j

1.2.17

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

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

log4j.rootLogger = DEBUG , console , D

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

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

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

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

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

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

log4j.logger.a=TRACE

log4j.logger.a.b=TRACE

log4j.logger.a.c=TRACE

### console ###

# 開始定義console名稱的handler

# console handler的類型

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

# console handler輸出的日志到哪里。 System.out 控制臺

log4j.appender.console.Target = System.out

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

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

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

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,記錄日志到哪一個文件

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

# 是否是追加寫入到日志文件

log4j.appender.D.Append = true

# 只能升級別,不能降

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

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;

/**

* 測試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;

/**

* 測試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是日志的接口聲明,不參與日志的具體實現(xiàn)。需要配合其他日志具體實現(xiàn)工具包才能進(jìn)行使用。每次添加其他日志工具包時,不要忘記SLF4j整合這個日志的依賴。

SLF4J支持多種日志實現(xiàn),但是在項目中整合依賴最好只有一個,否則會出現(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是命名空間的名字可以只寫一部分。

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)置日志工廠。日志工廠負(fù)責(zé)自動加載項目中配置的日志。MyBatis支持以下日志,當(dāng)存在多個日志工具時,嚴(yán)格按照從上往下順序使用,且只會使用一個

- 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è)置具體值的情況

${} 表示字符串拼接,用在動態(tài)設(shè)置表名和動態(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中,增刪改底層使用的邏輯是同一個。那么在沒有特定需求的時候,可以使用update實現(xiàn)增刪改的所有功能。也就是標(biāo)簽用update, 方法用update。

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

【10】MyBatis中DQL操作

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

package com.bjsxt.utils;

import org.apache.ibatis.io.Resources;

import org.apache.ibatis.session.SqlSessionFactory;

import org.apache.ibatis.session.SqlSessionFactoryBuilder;

/**

* 工具類型

*/

public final class MyBatisUtils {

// 會話工廠

private static SqlSessionFactory sqlSessionFactory;

/**

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

*/

static {

// 創(chuàng)建會話工廠

try {

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

} catch (Exception e) {

e.printStackTrace();

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

// 讓代碼終止

throw new ExceptionInInitializerError(e);

}

}

/**

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

*/

private MyBatisUtils() {

}

/**

* 獲取工廠的工具方法

*

* @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;

/**

* 查詢

*/

public class TestSelect {

/**

* 查詢方法

*

* selectOne selectList 最多 。 必須掌握

* selectMap 次之。 建議掌握

* selectCursor 再次。 了解

* select 最少。 聽說

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

*/

/**

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

*/

/**

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

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

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

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

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

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

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

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

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

* 使用的ResultHandler實現(xiàn)類型模式是DefaultResultHandler

*

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

*/

@Test

public void testSelect() {

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

DefaultResultHandler resultHandler = new DefaultResultHandler();

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

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

List list = resultHandler.getResultList();

list.forEach(obj -> {

System.out.println(obj);

});

session.close();

}

/**

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

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

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

*

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

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

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

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

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

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

*

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

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

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

*

* Cursor - 游標(biāo)

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

* 查詢的SQL沒有變化。

*

* 不常用

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

*/

@Test

public void testSelectCursor() {

Map params = new HashMap<>();

params.put("start", 100);

params.put("end", 1000);

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

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

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

// 條件查詢部分?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 查詢多行數(shù)據(jù)

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

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

*/

@Test

public void testSelectMap() {

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

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

// 查詢?nèi)?/p>

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

Map params = new HashMap<>();

params.put("start", 100);

params.put("end", 1000);

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

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查詢多行數(shù)據(jù)

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

* 特性:

* 1. 查詢無結(jié)果,返回size() = 0的 集合對象

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

*/

@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);

});

}

/**

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

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

* 方法特性:

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

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

* 3. 查詢結(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】分頁查詢

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

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

在SqlSession中select、selectMap、selectList中通過方法重載都提供了一個帶有RowBounds

/**

* 分頁查詢:

* 分頁查詢的種類|方式(面試題):

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

* 可移植性差,和數(shù)據(jù)庫耦合,因為不同的數(shù)據(jù)庫軟件,分頁語法不同。

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

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

* 特點和物理分頁相反。

* MyBatis中的分頁實現(xiàn):

* 1. 物理分頁,使用分頁語法實現(xiàn)分頁查詢。

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

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

*/

/**

* RowBounds分頁

* selectList

* 不推薦使用,相對效率較低。

*/

@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);

});

}

功能實現(xiàn)

package com.bjsxt.result;

import com.bjsxt.pojo.Student;

import java.io.Serializable;

import java.util.List;

import java.util.Objects;

/**

* 分頁查詢結(jié)果類型

*/

public class PageResult implements Serializable {

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

private int currPage;

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

private int total;

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

private List list;

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

private int pageSize;

/**

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

* JavaScript 中,可以使用Math.ceil(total / pageSize) 向上取整計算總計頁數(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 {

/**

* 分頁查詢

* @param param 查詢條件,由Servlet處理后傳入

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

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

* 1. 第幾頁

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

* 3. 一共多少頁

* 4. 當(dāng)前頁要顯示的數(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ù)邏輯實現(xiàn)類型

*/

public class StudentServiceImpl implements StudentService {

// 需要的數(shù)據(jù)庫訪問對象

private StudentDao studentDao = new StudentDaoImpl();

/**

* 分頁查詢

* @param param 查詢條件,由Servlet處理后傳入

* @return

*/

@Override

public PageResult selectByPage(MyParam param) {

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

List students = studentDao.selectByPage(param);

// 查詢總計多少行數(shù)據(jù)

int total = studentDao.selectCount(param);

// 根據(jù)查詢結(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;

/**

* 分頁查詢學(xué)生的Servlet 控制器

*/

@WebServlet("/getStudent")

public class StudentPageServlet extends HttpServlet {

private StudentService studentService = new StudentServiceImpl();

/**

* servlet 服務(wù)方法

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

* 1. 檢查JSP的字符集

* 2. 檢查Servlet中的請求字符集

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

*

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

* 請求頭參數(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");

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

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

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

// 分頁的頁碼

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

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

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

// 姓名模糊查詢條件

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

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

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

// 地址模糊查詢條件

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

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

// 維護(hù)查詢條件對象

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));

// 查詢

PageResult pageResult = studentService.selectByPage(param);

// 向客戶端輸出的是一個對象,使用JSON格式的字符串描述這個對象。

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

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

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

resp.setCharacterEncoding("UTF-8");

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

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

ObjectMapper objectMapper = new ObjectMapper();

// 把java對象,轉(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

姓名:   

地址:   

序號姓名地址操作

【12】模糊查詢

/**

* 模糊查詢

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

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

* _ : 是一個字符

* % : 是若干字符

*

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

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

*/

@Test

public void testLike3() {

/*

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

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

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

* 推薦的模糊查詢方式

*/

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中的${}實現(xiàn)字符串拼接??梢员苊鈪?shù)傳遞過程中的拼接問題。

* 但是可能有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ù)時,拼接必要的占位符,也就是 % 或 _

*/

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)置了一些常見類型的別名。這些別名不需要配置

別名映射的類型別名映射的類型別名映射的類型_bytebytestringStringdateDate_longlongbyteBytedecimalBigDecimal_shortshortlongLongbigdecimalBigDecimal_intintshortShortobjectObject_integerintintIntegermapMap_doubledoubleintegerIntegerhashmapHashMap_floatfloatdoubleDoublelistList_booleanbooleanfloatFloatarraylistArrayListbooleanBooleancollectionCollectioniteratorIterator

【14】結(jié)果填充

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

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

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

缺點: 配置增加

3. 駝峰對下劃線 很少使用

因為Java命名習(xí)慣 駝峰; 數(shù)據(jù)庫命名習(xí)慣 下劃線。因為這種常見的命名習(xí)慣很通用。所以MyBatis提供自動的駝峰對下劃線映射。

需要在mybatis.cfg.xml中開啟這種功能。

優(yōu)勢: 按照常見命名習(xí)慣自動映射

缺點: 要求表格命名和類型命名必須要個遵循常見命名習(xí)慣,并一一對應(yīng)。

【15】接口綁定

MyBatis提供自動的接口實現(xiàn)能力。稱為接口綁定。

命名習(xí)慣:

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

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

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

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

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

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

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

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

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

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

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

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

1. 一個參數(shù)

1.1 傳遞簡單參數(shù)。 SQL配置文件中的占位變量命名隨意??蚣懿粰z查。

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

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

2. 多個參數(shù)

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

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

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

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

2.2 傳遞多個參數(shù),帶有Map或自定義類型對象。 要求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】動態(tài)SQL

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

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

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

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

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

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

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

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

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

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

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

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

3. arg0, array 可用于 []

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

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

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

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

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

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

如:

數(shù)十個字段

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

十幾個if,+不同的查詢條件

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查詢部分?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查詢@Results / @Result結(jié)果映射@SelectKey主鍵回填@InsertProvider調(diào)用SQL構(gòu)建器。新增專用@DeleteProvider調(diào)用SQL構(gòu)建器。刪除專用@UpdateProvider調(diào)用SQL構(gòu)建器。修改專用@SelectProvider調(diào)用SQL構(gòu)建器。查詢專用@Param定義參數(shù)的名稱

常用注解:

1. 新增

@Insert("sql語句")

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

1.1 主鍵回填

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

2. 更新

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

3. 刪除

@Delete("sql")

4. 查詢

@Select("sql")

使用注解時,返回結(jié)果類型,默認(rèn)就是方法的返回值類型或返回值集合的泛型或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)合查詢的N+1方式中

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

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

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

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

javaType="Dept"

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

column="e_d_id"

fetchType="lazy">

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

【21】緩存

[1] 一級緩存

會話級緩存、線程級緩存,默認(rèn)開啟一級緩存

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

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

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

2. 查詢結(jié)果保存到一級緩存中

[2] 二級緩存

會話工廠緩存、進(jìn)程級緩存。

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

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

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

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

2. 查詢結(jié)果保存到一級緩存中

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

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

[3] 注意

開發(fā)時,只用一級緩存。不用二級緩存。由于二級緩存,相對性能低,安全差。

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

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

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

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

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

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

select e_id,e_name,e_d_id from emp

public class MyPageHelper {

protected static Integer pageStart;// 分頁起始行

protected static Integer pageSize;// 查詢條數(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)前是一個攔截器。

* @Signature 表示簽名。

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

* method:攔截type中的哪個方法

* args:method對應(yīng)方法的參數(shù)。這個很重要,因為Java支持方法重載,不設(shè)置參數(shù)可能無法精確到具體的方法

*/

@Intercepts(value = {@Signature(

type = StatementHandler.class,

method = "prepare",

args = {Connection.class,Integer.class}

)})

public class MyPageHelperInterceptor implements Interceptor {

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

// 對于自定義分頁插件來說,這個方法的作用就是在后面拼接limit x,y

@Override

public Object intercept(Invocation invocation) throws Throwable {

// 獲取攔截的對象

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

// 獲取SQL綁定器

BoundSql boundSql = target.getBoundSql();

// 獲取SQL語句

String sql = boundSql.getSql();

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

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

// 注意limit前面空格

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

}

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

MetaObject metaObject = SystemMetaObject.forObject(target);

// 第一個參數(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()); 通過輸出可以查詢執(zhí)行此方法時目標(biāo)對象

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

if(target instanceof StatementHandler){

return Plugin.wrap(target,this);

}

return target;

}

@Override

public void setProperties(Properties properties) {

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

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è)置分頁條件代碼必須放在調(diào)用SQL上面

MyPageHelper.startPage(0,2);

List list = empMapper.selectAllpage();

System.out.println(list);

session.close();

}

}

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

【26】執(zhí)行原理

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

http://yzkb.51969.com/

好文推薦

評論可見,查看隱藏內(nèi)容

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

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

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

發(fā)布評論

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

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問

文章目錄