【开发】后端框架——Mybatis
前置知識:JDBC
學習視頻
Mybatis——一種ORM框架:將Java中的Bean映射為數據庫的記錄
- ORM:用于實現面向對象編程語言里不同類型系統的數據之間的轉換
Mybatis運行過程——工廠模式
#{} 與 ${} ——三點區別
動態Sql
分頁——兩種方法
緩存——查詢緩存順序
MyBatis
文檔
官方文檔
下載鏈接
sql相關
- sql引擎
- innoDB底層
- 索引
- 索引優化
概述
JDBC
JDBC驅動程序:JDBC(Java Database Connectivity, Java 數 據 庫 連 接)是 一 種可用于執行 SQL 語句的 Java API(Application Programming Interface)
-
實現了從 Java 程序內調用標準的 SQL命令 對數據庫進行查詢、插入、刪除和更新等操作, 并確保數據事務的正常進行
-
基本層次結構由 Java 程序、JDBC 驅動程序管理器、數據庫驅動程序和數據庫四部分組成
-
Java 程序依賴于 JDBC API,通過 DriverManager 來獲取驅動,并且針對不同的數據庫可以使用不同的驅動。
-
這是典型的橋接的設計模式,把 抽象 Abstraction 與 行為實現Implementation 分離 開來,從而可以保持各部分的獨立性以及應對他們的功能擴展。
JDBC步驟
public static void connectionTest(){Connection connection = null;Statement statement = null;ResultSet resultSet = null;try {// 1. 加載并注冊 MySQL 驅動器實例Class.forName("com.mysql.cj.jdbc.Driver").newInstance();// 2. 將Mysql驅動程序注冊到驅動管理程序中// 根據特定的數據庫連接URL,返回與此URL所匹配的數據庫驅動對象Driver driver = DriverManager.getDriver("jdbc:mysql://localhost:3306/[dbName]"); // 3. 傳入參數,比如說用戶名和密碼Properties props = new Properties();props.put("user", USER_NAME);props.put("password", PASSWORD);// 4. 使用數據庫驅動創建數據庫連接 Connectionconnection = driver.connect(URL, props);// 5. 從數據庫連接 connection 中獲得 Statement 對象statement = connection.createStatement();// 6. 執行 sql 語句,返回結果resultSet = statement.executeQuery("select * from activity");// 7. 處理結果,取出數據while(resultSet.next()){System.out.println(resultSet.getString(2));}.....}finally{// 8.關閉鏈接,釋放資源 按照JDBC的規范,使用完成后管理鏈接,// 釋放資源,釋放順序應該是: ResultSet ->Statement ->ConnectionresultSet.close();statement.close();connection.close();} }JDBC存在的問題
- 傳統的JDBC代碼復雜
- 實現步驟多
- 需要設計一種 將數據映射到數據庫的框架 來簡化JDBC的步驟
Mybatis特點
-
持久層框架
持久化:將程序中的數據從 瞬時狀態【內存:斷電即失】轉化為 持久狀態【數據庫jdbc,io文件持久化】的過程
持久層:完成數據持久化工作的代碼塊,層次間界限分明
-
定制化Sql
-
避免JDBC代碼,手動設置參數和獲取結果集
優點
- 簡單:兩個jar文件(mybatis.jar+mysql-connector.jar)+配置幾個sql映射文件(Mapper)
- 靈活:sql寫在xml里,統一管理(mybatis-config.xml)
- 解除sql與程序的耦合:通過提供Mapper層,將業務邏輯與數據訪問邏輯分離
- 提供映射標簽:JavaBean與數據庫字段的關系映射
- 提供xml標簽,支持編寫動態sql
Mybatis執行流程
通過簡單的 XML 或注解來配置和映射原始類型、接口和 Java POJO
1. 導包——Maven
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.6</version> </dependency>SqlSessionFactoryBuilder
一旦創建了 SqlSessionFactory ,就不再需要它了。
因此 SqlSessionFactoryBuilder 實例的最佳作用域是方法作用域
- 作用域:局部變量
SqlSessionFactory <=> 數據庫連接工廠
每個基于 MyBatis 的應用都是以一個 SqlSessionFactory 的實例為核心
構造方法:從xml中配置文件中構建SqlSessionFactory實例
SqlSessionFactory 一旦被創建就應該在應用的運行期間一直存在
- 作用域:應用作用域
最簡單的就是使用單例模式或者靜態單例模式。
SqlSession => JDBC:Connection對象
通過 SqlSessionFactory 獲得 SqlSession 的實例。
SqlSession 提供了在數據庫執行 SQL 命令所需的所有方法。
SqlSession的實例時線程不安全的,不能被共享
- 每次收到一個數據庫訪問請求,打開一個SqlSession,返回響應后,立即關閉
Mapper => JDBC:Statement
代理對象 執行具體業務
將接口與xml進行綁定
Mybatis示例程序
#mermaid-svg-GeLKu5fxhYgbgLBt {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GeLKu5fxhYgbgLBt .error-icon{fill:#552222;}#mermaid-svg-GeLKu5fxhYgbgLBt .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-GeLKu5fxhYgbgLBt .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-GeLKu5fxhYgbgLBt .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-GeLKu5fxhYgbgLBt .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-GeLKu5fxhYgbgLBt .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-GeLKu5fxhYgbgLBt .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-GeLKu5fxhYgbgLBt .marker{fill:#333333;stroke:#333333;}#mermaid-svg-GeLKu5fxhYgbgLBt .marker.cross{stroke:#333333;}#mermaid-svg-GeLKu5fxhYgbgLBt svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-GeLKu5fxhYgbgLBt .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-GeLKu5fxhYgbgLBt .cluster-label text{fill:#333;}#mermaid-svg-GeLKu5fxhYgbgLBt .cluster-label span{color:#333;}#mermaid-svg-GeLKu5fxhYgbgLBt .label text,#mermaid-svg-GeLKu5fxhYgbgLBt span{fill:#333;color:#333;}#mermaid-svg-GeLKu5fxhYgbgLBt .node rect,#mermaid-svg-GeLKu5fxhYgbgLBt .node circle,#mermaid-svg-GeLKu5fxhYgbgLBt .node ellipse,#mermaid-svg-GeLKu5fxhYgbgLBt .node polygon,#mermaid-svg-GeLKu5fxhYgbgLBt .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-GeLKu5fxhYgbgLBt .node .label{text-align:center;}#mermaid-svg-GeLKu5fxhYgbgLBt .node.clickable{cursor:pointer;}#mermaid-svg-GeLKu5fxhYgbgLBt .arrowheadPath{fill:#333333;}#mermaid-svg-GeLKu5fxhYgbgLBt .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-GeLKu5fxhYgbgLBt .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-GeLKu5fxhYgbgLBt .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-GeLKu5fxhYgbgLBt .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-GeLKu5fxhYgbgLBt .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-GeLKu5fxhYgbgLBt .cluster text{fill:#333;}#mermaid-svg-GeLKu5fxhYgbgLBt .cluster span{color:#333;}#mermaid-svg-GeLKu5fxhYgbgLBt div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-GeLKu5fxhYgbgLBt :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 搭建環境 編寫代碼 測試 導入mysql驅動,MyBatis包 核心配置文件mybatis-config.xml 編寫工具類提供SqlSession對象1. 搭建數據庫
create table user(id int(11) not null primary key,user_name varchar(30) default null,pwd varchar(30) default null )engine=InnoDB default charset=utf8;insert into user(id,user_name,pwd) values (1,'a','123456'), (2,'b','123456'), (3,'c','c123456');2. 新建項目
3. 刪除src,使項目成為父工程
4. maven導入依賴
<!-- 父工程 --> <groupId>com.kuang.MyBatis</groupId> <artifactId>MyBatis</artifactId> <version>1.0-SNAPSHOT</version><!-- 導入依賴 --> <dependencies><!-- 導入MySql驅動 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.16</version></dependency><!-- 導入MyBatis驅動 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.6</version></dependency><!-- 導入junit依賴 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency> </dependencies>5. 新建模塊
6. 獲取數據庫連接對象
a. 編寫核心配置文件——mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"> <!-- configuration的核心配置 --> <configuration><!-- 可配置多套環境,defaulte屬性選擇當前屬性 --><environments default="development"><environment id="development"><!-- 事務管理器 --><transactionManager type="JDBC"/><dataSource type="POOLED"><!-- 配置數據庫驅動器類型及連接參數 --><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf-8"/><property name="username" value="root"/><property name="password" value="2017002231"/></dataSource></environment></environments><!-- 每一個Mapper.xml都需要在MyBatis核心配置文件中注冊 --><mappers><mapper resource="com/kuang/dao/UserMapper.xml"/></mappers> </configuration>- useSSL:使用安全連接
- useUnicode:保證中文不亂碼
- characterEncoding:編碼格式
b. 編寫MyBatis工具類
新建dao包,utils包
public class MyBatisUtils {private static SqlSessionFactory sqlSessionFactory;// 1.獲取SqlSessionFactory對象static{try {//1. 將資源中的配置文件以流的形式讀入String resource = "mybatis-config.xml";InputStream configuration = Resources.getResourceAsStream(resource);//2. 通過工廠類構建器構建SqlSessionFactory類sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);} catch (IOException e) {e.printStackTrace();}}// 2.獲取SqlSession對象public static SqlSession getSqlSession(){return sqlSessionFactory.openSession();} }7. 編寫代碼
實體類
pojo的作用就是將從數據庫獲取到的數據封裝為一個一個的對象,讓java能夠更好的進行操作DO、VO
package com.kuang.pojo;public class User {private Integer id;private String user_name;private String pwd;public User(){}public User(Integer id, String user_name, String pwd) {this.id = id;this.user_name = user_name;this.pwd = pwd;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUser_name() {return user_name;}public void setUser_name(String user_name) {this.user_name = user_name;}public String getPwd() {return pwd;}public void setPwd(String pwd) {this.pwd = pwd;}@Overridepublic String toString() {return "User{" +"id=" + id +", user_name='" + user_name + '\'' +", pwd='" + pwd + '\'' +'}';} }Dao接口
public interface UserDao{List<User> getUserList(); }接口的實現
由 UserDaoImpl 轉化為 Mapper 配置文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!-- 綁定一個對應的Dao/Mapper接口 --> <mapper namespace="com.kuang.dao.UserDao"><!--id:方法名--><select id="getUserList" resultType="com.kuang.pojo.User">select *from mybatis.user;</select> </mapper>- namespace:相當于指定要實現的接口
- 將不同的語句隔離開來,同時也實現了接口綁定
- 全限定名(比如 “com.mypackage.MyMapper.selectAllThings)將被直接用于查找及使用
- 短名稱(比如 “selectAllThings”)如果全局唯一也可以作為一個單獨的引用。 如果不唯一,有兩個或兩個以上的相同名稱(比如 “com.foo.selectAllThings” 和 “com.bar.selectAllThings”),那么使用時就會產生“短名稱不唯一”的錯誤,這種情況下就必須使用全限定名。
- 將不同的語句隔離開來,同時也實現了接口綁定
- id:方法名
- resultType:返回單個
- resultMap:返回多個
8. 測試
新建 測試類
編寫測試代碼
package com.kuang.dao;import com.kuang.pojo.User; import com.kuang.utils.MyBatisUtils; import org.apache.ibatis.session.SqlSession; import org.junit.Test;import java.util.List;public class UserDaoTest {@Testpublic void test(){//1.獲取SqlSession對象SqlSession sqlSession = MyBatisUtils.getSqlSession();//2.執行Sql //通過反射機制,獲取方法區中UserMapper的Class類實例,這個實例中有UserMapper全部信息UserMapper userMapper = sqlSession.getMapper(UserMapper.class);List<User> userList = userMapper.getUserList();/*//方式二:強制類型轉換,不安全List<User> userList = sqlSession.selectOne("com.kuang.UserDao.getUserList");*/for (User user:userList){System.out.println(user);}//關閉sqlSessionsqlSession.close();} }遇到的各種錯誤
org.apache.ibatis.io不存在——IDEA2020.1
class not found:ClassTest
執行UserDaoTest的test方法之前,要先 mvn test-compile 生成 test classes才可被部署并發現
Type interface com.kuang.dao.UserDao is not known to the MapperRegistry
<!-- 每一個Mapper.xml都需要在MyBatis核心配置文件中注冊 --> <mappers><mapper resource="com/kuang/dao/UserMapper.xml"/> </mappers>Could not find resource com/kuang/dao/UserMapper.xml
Maven約定大于配置,自己寫的配置文件默認不會被導出或生效
Maven默認的資源(自己配置的xml)位置在resources目錄下,當前項目的xml位于java目錄下,所以找不到
<!-- build中配置resources,防止資源導出失敗問題 --> <build><resources><resource><!-- 使得directory目錄下的資源可以被導出 --><directory>src/main/java</directory><!-- 設置可被識別通過的文件類型 --><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>true</filtering></resource><resource><!-- 使得directory目錄下的資源可以被導出 --><directory>src/main/resources</directory><!-- 設置可被識別通過的文件類型 --><includes><include>**/*.propertes</include><include>**/*.xml</include></includes><filtering>true</filtering></resource></resources> </build>終于成功
增刪改查CRUD
CUD 需要通過connection對象以Transition(事務)的形式提交
select
選擇,查詢語句:
- id:方法名
- resultType:Sql語句執行的返回值
- parameterType:參數類型
通過id獲取用戶
模糊查詢
Java代碼執行時,傳遞通配符 %%
在sql語句拼接中使用通配符
- 存在sql注入的風險
insert
并沒有新增
更新
刪除
參數傳遞&Map
單個參數傳遞方式
- 只有一個 基本數據類型 ,可省略
- 實體類對象作為參數,sql語句中的參數取對象的屬性
- Map作為參數,sql語句中參數取Map的屬性
多個參數的傳遞
使用Map的情況
當字段過多時,考慮使用 Map,可以自定義需要傳遞的參數
- 若使用實體類作為參數傳遞,當字段過多時,一個實體類的每個屬性都必須設置值
Plugin——通用Mapper
核心配置——mybatis-config.xml
configuration(配置)
- properties(屬性)
- settings(設置)
- typeAliases(類型別名)
- environments(環境配置)
- environment(環境變量)
- transactionManager(事務管理器)
- dataSource(數據源)
- environment(環境變量)
- mappers(映射器)
屬性(properties)
通過Properties引用配置文件
- 優先使用外部配置文件
通過 <properties/> 聲明引用屬性
<!-- properties引用屬性變量 --> <properties resource="db.properties"/>使用屬性
設置Settings
| cacheEnabled | 是否緩存Globally enables or disables any caches configured in any mapper under this configuration. | true | false | true |
| lazyLoadingEnabled | 懶加載,提高開發效率When enabled, all relations will be lazily loaded. This value can be superseded for a specific relation by using the fetchType attribute on it. | true | false | false |
| mapUnderscoreToCamelCase | Enables automatic mapping from classic database column names A_COLUMN to camel case classic Java property names aColumn. | true | false | false |
| logImpl | MyBatis的日志實現方式Specifies which logging implementation MyBatis should use. | LOG4J|STDOUT_LOGGING | No Set |
日志實現——logImpl
- SLF4J
- LOG4J | LOG4J2
- JDK_LOGGING
- COMMONS_LOGGING
- STDOUT_LOGGING
- NO_LOGGING
STDOUT_LOGGING
<!--設置日志實現方式--> <settings><setting name="logImpl" value="STDOUT_LOGGING"/> </settings>- 由日志可見,MyBatis底層是基于JDBC實現的
LOG4J
- 控制日志信息輸送的目的地是控制臺、文件、GUI組件,甚至是套接口服務器、NT的事件記錄器、UNIX Syslog守護進程等
- 控制每一條日志的輸出格式
導入 LOG4J 包
<dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version> </dependency>配置log4j.properties資源
程序中使用log4j
導包
import org.apache.log4j.Logger;設置變量
static Logger logger = Logger.getLogger(UserMapperTest.class);Logger.getLogger(className):將日志對象與目標對象綁定
使用
log級別
- info([信息])
- debug([信息])
- error([信息])
環境配置 enviroments
MyBatis 可以配置成適應多種環境,但每個 SqlSessionFactory 實例只能選擇一種環境
如果你想連接兩個數據庫,就需要創建兩個 SqlSessionFactory 實例,每個數據庫對應一個。
- 默認使用的環境 ID(比如:default=“development”)。
- 每個 environment 元素定義的環境 ID(比如:id=“development”)。
- 事務管理器的配置(比如:type=“JDBC”)。
- 數據源的配置(比如:type=“POOLED”)。
事務管理器(transactionManager)
兩種類型的事務管理器(也就是 type=“[JDBC|MANAGED]”)
- 使用 Spring + MyBatis,則沒有必要配置事務管理器,因為 Spring 模塊會使用自帶的管理器來覆蓋前面的配置。
數據源(dataSource)
連接數據庫:
- jdbc
- dbcp
- c3p0
- druid
三種數據源類型
UNPOOLED——用完即銷毀
-
無連接池,每次請求時打開和關閉連接
-
浪費資源
POOLED——用完即回收
JNDI
類型別名typeAliases
用于減少完全限定名的冗余給Bean取別名
配置方式
實體類較少,可逐一指定
<!-- mybatis-config.xml --> <typeAliases><typeAlias type="com.kuang.pojo.User" alias="User"/> </typeAliases><!-- UserMapper.xml --> <mapper namespace="com.kuang.mapper.UserMapper"><!--id:方法名--><select id="getUserList" resultType="User">select *from mybatis.user;</select> </mapper>You can also specify a package where MyBatis will search for all beans.包中實體類的別名為 lowercase(類名的首字母)
<!-- mybatis-config.xml --> <typeAliases><package name="com.kuang.pojo" /> </typeAliases><!-- UserMapper.xml --> <mapper namespace="com.kuang.mapper.UserMapper"><!--id:方法名--><select id="getUserList" resultType="user">select *from mybatis.user;</select> </mapper>If the @Alias annotation is found its value will be used as an alias. 優先級 :注解別名>配置別名
MyBatis默認配置的別名
| _普通數據類型 | 普通數據類型(int,short,long,byte,double,float,boolean) |
| 小寫首字母(數據類型名) | 首字母大寫的數據類型(基本數據類型 + Date,Object,Map,HashMap,List,ArrayList,Collection,Iterator) |
| Integer,int | BigDecimal |
| decimal,bigdecimal | Integer |
插件plugins
-
mybatis-generator-core
-
mybatis-plus
-
通用mapper
映射器mapper
接口實現(mapper.xml)必須在configuration中注冊才可被發現
第一種方式:資源路徑【推薦】
<!-- Using classpath relative resources --> <mappers><mapper resource="org/mybatis/builder/AuthorMapper.xml"/><mapper resource="org/mybatis/builder/BlogMapper.xml"/><mapper resource="org/mybatis/builder/PostMapper.xml"/> </mappers>第二種方式:類名
<!-- Using mapper interface classes --> <mappers><mapper class="org.mybatis.builder.AuthorMapper"/><mapper class="org.mybatis.builder.BlogMapper"/><mapper class="org.mybatis.builder.PostMapper"/> </mappers>第三種方式:包內全導入
<!-- Register all interfaces in a package as mappers --> <mappers><package name="org.mybatis.builder"/> </mappers>第二、三種方式的問題
- 接口和Mapper配置文件必須同名
- 接口和Mapper配置資源必須在同一包下
Mapper.xml(Dao實現類)
- resultMap – The most complicated and powerful element that describes how to load your objects from the database result sets.
- javaType:class——POJO| ArrayList
- ofType:list 或 set 中的POJO
- insert – A mapped INSERT statement.
- update – A mapped UPDATE statement.
- delete – A mapped DELETE statement.
- select – A mapped SELECT statement.
解決屬性名和字段名不一致問題——resultMap
簡單的例子
public class User {private Integer id;private String user_name;private String password; }解決思路:起別名
在 sql 中,用 as 關鍵字,可以給某一字段起別名
select *from user where id=#{id}selectid as id,user_name as user_name,pwd as password from user where id=#{id};在 Mybatis 中,使用 ResultMap 做結果映射,只需要將有差異的屬性與字段映射即可
- property:POJO中的屬性
- column:數據庫中的字段
復雜查詢
實體間的復雜關系&環境搭建
關聯association:多對一
- 查到的是結果是滿足某種關系的個體集
集合collection:一對多
- 返回的結果是一個個體,其中某個屬性是個體集
Association
聯表查詢
select s.id as sid,s.user_name as sname,t.id as tid,t.user_name as tname from student as s,teacher as t where s.tid=t.id接口
List<Student> getStudent2();接口實現
<!--BFS:聯表查詢,處理結果--> <select id="getStudent2" resultMap="StudentTeacher2">select s.id as sid,s.user_name as sname,t.id as tid,t.user_name as tnamefrom student as s,teacher as twhere s.tid=t.id </select><resultMap id="StudentTeacher2" type="student"><result property="id" column="sid"/><result property="user_name" column="sname"/><association property="teacher" javaType="teacher"><result property="id" column="tid"/><result property="user_name" column="tname"/></association> </resultMap>測試
嵌套查詢
select * from student as s where s.tid in (select t.id from teacher as t);定義接口
//查詢學生對應的老師信息 List<Student> getStudent();實現接口
<!--思路:DFS 查詢嵌套,1. 查詢所有學生信息2. 根據查出來學生的tid,查找對應的teacher --> <select id="getStudent" resultMap="StudentTeacher">select *from mybatis.student; </select><resultMap id="StudentTeacher" type="student"><!--簡單屬性用 <result property="" column=""/>映射即可--><!--復雜屬性多對*————關聯association一對*————集合collection--><association property="teacher" column="tid" javaType="teacher" select="getTeacher"/> </resultMap><select id="getTeacher" resultType="teacher">select *from mybatis.teacher where id=#{tid}; </select>Collection
@Data public class Student {private Integer id;private String user_name;private Integer tid; }@Data public class Teacher {private Integer id;private String user_name;//一個老師擁有多個學生private List<Student> students; }實現根據teacher.id查找該老師對應的所有學生
聯表查詢
select t.id tid,t.user_name tname, s.id sid,s.user_name sname from teacher t,student s where t.id=s.tid and t.id=1;定義接口
//獲取某個老師下所有的學生信息 Teacher getTeacherById(@Param("tid") Integer id);實現接口
<select id="getTeacherById" resultMap="StudentTeacher">select t.id tid,t.user_name tname, s.id sid,s.user_name snamefrom teacher t,student swhere t.id=s.tid and t.id=#{tid}; </select> <resultMap id="StudentTeacher" type="Teacher"><result property="id" column="tid"/><result property="user_name" column="tname"/><!-- 集合中的泛型用ofType指定 --><collection property="students" ofType="student"><result property="id" column="sid"/><result property="user_name" column="sname"/><result property="tid" column="tid"/></collection> </resultMap>測試
嵌套查詢
select tid,(select user_name from teacher where id=1) tname,id sid,user_name sname from student s where tid=1;定義接口
Teacher getTeacherById2(@Param("tid") Integer id);實現接口
<select id="getTeacherById2" resultMap="StudentTeacher2">select *from mybatis.teacher where id=#{tid} </select> <resultMap id="StudentTeacher2" type="teacher"><collection property="students" column="id" javaType="ArrayList" ofType="student" select="GetStudentByTid" /> </resultMap> <select id="GetStudentByTid" resultType="student">select *from mybatis.studentwhere tid=#{tid}; </select>測試
動態sql
根據不同的條件生成不同的sql語句
搭建環境
create table blog(id varchar(50) not null comment '博客id',title varchar(100) not null comment '博客標題',author varchar(30) not null comment '博客作者',create_time datetime not null comment '創建時間',views int(30) not null comment '瀏覽量' )engine=InnoDB default charset=utf8; @Data public class Blog {private String id;private String title;private String author;private Date createTime;private Integer views; } @SuppressWarnings("all")//抑制所有警告 public class TestBlog {@Testpublic void test(){SqlSession sqlSession = MyBatisUtils.getSqlSession();BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);Blog blog = new Blog();blog.setId(IDUtil.getId());blog.setAuthor("kuang");blog.setTitle("MyBatis如此簡單!");blog.setCreateTime(new Date());blog.setViews(9999);mapper.insert(blog);blog.setId(IDUtil.getId());blog.setTitle("Java如此簡單!");blog.setViews(9999);mapper.insert(blog);blog.setId(IDUtil.getId());blog.setTitle("Spring如此簡單!");mapper.insert(blog);blog.setId(IDUtil.getId());blog.setTitle("微服務如此簡單!");mapper.insert(blog);sqlSession.close();} }查詢
IF
接口
//查詢blog信息List<Blog> queryBlogIF(Map map);接口實現
<select id="queryBlogIF" resultType="blog" parameterType="map">select *from mybatis.blog where 1=1<if test="title!= null">and titie=#{title}</if><if test="author!= null">and author = #{author}</if> </select>測試
where優化
<select id="queryBlogIF" resultType="blog" parameterType="map">select *from mybatis.blog<where><if test="title!= null">title=#{title}</if><if test="author!= null">and author = #{author}</if></where> </select>- The where element knows to only insert “WHERE” if there is any content returned by the containing tags. (滿足條件插入)
- Furthermore, if that content begins with “AND” or “OR”, it knows to strip it off.(保證第一個 where前沒有邏輯判斷)
choose-when-otherwise&where
switch-case-default | if-else if - else
定義接口
List<Blog> queryBlogIF1(Map map);實現接口
<select id="queryBlogIF1" parameterType="map" resultType="blog">select *from mybatis.blog<where><choose><when test="id!=null">id=#{id}</when><when test="title != null">title=#{title}</when><when test="author != null">author=#{author}</when><otherwise>views>1000</otherwise></choose></where> </select>測試
更新
set
- The set element can be used to dynamically include columns to update, and leave out others.(選目標字段,刪除無關字符)
- the set element will dynamically prepend the SET keyword,(前置)
- and also eliminate any extraneous commas that might trail the value assignments after the conditions are applied.(刪逗號)
定義接口
//更新信息 int updateBlog(Map map);實現接口
<update id="updateBlog" parameterType="map">update mybatis.blog<set><if test="title!=null">title=#{title},</if><if test="author!=null">author=#{author},</if><if test="views!=null">views=#{views},</if>create_time =#{createTime}</set>where id=#{id} </update>測試
trim替換
前綴后綴都是 prefix,XXOverrides決定替換的位置
<select id="queryBlogIFByTrim" resultType="blog" parameterType="map">select *from mybatis.blog<trim prefix="where" prefixOverrides="and |or "><if test="title!= null">title=#{title}</if><if test="author!= null">and author = #{author}</if></trim> </select>- The prefixOverrides attribute takes a pipe delimited list of text to override, where whitespace is relevant.前綴Overrides 屬性采用管道分隔文本列表來重寫,其中空白是相關的。(最好寫上,替換后可能會出問題)
- The result is the removal of anything specified in the prefixOverrides attribute
- and the insertion of anything in the prefix attribute
sql片段
公共部分抽取出來,方便復用
- <sql id=""></sql> 抽取
- <include refid="" /> 引用
- 基于單表查詢
- 不要存在 <where> 標簽
foreach
sql in 的動態范圍查詢
select *from user where 1=1 and (id=1 or id=2 or id=3);<foreach item="item" collection="ids" open="(" separator=" or " close=")">#{item} </foreach>- open:開始符
- separator:分隔符
- close:結束符
- item:項
- colloetion:遍歷集合
定義接口
List<Blog> queryBlogIn(Map map);實現接口
<select id="queryBlogIn" parameterType="map" resultType="blog">select *from mybatis.blog<where><foreach collection="ids" item="id" open="(" separator="or" close=")">id=#{id}</foreach></where> </select>測試
分頁
limit實現分頁
sql語句
select *from [table_name] limit [offset],[limit];# [offset]缺省,默認從0開始,到[end] select *from [table_name] limit [end];MyBatis方式
接口
//分頁查詢用戶信息 List<User> getUserWithLimit(Map<String,Integer> map);接口配置
<select id="getUserWithLimit" resultMap="UserMap" resultType="user" parameterType="map">select *from mybatis.user limit #{offset},#{limit}; </select>測試
@Test public void testGetUserWithLimit(){SqlSession sqlSession = MyBatisUtils.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);Map<String, Integer> map = new HashMap<String, Integer>();map.put("offset",1);map.put("limit",2);List<User> userList = mapper.getUserWithLimit(map);for (User user : userList) {System.out.println(user);}sqlSession.close(); }RowBounds實現分頁[不建議使用]
不在sql進行分頁,通過sqlSession對象實現分頁——RowBounds
接口
List<User> getUserWithLimit2();配置Mapper
<select id="getUserWithLimit2" resultMap="UserMap" resultType="user">select *from mybatis.user; </select>測試
@Test public void testGetUserWithLimit2(){SqlSession sqlSession = MyBatisUtils.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);RowBounds rowbounds = new RowBounds(1,2);List<User> userList = sqlSession.selectList("com.kuang.mapper.UserMapper.getUserWithLimit2",null,rowbounds);for (User user : userList) {System.out.println(user);}sqlSession.close(); }插件——pageHelper
緩存
簡介
問題:連接數據庫消耗資源
解決:一次查詢,保存到高速存儲——> 內存
緩存:
- 放在內存中的臨時數據
- 將 經常查詢且不常改變 的數據存放在緩存,直接從服務器內存取比從服務器磁盤IO速度快,提高查詢效率,解決高并發系統的性能問題
使用緩存,減少與數據庫交互次數,減少系統開銷,提高系統效率
#mermaid-svg-5j8hTzdinpGfqAUy {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-5j8hTzdinpGfqAUy .error-icon{fill:#552222;}#mermaid-svg-5j8hTzdinpGfqAUy .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-5j8hTzdinpGfqAUy .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-5j8hTzdinpGfqAUy .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-5j8hTzdinpGfqAUy .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-5j8hTzdinpGfqAUy .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-5j8hTzdinpGfqAUy .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-5j8hTzdinpGfqAUy .marker{fill:#333333;stroke:#333333;}#mermaid-svg-5j8hTzdinpGfqAUy .marker.cross{stroke:#333333;}#mermaid-svg-5j8hTzdinpGfqAUy svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-5j8hTzdinpGfqAUy .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-5j8hTzdinpGfqAUy .cluster-label text{fill:#333;}#mermaid-svg-5j8hTzdinpGfqAUy .cluster-label span{color:#333;}#mermaid-svg-5j8hTzdinpGfqAUy .label text,#mermaid-svg-5j8hTzdinpGfqAUy span{fill:#333;color:#333;}#mermaid-svg-5j8hTzdinpGfqAUy .node rect,#mermaid-svg-5j8hTzdinpGfqAUy .node circle,#mermaid-svg-5j8hTzdinpGfqAUy .node ellipse,#mermaid-svg-5j8hTzdinpGfqAUy .node polygon,#mermaid-svg-5j8hTzdinpGfqAUy .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-5j8hTzdinpGfqAUy .node .label{text-align:center;}#mermaid-svg-5j8hTzdinpGfqAUy .node.clickable{cursor:pointer;}#mermaid-svg-5j8hTzdinpGfqAUy .arrowheadPath{fill:#333333;}#mermaid-svg-5j8hTzdinpGfqAUy .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-5j8hTzdinpGfqAUy .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-5j8hTzdinpGfqAUy .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-5j8hTzdinpGfqAUy .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-5j8hTzdinpGfqAUy .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-5j8hTzdinpGfqAUy .cluster text{fill:#333;}#mermaid-svg-5j8hTzdinpGfqAUy .cluster span{color:#333;}#mermaid-svg-5j8hTzdinpGfqAUy div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-5j8hTzdinpGfqAUy :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 緩存merCached緩存服務器 讀寫分離,主從復制MyBatis緩存
系統默認定義兩級緩存:一級緩存和二級緩存
- 一級緩存:SqlSession級,本地緩存
- 二級緩存:手動開啟和配置,namespace級緩存
- MyBatis自定義緩存接口Cache,通過實現接口自定義二級緩存
一級緩存——Map
一級緩存默認開啟,在一次SESSION期間有效
開啟日志
測試一個Session中查詢兩次相同記錄
@Test public void test(){SqlSession sqlSession = MyBatisUtils.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);User user1 = mapper.getUserById(1);System.out.println(user1);System.out.println("====================");User user2 = mapper.getUserById(1);System.out.println(user2);System.out.println(user1==user2);sqlSession.close(); }查看日志輸出
兩次查找一次查表
兩次結果引用同一對象
緩存失效
-
R不同的東西
-
CUD必定刷新緩存
-
不同的Mapper
-
手動清理緩存
二級緩存
工作機制:
一個Session期間的數據會被放到一級緩存,當Session關閉或提交,對應的一級緩存中的數據被保存到二級緩存中
- 新的Session查詢信息,從二級緩存中獲取內容
- 不同的mapper查出的數據會放到自己對應的緩存中
mybatis-config.xml 開啟二級緩存
<!--開啟二級緩存--> <setting name="cacheEnabled" value="true"/>配置mapper.xml
<!--在當前mapper中使用二級緩存--> <cacheeviction="FIFO"flushInterval="60000"size="512"readOnly="true"/>- mapper.xml中的所有 select 語句的結果將會被緩存。
- mapper.xml中的所有 insert、update 和 delete 語句會刷新緩存。
- eviction:替換策略
- LRU:默認
- FIFO
- flushInterval:刷新間隔
- 以毫秒為單位
- 不設置,也就是沒有刷新間隔,緩存僅僅會在調用語句時刷新
- size:引用數目
- 默認值是 1024
- readOnly:只讀
- 只讀的緩存會給所有調用者返回緩存對象的相同實例。 因此這些對象不能被修改
- 可讀寫的緩存會(通過序列化)返回緩存對象的拷貝。 速度上會慢一些,但是更安全,因此默認值是 false
測試
問題
- 將實體類序列化,否則保錯
緩存原理
查找順序:
- 由Cache Hit Ratio的計算,可知cache機制是先查二級緩存,再數據庫
自定義緩存——Ehcache
開源Java分布式緩存
<dependency><groupId>org.mybatis.caches</groupId><artifactId>mybatis-ehcache</artifactId><version>1.1.0</version> </dependency> <!--mapper.xml--> <cache type="com.domain.something.MyCustomCache"/> public interface Cache {String getId();int getSize();void putObject(Object key, Object value);Object getObject(Object key);boolean hasKey(Object key);Object removeObject(Object key);void clear(); }注解開發
面向接口編程
目的:解耦
接口的理解
- 定義 與 實現 分離
- 接口反映系統設計人員對系統的抽象理解
- 接口分類:
- 一個個體的抽象——抽象體(abstract class)
- 一個個體的某一方面的抽象——抽象面(Interface)
- 接口設計更多體現對系統整體的架構
使用注解開發
本質:反射機制
底層:動態代理
Java Annotations are both limited and messier for more complicated statements.
注解在接口上實現
public interface UserMapper {@Select("select *from user")List<User> getUsers(); }綁定接口
<!--mybatis-config.xml--> <!-- 綁定接口 --> <mappers><mapper class="com.kuang.mapper.UserMapper"/> </mappers>測試
@Test public void test(){SqlSession sqlSession = MyBatisUtils.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);List<User> users = mapper.getUsers();for (User user : users) {System.out.println(user);}sqlSession.close(); }參數
當有多個參數,基本數據類型或String的參數前加注解 @param關聯參數
引用類型不需要加
sql中使用的是@Param()中設定的屬性名
#{} 與 ${} 的區別
- ${}是字符串替換,,Mybatis 在處理${}時,就是把他替換成變量的值
- #{}是預編譯處理,會將 #{}替換為?號,調用 PreparedStatement 的 set 方法來賦值;
- 使用#{}可以有效的防止 SQL 注入,提高系統安全性
自動提交事務
public class MyBatisUtils{public static SqlSession getSqlSession(){return sqlSessionFactory.openSession(true);} }CRUD
Create
//UserMapper.java public interface UserMapper{@Insert("insert into user(id,user_name,pwd) values(#{id},#{user_name},#{pwd})") int insertUser(User user); }Update
//UserMapper.java public interface UserMapper{@Update("update user set user_name=#{user_name},pwd=#{pwd} where id=#{id}")int updateUser(User user); }POJO方法的簡化——Lombok
IDEA中安裝插件
項目中導入依賴
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version><scope>provided</scope> </dependency>使用注解簡化
@Getter and @Setter @ToString @EqualsAndHashCode @AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor @Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger, @CustomLog @Data-
@Data,@AllArgsConstructor,@NoArgsConstructor
MybatisPlus
簡介
在MyBatis基礎上,只做增強不做改變,為簡化開發、提高效率而生
- 無侵入
- 損耗小:啟動即會自動注入基本 CURD,性能基本無損耗,直接面向對象操作
- CRUD:內置通用 Mapper、通用 Service
- 支持主鍵自動生成
- 支持 XML 熱加載 :Mapper 對應的 XML 支持熱加載,對于簡單的 CRUD 操作,甚至可以無 XML 啟動
- 支持 ActiveRecord 模式
- 支持自定義全局通用操作:支持全局通用方法注入
- 內置代碼生成器 :采用代碼或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 層代碼,支持模板引擎
- 內置分頁插件 、性能分析插件
- 全局攔截(提供全表 delete 、 update 操作智能分析阻斷,也可自定義攔截規則,預防誤操作)
- 內置 Sql 注入剝離器:支持 Sql 注入剝離,有效預防 Sql 注入攻擊
MtbatisPlus架構
通過簡單語句,生成SQL語句,交給MyBatis執行
使用
1. 建庫建表
創建數據庫 haoke
use haoke;CREATE TABLE `user` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',`name` varchar(30) DEFAULT NULL COMMENT '姓名',`age` int(11) DEFAULT NULL COMMENT '年齡',`email` varchar(50) DEFAULT NULL COMMENT '郵箱',PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- 插入數據 INSERT INTO `user` (`id`, `name`, `age`, `email`) VALUES ('1', 'Jone', '18','test1@baomidou.com'); INSERT INTO `user` (`id`, `name`, `age`, `email`) VALUES ('2', 'Jack', '20','test2@baomidou.com'); INSERT INTO `user` (`id`, `name`, `age`, `email`) VALUES ('3', 'Tom', '28','test3@baomidou.com'); INSERT INTO `user` (`id`, `name`, `age`, `email`) VALUES ('4', 'Sandy', '21','test4@baomidou.com'); INSERT INTO `user` (`id`, `name`, `age`, `email`) VALUES ('5', 'Billie', '24','test5@baomidou.com');
2. 創建工程及導入依賴
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.4.3</version> </parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--mybatis-plus的springboot支持--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.2</version></dependency><!--mysql驅動--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.16</version></dependency> </dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins> </build>3. 編寫application.properties文件
spring.application.name = mybatis-plus spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://8.140.130.91:3306/haoke?characterEncoding=utf8&useSSL=false&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=root4. 創建User對象
package com.mybatisplus.pojo;public class User {private Long id;private String name;private Integer age;private String email;public User() {}public User(Long id, String name, Integer age, String email) {this.id = id;this.name = name;this.age = age;this.email = email;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;} }5. 編寫UserMapper
package com.mybatisplus.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;public interface UserMapper extends BaseMapper<User> {}6. 編寫SpringBoot啟動類
package com.mybatisplus;import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;@MapperScan("com.mybatisplus.mapper") //設置mapper接口的掃描包 @SpringBootApplication public class Myapplication {public static void main(String[] args) {SpringApplication.run(Myapplication.class,args);} }7. 編寫SpringBoot啟動類
package com.mybatisplus;import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;@MapperScan("com.mybatisplus.mapper") //設置mapper接口的掃描包 @SpringBootApplication public class Myapplication {public static void main(String[] args) {SpringApplication.run(Myapplication.class,args);} }8. 編寫單元測試用例
package com.mybatisplus;import com.mybatisplus.mapper.UserMapper; import com.mybatisplus.pojo.User; import org.junit.jupiter.api.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest;import java.util.List;@SpringBootTest public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void test(){System.out.println("-------selectAll method test-------");List<User> users = userMapper.selectList(null);for (User user : users) {System.out.println(user);}} }通用Mapper
在MybatisPlus中,BaseMapper中定義了一些常用的CRUD方法,當我們自定義的Mapper接口繼承BaseMapper后即可擁有了這些方法 【這些方法僅適合單表操作】
/*** Mapper 繼承該接口后,無需編寫 mapper.xml 文件,即可獲得CRUD功能*/ public interface BaseMapper<T> extends Mapper<T> {/*** 插入一條記錄** @param entity 實體對象*/int insert(T entity);/*** 根據 ID 刪除** @param id 主鍵ID*/int deleteById(Serializable id);/*** 根據 columnMap 條件,刪除記錄** @param columnMap 表字段 map 對象*/int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);/*** 根據 entity 條件,刪除記錄** @param queryWrapper 實體對象封裝操作類(可以為 null,里面的 entity 用于生成 where 語句)*/int delete(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);/*** 刪除(根據ID 批量刪除)** @param idList 主鍵ID列表(不能為 null 以及 empty)*/int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);/*** 根據 ID 修改** @param entity 實體對象*/int updateById(@Param(Constants.ENTITY) T entity);/*** 根據 whereEntity 條件,更新記錄** @param entity 實體對象 (set 條件值,可以為 null)* @param updateWrapper 實體對象封裝操作類(可以為 null,里面的 entity 用于生成 where 語句)*/int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);/*** 根據 ID 查詢** @param id 主鍵ID*/T selectById(Serializable id);/*** 查詢(根據ID 批量查詢)** @param idList 主鍵ID列表(不能為 null 以及 empty)*/List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);/*** 查詢(根據 columnMap 條件)** @param columnMap 表字段 map 對象*/List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);/*** 根據 entity 條件,查詢一條記錄** @param queryWrapper 實體對象封裝操作類(可以為 null)*/T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);/*** 根據 Wrapper 條件,查詢總記錄數** @param queryWrapper 實體對象封裝操作類(可以為 null)*/Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);/*** 根據 entity 條件,查詢全部記錄** @param queryWrapper 實體對象封裝操作類(可以為 null)*/List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);/*** 根據 Wrapper 條件,查詢全部記錄** @param queryWrapper 實體對象封裝操作類(可以為 null)*/List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);/*** 根據 Wrapper 條件,查詢全部記錄* <p>注意: 只返回第一個字段的值</p>** @param queryWrapper 實體對象封裝操作類(可以為 null)*/List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);/*** 根據 entity 條件,查詢全部記錄(并翻頁)** @param page 分頁查詢條件(可以為 RowBounds.DEFAULT)* @param queryWrapper 實體對象封裝操作類(可以為 null)*/<E extends IPage<T>> E selectPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);/*** 根據 Wrapper 條件,查詢全部記錄(并翻頁)** @param page 分頁查詢條件* @param queryWrapper 實體對象封裝操作類*/<E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper); }通過id查詢——selectById
@Test public void testSelectById(){System.out.println("通過Id查詢");User user = userMapper.selectById(3L);//數據類型為Long,id為3System.out.println(user); }模糊查詢——like
條件查詢
https://mp.baomidou.com/guide/wrapper.html#abstractwrapper
插入數據
@Test public void testSave(){User user = new User();user.setAge(25);user.setEmail("zhangsan@qq.com");user.setName("zhangsan");int count = userMapper.insert(user);System.out.println("新增數據成功! count=>"+count); }id自增問題
所以自增問題出現在java參數傳遞中
public class User {@TableId(value = "ID", type = IdType.AUTO)private Long id;private String name;private Integer age;private String email; }
刪除數據
修改數據
根據id修改,只修改指定的字段
分頁查詢
/*** 分頁插件*/ @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 設置請求的頁面大于最大頁后操作, true調回到首頁,false 繼續請求 默認false// paginationInterceptor.setOverflow(false);// 設置最大單頁限制數量,默認 500 條,-1 不受限制// paginationInterceptor.setLimit(500);PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();paginationInnerInterceptor.setDbType(DbType.MYSQL);interceptor.addInnerInterceptor(paginationInnerInterceptor);return interceptor; }配置
使用MyBatis原生配置文件
# 指定全局配置文件 mybatis-plus.config-location = classpath:mybatis-config.xml # 指定mapper.xml文件 mybatis-plus.mapper-locations = classpath*:mybatis/*.xml若指定配置文件,無需配置環境,只需要
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"> <!-- configuration的核心配置 --> <configuration><!-- 每一個Mapper.xml都需要在MyBatis核心配置文件中注冊 --> </configuration>https://mp.baomidou.com/guide/config.html#%E5%9F%BA%E6%9C%AC%E9%85%8D%E7%BD%AE
Lombok
- @Data:注解在類上;提供類所有屬性的 getting 和 setting 方法,此外還提供了equals、canEqual、hashCode、toString 方法
- @Setter:注解在屬性上;為屬性提供 setting 方法
- @Getter:注解在屬性上;為屬性提供 getting 方法
- @Slf4j:注解在類上;為類提供一個 屬性名為log 的 slf4j日志對象
- @NoArgsConstructor:注解在類上;為類提供一個無參的構造方法
- @AllArgsConstructor :注解在類上;為類提供一個全參的構造方法
- @Builder :使用Builder模式構建對象
總結
以上是生活随笔為你收集整理的【开发】后端框架——Mybatis的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ego-motion 自我运动
- 下一篇: 安全港到隐私护盾!美欧个人数据跨境流动2