MyBatis操作數據庫(入門)

本節目標

  • 使用MyBatis完成簡單的增刪改查操作,參數傳遞
  • 掌握MyBatis的兩種寫法:注解和XML方式
  • 掌握MyBatis相關的日志配置

前言

????????在應用分層學習中,我們了解web應用程序一般分為三層,即Controller、Service、Dao。在之前的案例中,請求流程如下:瀏覽器發起請求,先請求Controller,Controller接收到請求之后,調用Service進行業務邏輯處理,Service再調用Dao,但是Dao層的數據是Mock的,真實的數據應該從數據庫中讀取。

????????我們學習MySQL數據庫時,已經學習了JDBC來操作數據庫,但是JDBC操作太復雜了。

JDBC操作示例回顧

  1. 創建數據庫連接池DataSource
  2. 通過DataSource獲取數據庫連接Connection
  3. 編寫要執行帶?占位符的SQL語句
  4. 通過Connection及SQL創建操作命令對象Statement
  5. 替換占位符:指定要替換的數據庫字段類型,占位符索引及要替換的值
  6. 使用Stament執行SQL語句
  7. 查詢操作:返回結果集ResultSet,更新操作:返回更新的數量
  8. 處理結果集
  9. 釋放資源

從上述流程可以看出,對于JDBC來說,整個操作非常的繁瑣,那么有沒有一種方法,可以更簡單、更方便的操作數據庫呢?


目錄

前言

一、什么是MyBatis?

二、MyBatis入門?

2.1 準備工作

2.1.1 創建工程

2.1.2 數據準備?

2.2 配置數據庫連接字符串?

2.3 寫持久層代碼

三、MyBatis的基本操作?

3.1 打印日志?

3.2 參數傳遞?

3.3 增(Insert)?

3.4 刪(Delete)

3.5 改(update)?

3.6 查(select)

3.6.1 起別名

3.6.2 結果映射?

3.6.3 開啟駝峰命名(推薦)?

四、MyBatis XML配置文件?

4.1 配置連接字符串和MyBatis

4.2 寫持久層代碼?

4.2.1 添加mapper接口

4.2.2 添加UserinfoXmlMapper.xml?

4.3 增刪改查操作?

4.3.1 增(Insert)

4.3.2 刪(Delete)

4.3.3 改(Update)?

4.3.4 查(Select)

五、多表查詢?

六、#{}和${}

6.1 #{}和${}使用

6.2 #{}和${}區別?

6.3 #{}的優勢?

6.4 排序功能

6.5 like查詢


一、什么是MyBatis?

  • MyBatis是一款優秀的持久層框架,用于簡化JDBC的開發
  • MyBatis本是Apache的一個開源項目iBatis,2010年這個項目由apache遷移到google code,并改名為MyBatis。

持久層:指的就是持久化操作的層,通常指數據訪問層(dao),用來操作數據庫的。

簡單來說MyBatis是更簡單完成程序和數據庫交互的框架,也就是更簡單的操作和讀取數據工具

二、MyBatis入門?

MyBatis操作數據庫的步驟:

  • 準備工作(創建springboot工程、數據庫表準備,實體類)
  • 引入MyBatis的相關依賴,配置MyBtis(數據庫連接信息)
  • 編寫SQL語句(注解/XML)
  • 測試

2.1 準備工作

2.1.1 創建工程

創建springbboot工程,并導入MyBatis的依賴,MySQL的驅動包

2.1.2 數據準備?

創建用戶表,并創建對應的實體類UserInfo

-- 創建數據庫
DROP DATABASE IF EXISTS mybatis_test;CREATE DATABASE mybatis_test DEFAULT CHARACTER SET utf8mb4;-- 使用數據數據
USE mybatis_test;-- 創建表[用戶表]
DROP TABLE IF EXISTS userinfo;
CREATE TABLE `userinfo` (`id` INT ( 11 ) NOT NULL AUTO_INCREMENT,`username` VARCHAR ( 127 ) NOT NULL,`password` VARCHAR ( 127 ) NOT NULL,`age` TINYINT ( 4 ) NOT NULL,`gender` TINYINT ( 4 ) DEFAULT '0' COMMENT '1-男 2-女 0-默認',`phone` VARCHAR ( 15 ) DEFAULT NULL,`delete_flag` TINYINT ( 4 ) DEFAULT 0 COMMENT '0-正常, 1-刪除',`create_time` DATETIME DEFAULT now(),`update_time` DATETIME DEFAULT now(),PRIMARY KEY ( `id` ) 
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4; -- 添加用戶信息
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'admin', 'admin', 18, 1, '18612340001' );
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'zhangsan', 'zhangsan', 18, 1, '18612340002' );
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'lisi', 'lisi', 18, 1, '18612340003' );
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'wangwu', 'wangwu', 18, 1, '18612340004' );

創建對應的實體類UserInfo

import lombok.Data;import java.util.Date;@Data
public class Userinfo {private Integer id;private String username;private String password;private Integer age;private Integer gender;private String phone;private Integer deleteFlag;private Date createTime;private Date updateTime;}

2.2 配置數據庫連接字符串?

MyBatis中要連接數據庫,需要數據庫相關參數配置

  • MySQL驅動類
  • 登錄名
  • 密碼
  • 數據庫連接字符串?

?如果是application.yml文件,配置內容如下:

#數據庫連接配置
spring:datasource:url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=falseusername: rootpassword: 111111driver-class-name: com.mysql.cj.jdbc.Driver

2.3 寫持久層代碼

在項目中,創建持久層接口UserInfoMapper?

import com.example.MyBatis.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;import java.util.List;@Mapper
public interface UserInfoMapper {@Select("select * from userinfo")List<UserInfo> getUserInfoAll();
}

MyBatis的持久層接口規范一般都叫xxxMapper

@Mapper注解:表示是MyBatis中的Mapper接口

  • 程序運行時,框架會自動生成接口的實現類對象(代理對象),并交給Spring的IOC容器管理
  • @Select注解:代表的就是select查詢,也就是注解對應方法的具體實現內容

使用IDEA自動生成測試類

1、在需要測試的Mapper接口中,右鍵->Generate->Test

2、書寫測試代碼

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import static org.junit.jupiter.api.Assertions.*;@SpringBootTest
class UserInfoMapperTest {@Autowiredprivate UserInfoMapper userInfoMapper;@Testvoid getUserInfoAll() {System.out.println(userInfoMapper.getUserInfoAll());}
}

測試類上添加了注解@SpringBootTest,在測試類在運行時,就會自動加載Spring的運行環境。我們通過@Autowired這個注解,注入我們要測試的類,就可以開始進行測試了。

運行結果如下:

三、MyBatis的基本操作?

????????上面我們學習了MyBatis的查詢操作,接下來我們學習MyBatis的增,刪,改操作,在學習這些操作之前,我們先來學習MyBatis日志打印。

3.1 打印日志?

在MyBatis當中我們可以借助日志,查看sql語句的執行、執行傳遞的參數以及執行結果。

在配置文件中進行配置即可

mybatis:configuration: # 配置打印 MyBatis?志log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

重新運行程序,可以看到SQL執行內容,以及傳遞參數和執行結果。

3.2 參數傳遞?

需求:查詢id=2的用戶,對應的SQL語句就是:select * from userinfo where id = 2

但是這樣的話,只能查找id=2的數據,所以SQL語句中的id值不能寫成固定的值,需要變為動態的數值。解決辦法:在方法中添加一個參數,將方法中的參數,傳給SQL語句,使用#{}的方式獲取方法中的參數

@Select("select * from userinfo where id = #{id}")List<UserInfo> getUserInfoById(Integer id);

注意:如果mapper接口方法形參只有一個普通類型的參數,#{}里面的屬性名可以隨便寫。建議還是和參數名保持一致。

添加測試用例

@Testvoid getUserInfoById() {System.out.println(userInfoMapper.getUserInfoById(2));}

運行結果:

也可以通過@Param,設置參數的別名,如果使用@Param設置別名,#{}里面的屬性名必須和@Param設置一樣

@Select("select * from userinfo where id = #{iid}")List<UserInfo> getUserInfoById2(@Param("iid") Integer id);

如果#{}里面的屬性名必須和@Param設置不一樣,我們運行代碼。

運行結果:??

3.3 增(Insert)?

Mapper接口

@Options(useGeneratedKeys = true, keyProperty = "id")@Insert("insert into userinfo (username, password, age, gender) " +"values (#{username}, #{password}, #{age}, #{gender})")Integer insert(UserInfo userInfo);

直接使用UserInfo對象的屬性名來獲取參數

測試代碼:

@Testvoid insert() {UserInfo userinfo = new UserInfo();userinfo.setUsername("zzz");userinfo.setPassword("123");userinfo.setAge(18);userinfo.setGender(1);Integer result = userInfoMapper.insert(userinfo);System.out.println("result: " + result + ", id" + userinfo.getId());}

運行結果:

返回主鍵

Insert語句默認返回的是受影響的行數,但是在有些情況下,數據插入之后,還需要有后續的關聯操作,需要獲取到新插入數據的id

比如訂單系統

當我們下完訂單之后,需要通知物流系統,這時就需要拿到訂單id

如果想要拿到自增id,需要在Mapper接口上添加一個Options的注解

  • useGeneratedKeys:這會令MyBatis使用JDBC的getGeneratedKeys方法來取出數據庫內部生成的主鍵
  • keyProperty:指定能夠唯一識別對象的屬性,MyBatis會使用getGeneratedKeys的返回值或insert語句的selectKey子元素設置它的值

3.4 刪(Delete)

Mapper接口

@Delete("delete from userinfo where id = #{id}")Integer delete(Integer id);

測試用例

@Testvoid delete() {System.out.println(userInfoMapper.delete(10));}

運行截圖?

3.5 改(update)?

Mapper接口

@Update("update userinfo set username = #{username} where id = #{id}")Integer update(UserInfo userInfo);

測試用例

@Testvoid update() {UserInfo userInfo = new UserInfo();userInfo.setUsername("李四");userInfo.setId(9);System.out.println(userInfoMapper.update(userInfo));}

?運行截圖

3.6 查(select)

Mapper接口

@Select("select * from userinfo")List<UserInfo> getUserInfoAll();

測試用例

@Testvoid getUserInfoAll() {System.out.println(userInfoMapper.getUserInfoAll());}

運行截圖

?觀察數據庫中的字段

從運行結果上可以看出,我們SQL語句中,查詢了delete_flag,create_flag,update_time,這幾個字字段在數據庫中是有賦值的,但是在控制臺中顯示為空?,這是為什么呢

原因分析:?

當自動映射查詢結果時,MyBatis會獲取結果中返回的列名并在Java類中查找相同名字的屬性(忽略大小寫)。這意味著如果發現了ID列和id屬性,MyBatis會將ID列的值賦給id屬性。

注意:?

MyBatis會根據方法的返回結果進行賦值。

方法用對象Userinfo接收返回結果,MySQL查詢出來數據為一條,就會自動賦值給對象。

方法用List<Userinfo>接收返回結果,MySQL查詢出來數據為一條或多條時,也會自動賦值給List。

但如果MySQL查詢結果返回多條,但是方法返回值使用Userinfo接收,MyBatis執行就會報錯。

解決上述為null的辦法:

  1. 起別名
  2. 結果映射
  3. 開啟駝峰命名

3.6.1 起別名

Mapper接口

@Select("select id, username, password, age, gender, phone, delete_flag as deleteFlag, " +"create_time as createTime, update_time as updateTime from userinfo")List<UserInfo> queryAllUser();

測試代碼

@Testvoid queryAllUser() {System.out.println(userInfoMapper.queryAllUser());}

運行截圖

3.6.2 結果映射?

Mapper接口

@Results(id = "resultMap", value = {@Result(column = "delete_flag", property = "deleteFlag"),@Result(column = "create_time", property = "createTime"),@Result(column = "update_time", property = "updateTime")})@Select("select * from userinfo")List<UserInfo> queryAllUser2();

測試代碼

@Testvoid queryAllUser2() {System.out.println(userInfoMapper.queryAllUser2());}

運行截圖

如果其它SQL,也希望可以復用這個映射關系,可以用上述代碼定義的名稱resultMap

@Select("select * from userinfo")
@ResultMap(value = "resultMap")
List<UserInfo> queryAllUser3();

3.6.3 開啟駝峰命名(推薦)?

????????通常數據庫列使用蛇形命名法進行命名(下劃線分割各個單詞),而Java屬性一般遵循駝峰命名法約定。為了在這兩種方法之間啟動自動映射,需要將mapUnderscoreToCamelCase設置為true

mybatis:configuration: map-underscore-to-camel-case: true

四、MyBatis XML配置文件?

MyBatis的開發有兩種方式:

  1. 注解
  2. XML

上面學習了注解的方式,接下來我們學習XML的方式

使用MyBatis的注解方式,主要是來完成一些簡單的增刪查改功能,如果需要實現復雜的SQL功能,建議使用XML來配置映射語句,也就是將SQL語句寫在XML配置文件中。

MyBatis XML的方式需要以下兩步

  • 配置數據庫連接字符串和MyBatis
  • 寫持久層代碼

4.1 配置連接字符串和MyBatis

此步驟需要進行兩項設置,數據庫連接字符串設置和MyBatis的XML文件配置。

application.yml文件,配置內容如下:

#數據庫連接配置
spring:datasource:url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=falseusername: rootpassword: 111111driver-class-name: com.mysql.cj.jdbc.Drivermybatis:mapper-locations: classpath:mapper/**Mapper.xmlconfiguration: # 配置打印 MyBatis?志log-impl: org.apache.ibatis.logging.stdout.StdOutImplmap-underscore-to-camel-case: true

配置mybatis xml文件路徑,在resources/mapper下創建的所有XML文件?

4.2 寫持久層代碼?

持久層代碼分兩部分

  1. 方法定義interface
  2. 方法實現:XXX.xml

4.2.1 添加mapper接口

數據庫持久層的接口定義:

import com.example.MyBatis.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;import java.util.List;@Mapper
public interface UserinfoXmlMapper {List<UserInfo> queryAllUser();
}

4.2.2 添加UserinfoXmlMapper.xml?

數據庫持久層的實現,MyBatis的固定xml格式:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.MyBatis.mapper.UserinfoXmlMapper"></mapper>

創建UserInfoXmlMapper.xml,路徑參考yml中的配置

查詢所有用戶的具體實現:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.MyBatis.mapper.UserinfoXmlMapper"><select id="queryAllUser" resultType="com.example.MyBatis.model.UserInfo">select * from userinfo</select>
</mapper>

以下是對以上標簽的說明:

  • <mapper>標簽:需要指定namespace屬性,表示命名空間,值為mapper接口的全限定名,包括全包名.類名
  • <select>查詢標簽:是用來執行數據庫的查詢操作的:
    • id: 是和Interface(接口)中定義的方法名稱一樣的,表示對接口的具體實現方法
    • resultType:是返回的數據類型,也就是開頭我們定義的實體類

4.3 增刪改查操作?

4.3.1 增(Insert)

UserInfoMapper接口:

Integer insertUser(Userinfo userinfo);

UserInfoMapper.xml實現:

<insert id="insertUser">insert into userinfo (username, password, age, gender, phone) values (#{username},#{password}, #{age}, #{gender}, #{phone})
</insert>

4.3.2 刪(Delete)

UserInfoMapper接口:

Integer deleteUser(Integer id);

UserInfoMapper.xml實現:

<delete id="deleteUser">delete from userinfo where id = #{id}
</delete>

4.3.3 改(Update)?

UserInfoMapper接口:

Integer updateUser(Userinfo userinfo);

?UserInfoMapper.xml實現:

<update id="updateUser">update userinfo set username = #{username} where id = #{id}
</update>

4.3.4 查(Select)

????????同樣的,使用XML的方式進行查詢,也存在數據封裝的問題,我們把SQL語句進行簡單修改,查詢更多的字段內容。

<select id="queryAllUser" resultType="com.example.mybatis.model.Userinfo">select id, username, password, age, gender, phone, delete_flag, create_time, update_timefrom userinfo
</select>

運行截圖:

?結果顯示:deleteFlag, createTime, updateTime也沒有賦值

解決辦法和注解類似:

  • 起別名
  • 結果映射
  • 開啟駝峰命名

?重點講下xml來寫結果映射

Mapper.xml

<resultMap id="BaseMap" type="com.example.mybatis.model.Userinfo"><id column="id" property="id"></id><result column="delete_flag" property="deleteFlag"></result><result column="create_time" property="createTime"></result><result column="update_time" property="updateTime"></result></resultMap><select id="queryAllUser" resultMap="BaseMap" resultType="com.example.mybatis.model.Userinfo">select id, username, password, age, gender, phone, delete_flag, create_time, update_timefrom userinfo</select>

五、多表查詢?

多表查詢和單表查詢類似,只是SQL不同而已

實體類

import lombok.Data;import java.util.Date;@Data
public class Userinfo {private Integer id;private String username;private String password;private Integer age;private Integer gender;private String phone;private Integer deleteFlag;private Date createTime;private Date updateTime;
}

Mapper接口

import com.example.mybatis.model.ArticleInfo;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface ArticleInfoXmlMapper {ArticleInfo selectArticleAndUserById(Integer id);
}

ArticleInfoXmlMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mybatis.mapper.ArticleInfoXmlMapper"><select id="selectArticleAndUserById" resultType="com.example.mybatis.model.ArticleInfo">select article.*, user.username, user.gender from articleinfo articleleft join userinfo useron article.uid = user.idwhere article.id = #{id}</select>
</mapper>

運行結果截圖

?

六、#{}和${}

MyBatis參數賦值有兩種方式,前面使用了#{}進行賦值,接下來我們看下兩者的區別

6.1 #{}和${}使用

1、先看Interger類型的參數

@Select("select username, password, age, gender, phone from userinfo where id = #{id}")Userinfo queryById4(Integer id);

觀察打印日志

?

????????我們輸出的參數并沒有在后面拼接,id的值是使用?進行占位,這種SQL我們稱之為“預編譯SQL”。?

我們把#{}改成${}再觀察打印的日志:

@Select("select username, password, age, gender, phone from userinfo where id = ${id}")Userinfo queryById5(Integer id);

觀察打印日志

?

可以看出,這次參數是直接拼接在SQL語句中了。

2.接下來我們再看String類型的參數

@Select("select username, password, age, gender, phone from userinfo where username = #{name}")Userinfo queryByName(String name);

觀察打印日志:

?

我們把#{}改成${}再觀察打印的日志:

@Select("select username, password, age, gender, phone from userinfo where username = ${name}")Userinfo queryByName2(String name);

觀察打印日志:

?

????????可以看出,這次的參數依然是直接拼接在SQL語句中了,但是字符串作為參數時,需要添加引號'',使用${}不會拼接引號'',導致程序報錯。

修改代碼如下:

@Select("select username, password, age, gender, phone from userinfo where username = '${name}'")Userinfo queryByName2(String name);

再運行觀察打印日志:

?

從上面兩個例子可以看出:

  • #{}使用的是預編譯SQL,通過?占位的方式,提前對SQL進行編譯,然后把參數填充到SQL語句中,#{}會根據參數類型,自動拼接引號''
  • ${}會直接進行字符替換,一起對SQL進行編譯,如果參數為字符串,需要加上引號''

注意:參數為數字類型時,也可以加上,查詢結果不變,但是可能會導致索引失效,性能下降。

6.2 #{}和${}區別?

#{}和${}的區別就是預編譯SQL即時SQL的區別

簡單回顧:

當客戶發送一條SQL語句給服務器后,大致流程如下:

  1. 解析語法和語義,校驗SQL語句是否正確
  2. 優化SQL語句,制定執行計劃
  3. 執行并返回結果

一條SQL如果走上述流程處理,我們稱之為Immediate Statements(即時SQL)

6.3 #{}的優勢?

1、性能更高

? ? ? ? 絕大多數情況下,某一條SQL語句可能會被反復調用執行,或者每次執行的時候只有個別的值不同(比如select的where子句值不同,update的set子句值不同,insert的values值不同),如果每次都需要經過上面的語法解析,SQL優化、SQL編譯等,則效率就明顯不行了。

?

????????預編譯SQL,編譯一次之后會將編譯后的SQL語句緩存起來,后面再次執行這條語句時,不會再次編譯(只是輸入的參數不同),省去了解析優化等過程,以此來提高效率。?

2、更安全(防止SQL注入)?

????????SQL注入:是通過操作輸入的數據來修改事先定義好的SQL語句,以達到執行代碼對服務器進行攻擊的方法。

????????由于沒有對用戶輸入進行充分檢查,而SQL又是拼接而成,在用戶輸入參數時,在參數中添加一些SQL關鍵字,達到改變SQL運行結果的目的,也可以完成惡意攻擊。

SQL注入代碼:' or 1 = '1'

先來看看SQL注入的例子

@Select("select username, password, age, gender, phone from userinfo where username = '${name}'")List<Userinfo> queryByName3(String name);

測試代碼:

正常訪問情況:

@Testvoid queryByName3() {System.out.println(userInfoMapper.queryByName3("admin"));}

結果運行截圖

SQL注入場景

??@Testvoid queryByName3() {System.out.println(userInfoMapper.queryByName3("' or 1 = '1"));}

結果依然被正確查詢出來了,其中參數or被當成了SQL語句的一部分

可以看出,查詢的數據并不是自己想要的數據,所以用于查詢的字段,盡量使用#{}預查詢的方式?

????????SQL注入是一種非常常見的數據庫攻擊手段,SQL注入漏洞也是網絡世界中最普遍的漏洞之一。

? ? ? ? 如果發生在用戶登陸的場景中,密碼輸入為' or 1 = ' 1,就可能完成登陸(不是一定會發生的場景,需要看登陸代碼如何寫)

6.4 排序功能

????????從上面的例子中,可以得出結論:${}會有SQL注入的風險,所以我們盡量使用#{}完成查詢,既然如此,是不是${}就沒有存在的必要性呢?

當然不是

接下來我們看下${}的使用場景

Mapper實現

@Select("select id, username, age, gender, phone, delete_flag, create_time, update_time " +"from userinfo order by id ${sort}")List<Userinfo> queryAllUserBySort(String sort);

使用${sort}可以實現排序查詢,而使用#{sort}就不能實現排序查詢了。?

????????注意:此處sort參數為String類型,但是SQL語句中,排序規則是不需要加引號''的,所以此時的${sort}也不加引號。

我們把${}改成#{}

運行結果:

可以發現,使用#{sort}查詢時,desc前后自動給加了引號,導致sql錯誤

#{}會根據參數類型判斷是否拼接引號,如果參數類型為String,就會加上引號。

除此之外,還有表明作為參數時,也只能使用${}?

6.5 like查詢

like使用#{}報錯

@Select("select id, username, age, gender, phone, delete_flag, create_time, update_time " +"from userinfo where username like '%#{key}%'")List<Userinfo> queryAllUserByLike(String key);

把#{}改成${}可以正確查出來,但是${}存在SQL注入的問題,所以不能直接使用${}。

解決辦法:使用MySQL的內置函數concat()來處理,實現代碼如下:

@Select("select id, username, age, gender, phone, delete_flag, create_time, update_time " +"from userinfo where username like concat('%', #{key}, '%'})")List<Userinfo> queryAllUserByLike(String key);

?

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/38534.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/38534.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/38534.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

化學SCI期刊,中科院4區,易錄用,幾乎不退稿

一、期刊名稱 Chemical Papers 二、期刊簡介概況 期刊類型&#xff1a;SCI 學科領域&#xff1a;化學 影響因子&#xff1a;2.1 中科院分區&#xff1a;4區 三、期刊征稿范圍 該雜志致力于基礎和應用化學和化學工程研究。它的范圍很廣&#xff0c;涵蓋了所有化學科學&…

2024年江蘇智能制造工廠名單:我看出了未來擇業和跳槽方向

導語 大家好&#xff0c;我是社長&#xff0c;老K。專注分享智能制造和智能倉儲物流等內容。 新書《智能物流系統構成與技術實踐》 在當今這個飛速發展的時代&#xff0c;智能制造已成為推動工業進步的強大引擎。隨著技術革新的浪潮一波接一波地涌來&#xff0c;我們不禁要問&a…

動手學深度學習(Pytorch版)代碼實踐 -計算機視覺-49風格遷移

49風格遷移 讀入內容圖像&#xff1a; import torch import torchvision from torch import nn import matplotlib.pylab as plt import liliPytorch as lp from d2l import torch as d2l# 讀取內容圖像 content_img d2l.Image.open(../limuPytorch/images/rainier.jpg) plt.…

使用 Swift 遞歸搜索目錄中文件的內容,同時支持 Glob 模式和正則表達式

文章目錄 前言項目設置查找文件讀取CODEOWNERS文件解析規則搜索匹配的文件確定文件所有者輸出結果總結前言 如果你新加入一個團隊,想要快速的了解團隊的領域和團隊中擁有的代碼庫的詳細信息。 如果新團隊中的代碼庫在 GitHub / GitLab 中并且你不熟悉代碼所有權模型的概念或…

Unity開箱即用的UGUI面板的拖拽移動功能

文章目錄 &#x1f449;一、背景&#x1f449;二、效果圖&#x1f449;三、原理&#x1f449;四、核心代碼&#x1f449;五&#xff0c;總結 &#x1f449;一、背景 之前做PC項目時常常有面板拖拽移動的需求&#xff0c;今天總結封裝一下&#xff0c;做成一個隨時隨地可復用的…

More Effective C++ 35個改善編程與設計的有效方法筆記與心得 3

三. 異常 條款9&#xff1a; 利用destructors避免泄露資源 ????  在編程中&#xff0c;"資源"可以指任何系統級的有限資源&#xff0c;如內存、文件句柄、網絡套接字等。"泄露"則是指在應用程序中分配了資源&#xff0c;但在不再需要這些資源時沒有…

Linux 安裝 Redis 教程

優質博文&#xff1a;IT-BLOG-CN 一、準備工作 配置gcc&#xff1a;安裝Redis前需要配置gcc&#xff1a; yum install gcc如果配置gcc出現依賴包問題&#xff0c;在安裝時提示需要的依賴包版本和本地版本不一致&#xff0c;本地版本過高&#xff0c;出現如下問題&#xff1a…

Jupyter無法導入庫,但能在終端導入的問題

Jupyter無法導入庫&#xff0c;但能在終端導入 ?錯誤問題描述&#xff1a;conda activate LLMs激活某個Conda的環境后&#xff0c;盡管已經通過conda或者pip在這個環境中安裝了一些&#x1f40d;Python的庫&#xff0c;但無法在Jupyter中導入&#xff0c;卻能在終端成功導入。…

京東商品詳情數據接口(JD.item_get)丨京東API實時接口指南

京東商品詳情API接口&#xff08;JD.item_get&#xff09;是京東開放平臺提供的一個數據接口&#xff0c;用于獲取京東平臺上單個商品的詳細信息。 通過這個接口&#xff0c;開發者可以獲取到包括商品名稱、品牌、產地、規格參數、價格信息、銷量、評價、圖片、描述等在內的詳…

Node.js開發實戰 視頻教程 下載

ode.js開發實戰 視頻教程 下載 下載地址 https://download.csdn.net/download/m0_67912929/89487510 01-課程介紹.mp4 02-內容綜述.mp4 03-Node.js是什么? .mp4 04-Node.js可以用來做什么?.mp4 05-課程實戰項目介紹.mp4 06-什么是技術預研? .mp4 07-Node.js開發環境…

Windows 11 安裝 安卓子系統 (WSA)

How to Install Windows Subsystem for Android (WSA) on Windows 11 新手教程&#xff1a;如何安裝Windows 11 安卓子系統 說明 Windows Subsystem for Android 或 WSA 是由 Hyper-V 提供支持的虛擬機&#xff0c;可在 Windows 11 操作系統上運行 Android 應用程序。雖然它需…

【JS】注意考點

1.聲明變量時所遵循的規則&#xff1a; (1)可以使用一個保留關鍵字var同時聲明多個變量 (2)可以在聲明變量的同時對其賦值&#xff0c; (3)如果只是聲明了變量&#xff0c;并未對其賦值&#xff0c;其值就默認為 Undefined。 (4)保留關鍵字var可以用作for語句和for…in語句…

python基礎_類

在Python中&#xff0c;類&#xff08;Class&#xff09;是面向對象編程&#xff08;OOP&#xff09;的核心概念之一。類提供了一種創建新對象的模板&#xff0c;這些對象通常被稱為類的實例或對象。以下是關于Python類的一些關鍵點和特性&#xff1a; 定義類 類通過class關鍵…

PostgreSQL的系統視圖pg_stat_wal

PostgreSQL的系統視圖pg_stat_wal 在 PostgreSQL 數據庫中&#xff0c;pg_stat_wal 視圖提供了與 WAL&#xff08;Write-Ahead Logging&#xff09;日志有關的統計信息。WAL 是 PostgreSQL 用于確保數據一致性和持久性的重要機制。因此&#xff0c;監控和分析 WAL 活動對于數據…

ctfshow-web入門-命令執行(web71-web74)

目錄 1、web71 2、web72 3、web73 4、web74 1、web71 像上一題那樣掃描但是輸出全是問號 查看提示&#xff1a;我們可以結合 exit() 函數執行php代碼讓后面的匹配緩沖區不執行直接退出。 payload&#xff1a; cvar_export(scandir(/));exit(); 同理讀取 flag.txt cinclud…

文華財經博易大師盤立方多空波段止損畫線指標公式

TT:PERIOD7; EMA120:EMA(C,120); RSV:(CLOSE-LLV(LOW,9))/(HHV(HIGH,9)-LLV(LOW,9))*100; K:SMA(RSV,3,1); D:SMA(K,3,1); J:3*K-2*D; DRAWTEXT(TT&&J<0,L,多),VALIGN0; DRAWTEXT(TT&&J>100,H,空),VALIGN2; IF(TT,EMA(C,60),NULL),RGB(255,255,2…

JavaScript數組對象 , 正則對象 , String對象以及自定義對象介紹

1. Array數組對象 數組對象是使用單獨的變量名來存儲一系列的值。 1.1創建一個數組 創建一個數組&#xff0c;有三種方法。 【1】常規方式: let 數組名 new Array();【2】簡潔方式: 推薦使用 let 數組名 new Array(數值1,數值2,...);【3】字面:在js中創建數組使用中括號…

【ubuntu 】使用samba配置共享用戶home目錄和其他具體路徑

目錄 1 安裝samba 2 修改Samba配置文件 3 增加Rose用戶的samba帳號 4 重啟samba 5 測試 1 安裝samba 使用如下命令安裝samba&#xff1a; sudo apt-get updatesudo apt-get install samba openssh-server 2 修改Samba配置文件 sudo cp /etc/samba/smb.conf /etc/samba…

試用筆記之-收錢吧安卓版演示源代碼,收錢吧手機版感受

首先下載&#xff1a; https://download.csdn.net/download/tjsoft/89499105 安卓手機安裝 如果有收錢吧帳號輸入收錢吧帳號和密碼。 如果沒有收錢吧帳號點我的注冊 登錄收錢吧帳號后就可以把手機當成收錢吧POS機用了&#xff0c;還可以掃客服的付款碼哦 源代碼技術交流QQ:42…

Docker安裝MySQL5

Docker安裝MySQL5 前言 MySQL 是一個開源的關系型數據庫管理系統&#xff0c;廣泛用于各種 Web 應用程序的開發和生產環境中。MySQL 5 是 MySQL 數據庫的一個較早版本&#xff0c;雖然不再是最新版本&#xff0c;但仍然被一些項目所使用和支持。 在 Docker 中安裝 MySQL 5 可…