柚子快報(bào)邀請碼778899分享:MyBatis筆記
柚子快報(bào)邀請碼778899分享:MyBatis筆記
Mybatis
Mybatis介紹
什么是Mybatis?
mybatis是支持普通SQL查詢、存儲(chǔ)過程和高級映射的優(yōu)秀持久層框架。
Mybatis優(yōu)點(diǎn)
幾乎消除了JDBC代碼和參數(shù)的手動(dòng)設(shè)置消除結(jié)果集的檢索使用XML或注解用于配置和原始映射,將接口和POJOs(實(shí)體類)映射成數(shù)據(jù)庫中的記錄。
Mybatis特點(diǎn)
簡單易學(xué):本身就很小且簡單。沒有任何第三方依賴,最簡單安裝只要兩個(gè)jar文件+配置幾個(gè)sql映射文件易于學(xué)習(xí),易于使用,通過文檔和源代碼,可以比較完全的掌握它的設(shè)計(jì)思路和實(shí)現(xiàn)。靈活:mybatis不會(huì)對應(yīng)用程序或者數(shù)據(jù)庫的現(xiàn)有設(shè)計(jì)強(qiáng)加任何影響。 sql寫在xml里,便于統(tǒng)一管理和優(yōu)化。通過sql基本上可以實(shí)現(xiàn)我們不使用數(shù)據(jù)訪問框架可以實(shí)現(xiàn)的所有功能,或許更多。解除sql與程序代碼的耦合:通過提供DAO層,將業(yè)務(wù)邏輯和數(shù)據(jù)訪問邏輯分離,使系統(tǒng)的設(shè)計(jì)更清晰,更易維護(hù),更易單元測試。sql和代碼的分離,提高了可維護(hù)性。提供映射標(biāo)簽,支持對象與數(shù)據(jù)庫的orm字段關(guān)系映射提供對象關(guān)系映射標(biāo)簽,支持對象關(guān)系組建維護(hù)提供xml標(biāo)簽,支持編寫動(dòng)態(tài)sql
Mybatis功能構(gòu)架
我們把Mybatis的功能架構(gòu)分為三層:
1.API接口層 2.數(shù)據(jù)處理層 3.基礎(chǔ)支撐層
**API接口:**提供給外部使用的API接口,開發(fā)人員使用本地API接口操作數(shù)據(jù)庫。接口層一收到調(diào)用請求,就會(huì)調(diào)用數(shù)據(jù)處理層進(jìn)行具體的數(shù)據(jù)處理。
**數(shù)據(jù)處理層:**負(fù)責(zé)具體的SQL查詢,SQL解析、SQL執(zhí)行以及執(zhí)行結(jié)果集映射的處理。主要目的是根據(jù)調(diào)用進(jìn)行一次操作數(shù)據(jù)庫
**基礎(chǔ)支撐層:**負(fù)責(zé)最基礎(chǔ)的支撐,包括 連接管理、事務(wù)管理、配置加載、緩沖加載。這些都是公用的的基礎(chǔ)組件。
框架解析
框架架構(gòu)講解:
mybatis結(jié)構(gòu)
(1)加載配置:配置來源于兩個(gè)地方,一處是配置文件,一處是Java代碼的注解,將SQL的配置信息加載成為一個(gè)個(gè)MappedStatement對象(包括了傳入?yún)?shù)映射配置、執(zhí)行的SQL語句、結(jié)果映射配置),存儲(chǔ)在內(nèi)存中。
(2)SQL解析:當(dāng)API接口層接收到調(diào)用請求時(shí),會(huì)接收到傳入SQL的ID和傳入對象(可以是Map、JavaBean或者基本數(shù)據(jù)類型),Mybatis會(huì)根據(jù)SQL的ID找到對應(yīng)的MappedStatement,然后根據(jù)傳入?yún)?shù)對象對MappedStatement進(jìn)行解析,解析后可以得到最終要執(zhí)行的SQL語句和參數(shù)。
(3)SQL執(zhí)行:將最終得到的SQL和參數(shù)拿到數(shù)據(jù)庫進(jìn)行執(zhí)行,得到操作數(shù)據(jù)庫的結(jié)果。
(4)結(jié)果映射:將操作數(shù)據(jù)庫的結(jié)果按照映射的配置進(jìn)行轉(zhuǎn)換,可以轉(zhuǎn)換成HashMap、JavaBean或者基本數(shù)據(jù)類型,并將最終結(jié)果返回。
獲取Mybatis
mavenGitHub
持久層
持久化
將程序的數(shù)據(jù)在持久狀態(tài)和瞬時(shí)狀態(tài)轉(zhuǎn)化的過程。內(nèi)存的特點(diǎn):斷電即失
第一個(gè)Mybatis程序
搭建環(huán)境
1.搭建數(shù)據(jù)庫
CREATE DATABASS mybatis;
創(chuàng)建表
USE mybatis
go
CREATE TABLE Users(
id int not null PRIMARY KEY,
name varchar default NULL,
pwd varchar default NULL
)
插入值
insert Users(id,name,pwd)
values (1,'張三','123456')
insert Users(id,name,pwd)
values (2,'李四','123456')
insert Users(id,name,pwd)
values (3,'王五','123456')
另外一種值插入方法
insert into Users
select 1,'張三','123456'
union
2.創(chuàng)建項(xiàng)目
導(dǎo)入依賴
sqlServer驅(qū)動(dòng)
mybatis
junit
創(chuàng)建Module 作為子模塊
編寫代碼
編寫Mybatis核心配置文件
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
編寫工具類
編寫工具類 加載使用
public class UsersUtils {
private static SqlSessionFactory sqlSessionFactory;
static{
//獲取sqlSessionFactory對象
try {
String resource ="mybatis-config.xml";
InputStream resourceAsStream = Resources.getResourceAsStream(resource);
sqlSessionFactory =new SqlSessionFactoryBuilder().build(resourceAsStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//獲取SqlSession實(shí)例
//既然有了 SqlSessionFactory,顧名思義,我們可以從中獲得 SqlSession 的實(shí)例。
// SqlSession 提供了在數(shù)據(jù)庫執(zhí)行 SQL 命令所需的所有方法。你可以通過 SqlSession 實(shí)例來直接執(zhí)行已映射的 SQL 語句。
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
// SqlSession sqlSession = sqlSessionFactory.openSession();
// return sqlSession;
}
}
編寫實(shí)體類
public class Users implements Serializable {
private int id;
private String name;
private String pwd;
public Users() {
}
public Users(int id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
@Override
public String toString() {
return "Users{" +
"id=" + id +
", name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
}
編寫Dao接口 層
interface UsersDao {
List
}
編寫Dao接口層實(shí)現(xiàn)代碼的xml文件
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
select * from Users
namespace=“com.Dao.UsersDao”
全限命名法,namespace 表示和某一個(gè)類或接口 相匹配
id=“getUsersDaoList”
Select 中的ID表示查詢的方法
resultType=“com.pojo.Users”
返回單個(gè)的類型,必須表示返回類型所對應(yīng)的實(shí)體類。
測試
測試注意
一般在Text下創(chuàng)建和代碼相對應(yīng)的目錄進(jìn)行測試。
編寫測試代碼
public class Text {
@Test
public void text(){
//加載resources資源
//獲取SqlSession對象
SqlSession sqlSession = UsersUtils.getSqlSession();
//執(zhí)行SQL
UsersDao mapper = sqlSession.getMapper(UsersDao.class);
List
for (Users users : usersDao) {
System.out.println(users);
}
//關(guān)閉資源
sqlSession.close();
}
}
測試果
可能會(huì)出現(xiàn)的錯(cuò)誤
org.apache.ibatis.binding.BindingException: Type interface com.Dao.UsersDao is not known to the MapperRegistry.
錯(cuò)誤原因
在核心配置文件中沒有沒有將UsersDao的xml文件配置注冊
解決
將UsersDao的xml文件配置到Mybatis核心配置文件當(dāng)中
IOException: Could not find resource com/Dao/UsersMapper.xml
錯(cuò)誤原因
1.沒有編寫UsersMapper.xml配置文件。
2.因?yàn)樵贛aven項(xiàng)目中,約定大于配置,所以需要手動(dòng)將Java中的xml打包帶出
解決
1.編寫UsersMapper.xml文件
2.在Pom文件下加上Build
項(xiàng)目代碼結(jié)構(gòu)
CURD
查詢
UsersDao接口
//通過id查詢用戶
Users getUsersById(int id);
映射文件
select * from Users where id=#{id}
測試結(jié)果
@Test
public void Text01(){
SqlSession sqlSession = UsersUtils.getSqlSession();
UsersDao mapper = sqlSession.getMapper(UsersDao.class);
Users usersById = mapper.getUsersById(1);
System.out.println(usersById);
sqlSession.close();
}
增加
UsersDao接口
//增加用戶
int InsertUser(Users users);
映射文件
insert Users(id,name,pwd) values(#{id},#{name},#{pwd})
測試
//增加用戶
@Test
public void Text02(){
SqlSession sqlSession = UsersUtils.getSqlSession();
UsersDao mapper = sqlSession.getMapper(UsersDao.class);
int s = mapper.InsertUser(new Users(4, "五百", "123456"));
if (s>0){
System.out.println("增加用戶成功");
}
//增刪改需要提交事務(wù),否則無法更改
sqlSession.commit();
sqlSession.close();
}
修改
UsersDao接口
//更改用戶數(shù)據(jù)
int UpdataUser(Users users);
映射文件
update Users set name=#{name},pwd=#{pwd} where id=#{id};
測試
//修改用戶 將四號(hào)用戶的名字改為六百
@Test
public void text03(){
SqlSession sqlSession = UsersUtils.getSqlSession();
UsersDao mapper = sqlSession.getMapper(UsersDao.class);
int liu = mapper.UpdataUser(new Users(4, "六百", "123456"));
if (liu>0){
System.out.println("修改用戶成功");
}
//提交事務(wù)
sqlSession.commit();
sqlSession.close();
}
刪除
UsersDao接口
//刪除用戶數(shù)據(jù)
int DelectUser(int id);
映射文件
delete from Users where id=#{id};
測試
@Test
public void text04(){
SqlSession sqlSession = UsersUtils.getSqlSession();
UsersDao mapper = sqlSession.getMapper(UsersDao.class);
int i = mapper.DelectUser(4);
if (i>0){
System.out.println("刪除用戶成功");
}
sqlSession.commit();
sqlSession.close();
}
完整代碼
UsersDao接口
public interface UsersDao {
//獲取列表
List
//通過id查詢用戶
Users getUsersById(int id);
//增加用戶
int InsertUser(Users users);
//更改用戶數(shù)據(jù)
int UpdataUser(Users users);
//刪除用戶數(shù)據(jù)
int DelectUser(int id);
}
映射文件
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
select * from Users
select * from Users where id=#{id}
insert Users(id,name,pwd) values(#{id},#{name},#{pwd})
update Users set name=#{name},pwd=#{pwd} where id=#{id};
delete from Users where id=#{id};
XML配置
首先聲明xml中各個(gè)配置設(shè)置的位置是固定不變的,否則會(huì)出現(xiàn)異常
必須遵循下面的順序進(jìn)行設(shè)置。
(properties–settings–typeAliases–typeHandlers–objectFactory–objectWrapperFactory–reflectorFactory–plugins–environments–databaseIdProvider–mappers)"
屬性(properties)
目前我們學(xué)過的屬性文件db.properties
在xml文件當(dāng)中,為了實(shí)現(xiàn)我們可以動(dòng)態(tài)修改xml文件,可以在外部設(shè)置屬性文件引用到mybatis-config.xml文件當(dāng)中。
屬性配置有兩種插入方法
1.內(nèi)部引入
2.外部引入
2.1 首先編寫一個(gè)properties屬性文件。
driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
url=jdbc:sqlserver://localhost:1433;database=mybatis;useSSL=true&useUnicode=true&characterEncoding=UTF-8
username=sa
password=1582183834
然后在mybatis-config.xml文件當(dāng)中
環(huán)境中屬性的更改
通過${}以實(shí)現(xiàn)動(dòng)態(tài)獲取properties屬性文件當(dāng)中的屬性
若兩部分都有部署,首先會(huì)執(zhí)行內(nèi)部的xml,再執(zhí)行外部的屬性資源,但是內(nèi)部的某些屬性會(huì)被外部屬性覆蓋!
類型別名(typeAliases)
類型別名相當(dāng)于對動(dòng)態(tài)SQL中的返回類型或者參數(shù)類型的優(yōu)化
例如在查詢表單的SQL中的返回類型resultType的返回類型是一個(gè)對象
select * from Users
這樣些寫較為麻煩,所以為這個(gè)類型設(shè)置一個(gè)別名
這樣設(shè)置類型為Users類的別名就變?yōu)閁sers
select * from Users
package類型別名
package 顧名思義是包 package類型別名,即是掃描包
掃描包
每一個(gè)在包 domain.blog 中的 Java Bean,在沒有注解的情況下,會(huì)使用 Bean 的首字母小寫的非限定類名來作為它的別名。
例如 在pojo包下有一個(gè)名為User的類,那么掃描后的返回類型就為user
注解別名
和上側(cè)相同,當(dāng)包下的類有注解時(shí),注解為Alias(“”)
則此時(shí)的返回類型就為注解內(nèi)容,并且和類名無關(guān)
例如 在pojo包下有一個(gè)名為User的類,注解為Alias(“hello”),那么掃描后的返回類型為hello,并不為user
換一種說法,也就是在掃描包別名是,注解的優(yōu)先級大于類名別名優(yōu)先級
映射器配置
映射器
映射器配置共有3中配置方法
1.resource
配置這種資源,每一層需要斜杠間隔(/)
2.class
使用映射器中的class映射必須遵守以下規(guī)則,否則就會(huì)報(bào)錯(cuò)
接口和它的Mapper配置文件名稱保持一致接口和它的Mapper配置文件需要在同一個(gè)包下
3.package掃描方法
使用映射器中的package方法也必須遵循以下規(guī)則
接口和它的Mapper配置文件名稱保持一致接口和它的Mapper配置文件需要在同一個(gè)包下
另外還有一種url路徑反射,因?yàn)槁窂絾栴},所以很難尋找(不建議使用)。
mybatis官方url定位介紹
ResultMap
問題
當(dāng)pojo中的字段與數(shù)據(jù)庫中的字段不同時(shí),則可能會(huì)導(dǎo)致項(xiàng)目某些功能運(yùn)行失敗
因?yàn)樽侄蚊灰恢?,運(yùn)行結(jié)果導(dǎo)致結(jié)果查詢失敗
解決方法
方法一
(起別名)
select * from Users
相當(dāng)于
select id,name,pwd from Users
為此,我們必須為pwd起一個(gè)別名
select id,name,pwd as password from Users
然后就可以查詢到password這個(gè)字段對應(yīng)在數(shù)據(jù)庫pwd中的值了
方法二;
(更改前)使用ResultMap集合
select id,name, pwd as password from Users
(更改后)其中resultType更換為resultMap
select id,name, pwd from Users
然后追加一個(gè)屬性
此處標(biāo)簽屬性介紹
id - 相當(dāng)于綁定標(biāo)識(shí) -在這里綁定到 resultMap=“usersResultMap” -即id=“usersResultMap”
type-相當(dāng)于返回類型–返回類型為實(shí)體類中的類—type =“Users”
column–列表,數(shù)據(jù)庫中的字段–column=“pwd”
property–屬性,java類中字段名–property=“password”
當(dāng)然,在我們這個(gè)實(shí)例當(dāng)中,字段id和name和數(shù)據(jù)庫中的字段并沒有區(qū)別,所以我們可以適當(dāng)進(jìn)行刪減
這樣就體現(xiàn)到了resultMap的一個(gè)優(yōu)點(diǎn)
是否使用resultMap
當(dāng)連表查詢等復(fù)雜查詢時(shí),建議使用resultMap 進(jìn)行項(xiàng)目創(chuàng)建
當(dāng)僅僅是簡單查詢時(shí),不建議使用resultMap
為了保證項(xiàng)目的簡潔,建議在創(chuàng)建實(shí)體類時(shí),最后將數(shù)據(jù)庫和實(shí)體類中的字段名一一對應(yīng)。
日志
日志工廠
日志簡而言之是提供操作記錄,有時(shí)便于我們進(jìn)行排錯(cuò)
日志工廠在設(shè)置中進(jìn)行添加,即
key–> logImpl
value—>
SLF4JLOG4J (常用)LOG4J2JDK_LOGGINGCOMMONS_LOGGINGSTDOUT_LOGGING (常用,標(biāo)準(zhǔn))NO_LOGGING
重要:使用日志工廠時(shí),必須保證大小寫,數(shù)量一致,空格多少也會(huì)導(dǎo)致錯(cuò)誤。
STDOUT_LOGGING
STDOUT_LOGGING
觀察控制臺(tái)輸出結(jié)果
前部分一些處理(暫且不看)
總體來說便于理解如何實(shí)現(xiàn)SQL查詢
LOG4J
什么是LOG4J
Log4j是Apache的一個(gè)開發(fā)源代碼項(xiàng)目,通過使用Log4j,我們可以控制日志信息輸送的目的地是控制臺(tái)、文件、GUI組件,甚至是套接口服務(wù)器、NT的實(shí)踐記錄器、UNIX Syslog守護(hù)進(jìn)程等;我們也可以控制每一條日志的輸出格式;通過定義每一條日志信息的級別,我們能夠更加細(xì)致地控制日志的生成過程??梢酝ㄟ^一個(gè)配置文件進(jìn)行靈活的配置
導(dǎo)入LOG4J包
配置LOG4J配置
log4j.rootLogger=DEBUG,console,file
\#控制臺(tái)輸出的相關(guān)設(shè)置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
\#文件輸出的相關(guān)設(shè)置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/caiji.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=【%p】【%d{yy-MM-dd}】【%c】%m%n
\#日志輸出級別
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
將大括號(hào)改為英文下的
運(yùn)行后可能出現(xiàn)的問題
日志目錄下的log存在打不開的現(xiàn)象
出現(xiàn)的原因可能有
在Mybatis核心配置文件當(dāng)中 解決 將包掃描改為其他方式查找資源 LOG4J日志化打印格式 Log4J采用類似C語言中的printf函數(shù)的打印格式格式化日志信息,打印參數(shù)如下: %m輸出代碼中指定的消息; %M輸出打印該條日志的方法名; %p輸出優(yōu)先級,即DEBUG,INFO,WARN,ERROR,F(xiàn)ATAL; %r輸出自應(yīng)用啟動(dòng)到輸出該log信息耗費(fèi)的毫秒數(shù); %c輸出所屬的類目,通常就是所在類的全名; %t輸出產(chǎn)生該日志事件的線程名; %n輸出一個(gè)回車換行符,Windows平臺(tái)為"rn”,Unix平臺(tái)為"n”; %d輸出日志時(shí)間點(diǎn)的日期或時(shí)間,默認(rèn)格式為ISO8601,也可以在其后指定格式,比如:%d{yyyy-MM-ddHH:mm:ss,SSS},輸出類似:2002-10-1822:10:28,921; %l輸出日志事件的發(fā)生位置,及在代碼中的行數(shù)。 LOG4J簡單應(yīng)用 首先需要一個(gè)Logger對象,獲取當(dāng)前類的信息,并通過這個(gè)對象來進(jìn)行操作日志 static Logger logger = Logger.getLogger(Text.class); //因?yàn)槿罩竞枚喽夹枰褂茫砸嵘饔糜?/p> 然后進(jìn)行一個(gè)簡單的測試 static Logger logger = Logger.getLogger(Text.class); @Test public void TestLOG4J(){ logger.info("INFO:進(jìn)入方法"); logger.debug("DEBUG:進(jìn)入方法"); logger.error("ERROR:進(jìn)入方法"); } 其中,logger.info logger.debug logger.error 相當(dāng)于java中的System.out.println() 測試結(jié)果 log日志 輸出了方法 其中,優(yōu)先級 Error >Info>debug OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL 以此遞減 Limit分頁 首先,如果使用的是SQLServer數(shù)據(jù)庫,那么他的分頁方法有四種,并不是Limit關(guān)鍵字進(jìn)行分頁 limit關(guān)鍵字是mySql數(shù)據(jù)庫進(jìn)行分頁操作時(shí)的關(guān)鍵字。 在這里使用SQLServer數(shù)據(jù)庫進(jìn)行分頁查詢 使用map為參數(shù)查詢 編寫分頁查詢接口 //分頁 List 采用傳遞Map接口來傳遞參數(shù)更快捷簡單 編寫接口配置文件 select top ${pageSize} * from Users where id not in(select top ${pageIndex} id from Users ORDER BY id) 其中usersResultMap綁定在resultMap當(dāng)中,用于上一次解決字段名不相同問題 ${pageSize} 以及 ${pageIndex} 為自定義名字,用于傳遞參數(shù),在測試類當(dāng)中我們將以此為Key值進(jìn)行傳遞參數(shù)。 需要注意的是: 在編寫SQL語句時(shí),一般在數(shù)據(jù)庫具有字段可變參格式 例如,id=#{id} 自行構(gòu)造參數(shù)傳遞時(shí),例如分頁查詢,其傳遞參數(shù)僅僅為#{pageSize} 當(dāng)SQL語句當(dāng)中top 等關(guān)鍵字出現(xiàn)時(shí),傳遞的參數(shù)格式就需要 ${pageSize} 原因是top關(guān)鍵字后占位符不能使用#{}來進(jìn)行占位 但是有可能會(huì)有注入問題出現(xiàn) 編寫Test測試 @Test public void TestLimit(){ SqlSession sqlSession = UsersUtils.getSqlSession(); UsersMapper mapper = sqlSession.getMapper(UsersMapper.class); HashMap map.put("pageSize",2); map.put("pageIndex",1); List for (Users u : us) { System.out.println(u); } sqlSession.close(); } RowBounds分頁查詢(了解) RowBounds查詢屬于面向?qū)ο蟛樵儯ü俜讲唤ㄗh使用) 編寫Mapper接口 List 編寫接口配置文件即SQL select * from Users 測試類 簡單查詢分頁,沒有調(diào)用UsersMapper接口中的方法,不需要獲取其反射對象 @Test public void TestRowBounds(){ SqlSession sqlSession = UsersUtils.getSqlSession(); RowBounds rowBounds = new RowBounds(1,2); //另一種獲取Mapper接口的方法 //權(quán)限命名 List for (Users users : usersList) { System.out.println(users); } sqlSession.close(); } 注解開發(fā) 一個(gè)簡單的注解開發(fā)案例 編寫接口 //注解開發(fā) @Select("select * from Users") List 將mybatis核心配置文件的映射部分改為Class映射 編寫測試類 @Test public void TestCom(){ SqlSession sqlSession = UsersUtils.getSqlSession(); UsersMapper mapper = sqlSession.getMapper(UsersMapper.class); List for (Users users : List) { System.out.println(users); } sqlSession.close(); } CURD 編寫接口 //注解開發(fā) @Select("select * from Users") List //增 @Insert("Insert Users (id,name,pwd) values(#{id},#{name},#{password})") int insertUsers(Users users); //改 @Update("update Users set name=#{name},pwd=#{password} where id=#{id}") int updateUsers(Users users); //刪 @Delete("delete from Users where id=#{id}") int delectUsers(@Param("id") int id); @Param參數(shù)注解,后面參數(shù)名稱 測試類 省略 lombok 多對一的處理 搭建復(fù)雜SQL查詢環(huán)境 創(chuàng)建Student表 create table Student( id int not NULL primary key, name varchar(20) Null, tid int null ) 創(chuàng)建Teacher表 create table Teacher( id int not NULL primary key, name varchar(20) null ) 創(chuàng)建外鍵 alter table Student add constraint FK_Student_tid foreign key(tid) references Teacher (id) association 多對一 多個(gè)學(xué)生面對同一個(gè)老師 collection 集合 一對多 一個(gè)老師擁有多個(gè)學(xué)生 實(shí)體類 public class Student { private int id; private String name; private Teacher teacher; } public class Teacher { private int id; private String name; } 按照查詢嵌套處理 select * from Student select * from Teacher where id=#{tid} 按照結(jié)果嵌套處理 select s.id sid, s.name sname, t.name tname from Student s,Teacher t where s.tid=t.id 接口類 public interface StudentMapper { //獲取學(xué)生別表 // @Select("select * from Student") List //獲取學(xué)生信息 List } 一對多處理 一個(gè)老師擁有多個(gè)學(xué)生 collection 集合 實(shí)體類 public class Student { private int id; private String name; } public class Teacher { private int id; private String name; private List } 按照查詢嵌套處理 select * from Teacher where id=#{id} select * from Student where tid =#{id} 按照結(jié)果嵌套處理 select s.id sid, s.name sname ,t.id tid ,t.name tname from Student s,Teacher t where s.tid=t.id and s.tid=#{id} 接口類 public interface TeacherMapper { //獲取老師列表 List //查詢?nèi)?/p> List } 動(dòng)態(tài)SQL環(huán)境搭建 什么是動(dòng)態(tài)SQL 動(dòng)態(tài)SQL就是根據(jù)不同的條件生成不同的SQL語句 創(chuàng)建表 利用mybatis 添加數(shù)據(jù) pojo實(shí)體類 public class Blog { private String id; private String title; private String author; private Date createTime; private int views; } 數(shù)據(jù)庫中的字段名與實(shí)體類中的橫杠不統(tǒng)一 createTime----create_time 解決方法 在mybatis-config.xml核心配置文件當(dāng)中設(shè)置 開啟駝峰轉(zhuǎn)換 BlogMapper //添加Blog用戶 int addBlogList(Blog blog); BlogMapper.xml insert Blog(id,title,author,create_time,views)values(#{id},#{title},#{author},#{createTime},#{views}) 測試類 //添加用戶 @Test public void addBlogList(){ SqlSession sqlSession = UserUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); Blog blog = new Blog(); blog.setId(IDUtils.getUUid()); blog.setTitle("JAVA的入門"); blog.setAuthor("咸魚"); blog.setCreateTime(new Date()); blog.setViews(9999); mapper.addBlogList(blog); blog.setId(IDUtils.getUUid()); blog.setTitle("JAVA的開始"); blog.setAuthor("咸魚"); blog.setCreateTime(new Date()); blog.setViews(8080); mapper.addBlogList(blog); blog.setId(IDUtils.getUUid()); blog.setTitle("JAVA的進(jìn)階"); blog.setAuthor("咸魚"); blog.setCreateTime(new Date()); blog.setViews(6666); mapper.addBlogList(blog); blog.setId(IDUtils.getUUid()); blog.setTitle("JAVA的精通"); blog.setAuthor("咸魚"); blog.setCreateTime(new Date()); blog.setViews(9999); mapper.addBlogList(blog); sqlSession.close(); } 動(dòng)態(tài)SQL—if 當(dāng)我們想要做一個(gè)類似于查找的功能時(shí),例如通過title和author進(jìn)行模糊查找 我們可以選擇只填寫title 或者只填寫author 如果僅僅采用編寫多個(gè)方法來應(yīng)對不同的需求時(shí),那么這些代碼將有很多重復(fù),不簡潔 select * from User where title=? and author=? select * from User where title=? select * from User where author=? 這樣寫一個(gè)功能 使用3個(gè)sql進(jìn)行多次查詢? 這樣也太麻煩了 為此 我們將采用動(dòng)態(tài)sql中的if查詢 同樣是上側(cè)的案例 接口方法:(采用map作為參數(shù)進(jìn)行傳值,通過put進(jìn)行動(dòng)態(tài)添加key,value) //動(dòng)態(tài)SQLif List mapper.xml select * from Blog where 1=1 and title=#{title} and author=#{author} 首先,先書寫一個(gè)用于查詢?nèi)繑?shù)據(jù)的SQL語句,然后在后添加一個(gè)Where 1=1 ,添加where 1=1 的目的就是在沒有任何條件下的查詢語句 ,其作用和 select * from Blog 作用相等(但是在項(xiàng)目書寫代碼中,where 1=1并不符合規(guī)范,這里使用僅僅是為了學(xué)習(xí)if,接下來會(huì)有解決這個(gè)問題的知識(shí)。) 然后在使用if語句進(jìn)行判斷,當(dāng)有title這個(gè)值存在時(shí),就把他拼接進(jìn)去。同理 author也是如此。 這樣就使用一個(gè)sql語句就解決帶有N多種條件的查詢啦! 動(dòng)態(tài)SQL—where where 解決where 1=1 的問題 //動(dòng)態(tài)SQLif2 where標(biāo)簽 List select * from Blog and title =#{title} and author=#{author} 添加where標(biāo)簽,可以在if滿足的條件下,自動(dòng)添加where標(biāo)簽。并且自動(dòng)檢測是否在第一項(xiàng),自動(dòng)省略第一個(gè)條件的and標(biāo)簽。 另外,有時(shí)候where自動(dòng)省略and 或者or 標(biāo)簽失敗。 所以,解決此問題的方法自定義設(shè)定 ... prefix------前綴 prefixOverrides------前綴覆蓋 set //動(dòng)態(tài)SQL update set標(biāo)簽 int updateList(Map map); update Blog where id=#{id} 自動(dòng)將后面的,進(jìn)行覆蓋或者顯現(xiàn) ... choose、when、otherwise //choose選擇 List select * from Blog and views=#{views} choose選擇器,相當(dāng)于java中的while 當(dāng)?shù)谝恢蟹蠒r(shí),其余的都不會(huì)有效 當(dāng)有一種符合時(shí),其他都會(huì)無效。 SQL片段 //sql片段。實(shí)現(xiàn)sql復(fù)用 List select * from Blog and title =#{title} and author=#{author} 定義sql以實(shí)現(xiàn)sql 的復(fù)用 最好不要將where等標(biāo)簽放入sql語句當(dāng)中,以提供sql語句的多次復(fù)用 foreach(* //sqlforeach查詢 List select * from Blog id=#{id} 測試 //sqlforeach @Test public void getIfListTest4(){ SqlSession sqlSession = UserUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); HashMap map = new HashMap(); ArrayList ids = new ArrayList(); ids.add("1"); ids.add("2"); map.put("ids",ids); List for (Blog blog : list2) { System.out.println(blog); } sqlSession.close(); } 在這里分隔符需要使用or 其他可能會(huì)報(bào)錯(cuò) 動(dòng)態(tài)SQL,就是在拼接SQL,保證SQL的正確性,按照SQL格式 緩存 在Mybatis當(dāng)中,分為一級緩存和二級緩存 一級緩存 一級緩存和SQLsession同級別 在創(chuàng)建session和關(guān)閉session之間有效。 緩存可以緩存所有的select語句,每當(dāng)出現(xiàn)update、insert、delect出現(xiàn)時(shí),緩存將會(huì)失效,將會(huì)被刷新 一級緩存是默認(rèn)緩存 二級緩存 雖然在設(shè)置當(dāng)中默認(rèn)開啟了二級緩存的總開關(guān),但是為了保證代碼的可讀性,建議在xml核心配置文件當(dāng)中設(shè)置 在Mapper里添加下面的標(biāo)簽開啟二級緩存 Mybatis緩存原理 (首次)開啟sqlsession查詢數(shù)據(jù)庫,然后存入一級緩存,當(dāng)SQLsession關(guān)閉后,一級緩存將會(huì)存入該Mapper中的二級緩存當(dāng)中。 (再次)查詢過程 r"> and title =#{title} and author=#{author} ``` 定義sql以實(shí)現(xiàn)sql 的復(fù)用 最好不要將where等標(biāo)簽放入sql語句當(dāng)中,以提供sql語句的多次復(fù)用 foreach(* //sqlforeach查詢 List select * from Blog id=#{id} 測試 //sqlforeach @Test public void getIfListTest4(){ SqlSession sqlSession = UserUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); HashMap map = new HashMap(); ArrayList ids = new ArrayList(); ids.add("1"); ids.add("2"); map.put("ids",ids); List for (Blog blog : list2) { System.out.println(blog); } sqlSession.close(); } [外鏈圖片轉(zhuǎn)存中…(img-vgNIQlbm-1703315948656)] 在這里分隔符需要使用or 其他可能會(huì)報(bào)錯(cuò) 動(dòng)態(tài)SQL,就是在拼接SQL,保證SQL的正確性,按照SQL格式 緩存 在Mybatis當(dāng)中,分為一級緩存和二級緩存 一級緩存 一級緩存和SQLsession同級別 在創(chuàng)建session和關(guān)閉session之間有效。 緩存可以緩存所有的select語句,每當(dāng)出現(xiàn)update、insert、delect出現(xiàn)時(shí),緩存將會(huì)失效,將會(huì)被刷新 一級緩存是默認(rèn)緩存 二級緩存 [外鏈圖片轉(zhuǎn)存中…(img-TXo9UTXP-1703315948657)] 雖然在設(shè)置當(dāng)中默認(rèn)開啟了二級緩存的總開關(guān),但是為了保證代碼的可讀性,建議在xml核心配置文件當(dāng)中設(shè)置 在Mapper里添加下面的標(biāo)簽開啟二級緩存 Mybatis緩存原理 (首次)開啟sqlsession查詢數(shù)據(jù)庫,然后存入一級緩存,當(dāng)SQLsession關(guān)閉后,一級緩存將會(huì)存入該Mapper中的二級緩存當(dāng)中。 (再次)查詢過程 先從二級緩存中查詢是否有此查詢的緩存,若沒有,然后在一次緩存當(dāng)中查詢是否有此緩存,如果都沒有,那么連接數(shù)據(jù)庫,進(jìn)行查詢。 柚子快報(bào)邀請碼778899分享:MyBatis筆記 精彩文章
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。