2022最新最全MyBatis(简单全面,一发入魂,内容超详细)
目錄
一、MyBatis簡介
1、MyBatis歷史
2、MyBatis特性
3、MyBatis下載
4、和其它持久化層技術對比
JDBC
Hibernate 和 JPA
MyBatis
二、搭建MyBatis
1、開發環境
2、創建maven工程
a>打包方式:jar
b>引入依賴
3、創建MyBatis的核心配置文件
4、創建mapper接口
5、創建MyBatis的映射文件
6、通過junit測試功能
7、加入log4j日志功能
a>加入依賴
b>加入log4j的配置文件
三、核心配置文件詳解
四、MyBatis的增刪改查
五、MyBatis獲取參數值的兩種方式(重點)
1、單個字面量類型的參數
2、多個字面量類型的參數
3、map集合類型的參數
4、實體類類型的參數
5、使用@Param標識參數
?六、MyBatis的各種查詢功能
1、查詢一個實體類對象
2、查詢一個list集合
3、查詢單個數據
4、查詢一條數據為map集合
5、查詢多條數據為map集合
七、特殊SQL的執行
1、模糊查詢
2、批量刪除
3、動態設置表名
4、添加功能獲取自增的主鍵
八、自定義映射resultMap
1、resultMap處理字段和屬性的映射關系
2、多對一映射處理
a>級聯方式處理映射關系
?b>使用association處理映射關系
3、一對多映射處理
a>collection
b>分步查詢
九、動態SQL
1、if
2、where
3、trim
4、choose、when、otherwise
5、foreach
6、SQL片段
十、MyBatis的緩存
1、MyBatis的一級緩存
2、MyBatis的二級緩存
3、二級緩存的相關配置
4、MyBatis緩存查詢的順序
5、整合第三方緩存EHCache
a>添加依賴
b>各jar包功能
c>創建EHCache的配置文件ehcache.xml
d>設置二級緩存的類型
e>加入logback日志
f>EHCache配置文件說明
十一、MyBatis的逆向工程
1、創建逆向工程的步驟
a>添加依賴和插件
b>創建MyBatis的核心配置文件
c>創建逆向工程的配置文件
d>執行MBG插件的generate目標
2、QBC查詢
十二、分頁插件
1、分頁插件使用步驟
a>添加依賴
b>配置分頁插件
2、分頁插件的使用
一、MyBatis簡介
1、MyBatis歷史
MyBatis最初是Apache的一個開源項目iBatis, 2010年6月這個項目由Apache Software Foundation遷 移到了Google Code。隨著開發團隊轉投Google Code旗下, iBatis3.x正式更名為MyBatis。代碼于 2013年11月遷移到Github。 iBatis一詞來源于“internet”和“abatis”的組合,是一個基于Java的持久層框架。 iBatis提供的持久層框架 包括SQL Maps和Data Access Objects(DAO)。2、MyBatis特性
1) MyBatis 是支持定制化 SQL、存儲過程以及高級映射的優秀的持久層框架 2) MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集 3) MyBatis可以使用簡單的XML或注解用于配置和原始映射,將接口和Java的POJO(Plain Old Java Objects,普通的Java對象)映射成數據庫中的記錄 4) MyBatis 是一個 半自動的ORM(Object Relation Mapping)框架3、MyBatis下載
MyBatis下載地址:https://github.com/mybatis/mybatis-34、和其它持久化層技術對比
JDBC
SQL 夾雜在Java代碼中耦合度高,導致硬編碼內傷 維護不易且實際開發需求中 SQL 有變化,頻繁修改的情況多見 代碼冗長,開發效率低Hibernate 和 JPA
操作簡便,開發效率高 程序中的長難復雜 SQL 需要繞過框架 內部自動生產的 SQL,不容易做特殊優化 基于全映射的全自動框架,大量字段的 POJO 進行部分映射時比較困難。 反射操作太多,導致數據庫性能下降MyBatis
輕量級,性能出色 SQL 和 Java 編碼分開,功能邊界清晰。Java代碼專注業務、SQL語句專注數據 開發效率稍遜于HIbernate,但是完全能夠接受二、搭建MyBatis
1、開發環境
IDE:idea 2019.2 構建工具:maven 3.5.4 MySQL版本:MySQL 5.7 MyBatis版本:MyBatis 3.5.72、創建maven工程
a>打包方式:jar
b>引入依賴
<dependencies> <!-- Mybatis核心 --> <dependency><groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId><version>3.5.7</version> </dependency><!-- junit測試 --> <dependency><groupId>junit</groupId><artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- MySQL驅動 --> <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.3</version></dependency></dependencies>3、創建MyBatis的核心配置文件
習慣上命名為mybatis-config.xml,這個文件名僅僅只是建議,并非強制要求。將來整合Spring 之后,這個配置文件可以省略,所以大家操作時可以直接復制、粘貼。 核心配置文件主要用于配置連接數據庫的環境以及MyBatis的全局配置信息 核心配置文件存放的位置是src/main/resources目錄下?
提示:
下面的? username 和 password 為mysql的賬號密碼? ?根據自身實際情況進行改寫??
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!--設置連接數據庫的環境--> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/MyBatis"/> <property name="username" value="root"/> <property name="password" value="123456"/></dataSource> </environment> </environments> <!--引入映射文件--><mappers> <mapper resource="mappers/UserMapper.xml"/></mappers> </configuration>4、創建mapper接口
MyBatis中的mapper接口相當于以前的dao。但是區別在于,mapper僅僅是接口,我們不需要 提供實現類。 先創建用戶類 類中屬性 與 數據庫中的字段對應 User類里面的代碼: public class User {private Integer id;private String username;private String password;private Integer age;private String sex;private String email;public User() {}public User(Integer id, String username, String password, Integer age, String sex, String email) {this.id = id;this.username = username;this.password = password;this.age = age;this.sex = sex;this.email = email;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", password='" + password + '\'' +", age=" + age +", sex='" + sex + '\'' +", email='" + email + '\'' +'}';} } 創建UserMapper接口 public interface UserMapper { /*** 添加用戶信息 */ int insertUser(); }5、創建MyBatis的映射文件
相關概念:ORM(Object Relationship Mapping)對象關系映射。 對象:Java的實體類對象 關系:關系型數據庫 映射:二者之間的對應關系 1、映射文件的命名規則: 表所對應的實體類的類名+Mapper.xml 例如:表t_user,映射的實體類為User,所對應的映射文件為UserMapper.xml 因此一個映射文件對應一個實體類,對應一張表的操作 MyBatis映射文件用于編寫SQL,訪問以及操作表中的數據 MyBatis映射文件存放的位置是src/main/resources/mappers目錄下 2、MyBatis中可以面向接口操作數據,要保證兩個一致: a>mapper接口的全類名和映射文件的命名空間(namespace)保持一致 b>mapper接口中方法的方法名和映射文件中編寫SQL的標簽的id屬性保持一致 <?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.atguigu.mybatis.mapper.UserMapper"> <!--int insertUser();--> <insert id="insertUser"> insert into t_user values(null,'張三','123',23,'女') </insert> </mapper>6、通過junit測試功能
//讀取MyBatis的核心配置文件 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); //創建SqlSessionFactoryBuilder對象SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); //通過核心配置文件所對應的字節輸入流創建工廠類SqlSessionFactory,生產SqlSession對象 SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is); //創建SqlSession對象,此時通過SqlSession對象所操作的sql都必須手動提交或回滾事務 //SqlSession sqlSession = sqlSessionFactory.openSession(); //創建SqlSession對象,此時通過SqlSession對象所操作的sql都會自動提交 S qlSession sqlSession = sqlSessionFactory.openSession(true); //通過代理模式創建UserMapper接口的代理實現類對象 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); //調用UserMapper接口中的方法,就可以根據UserMapper的全類名匹配元素文件,通過調用的方法名匹配 映射文件中的SQL標簽,并執行標簽中的SQL語句 int result = userMapper.insertUser(); //sqlSession.commit(); SqlSession:代表Java程序和數據庫之間的會話。(HttpSession是Java程序和瀏覽器之間的 會話) SqlSessionFactory:是“生產”SqlSession的“工廠”。 工廠模式:如果創建某一個對象,使用的過程基本固定,那么我們就可以把創建這個對象的 相關代碼封裝到一個“工廠類”中,以后都使用這個工廠類來“生產”我們需要的對象。7、加入log4j日志功能
a>加入依賴
<!-- log4j日志 --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>b>加入log4j的配置文件
log4j的配置文件名為log4j.xml,存放的位置是src/main/resources目錄下 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"><appender name="STDOUT" class="org.apache.log4j.ConsoleAppender"><param name="Encoding" value="UTF-8"/><layout class="org.apache.log4j.PatternLayout"><param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n"/></layout></appender><logger name="java.sql"><level value="debug"/></logger><logger name="org.apache.ibatis"><level value="info"/></logger><root><level value="debug"/><appender-ref ref="STDOUT"/></root> </log4j:configuration> 日志的級別 FATAL(致命)>ERROR(錯誤)>WARN(警告)>INFO(信息)>DEBUG(調試) 從左到右打印的內容越來越詳細三、核心配置文件詳解
核心配置文件中的標簽必須按照固定的順序: properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorF actory?,plugins?,environments?,databaseIdProvider?,mappers? <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//MyBatis.org//DTD Config 3.0//EN""http://MyBatis.org/dtd/MyBatis-3-config.dtd"> <configuration> <!--引入properties文件,此時就可以${屬性名}的方式訪問屬性值--><properties resource="jdbc.properties"></properties><settings> <!--將表中字段的下劃線自動轉換為駝峰--><setting name="mapUnderscoreToCamelCase" value="true"/> <!--開啟延遲加載--><setting name="lazyLoadingEnabled" value="true"/></settings><typeAliases> <!--typeAlias:設置某個具體的類型的別名 屬性: type:需要設置別名的類型的全類名 alias:設置此類型的別名,若不設置此屬性,該類型擁有默認的別名,即類名且不區分大小 寫 若設置此屬性,此時該類型的別名只能使用alias所設置的值 --> <!--<typeAlias type="com.atguigu.mybatis.bean.User"></typeAlias>--> <!--<typeAlias type="com.atguigu.mybatis.bean.User" alias="abc"> </typeAlias>--> <!--以包為單位,設置改包下所有的類型都擁有默認的別名,即類名且不區分大小寫--><package name="com.atguigu.mybatis.bean"/></typeAliases><!--environments:設置多個連接數據庫的環境 屬性: default:設置默認使用的環境的id --><environmentsdefault="mysql_test"> <!--environment:設置具體的連接數據庫的環境信息 屬性: id:設置環境的唯一標識,可通過environments標簽中的default設置某一個環境的id, 表示默認使用的環境 --><environmentid="mysql_test"> <!--transactionManager:設置事務管理方式 屬性:type:設置事務管理方式,type="JDBC|MANAGED" type="JDBC":設置當前環境的事務管理都必須手動處理 type="MANAGED":設置事務被管理,例如spring中的AOP --><transactionManagertype="JDBC"/> <!--dataSource:設置數據源 屬性: type:設置數據源的類型,type="POOLED|UNPOOLED|JNDI" type="POOLED":使用數據庫連接池,即會將創建的連接進行緩存,下次使用可以從 緩存中直接獲取,不需要重新創建 type="UNPOOLED":不使用數據庫連接池,即每次使用連接都需要重新創建 type="JNDI":調用上下文中的數據源 --><dataSource type="POOLED"> <!--設置驅動類的全類名--><property name="driver" value="${jdbc.driver}"/> <!--設置連接數據庫的連接地址--><property name="url" value="${jdbc.url}"/> <!--設置連接數據庫的用戶名--><property name="username" value="${jdbc.username}"/> <!--設置連接數據庫的密碼--><property name="password" value="${jdbc.password}"/></dataSource></environment></environments> <!--引入映射文件--><mappers><mapper resource="UserMapper.xml"/> <!--以包為單位,將包下所有的映射文件引入核心配置文件 注意:此方式必須保證mapper接口和mapper映射文件必須在相同的包下 --><package name="com.atguigu.mybatis.mapper"/></mappers> </configuration>四、MyBatis的增刪改查
1、添加 <!--int insertUser();--> <insert id="insertUser">insert into t_user values(null,'admin','123456',23,'男')</insert> 2、刪除 <!--int deleteUser();--> <delete id="deleteUser">delete from t_user where id = 7</delete> 3、修改 <!--int updateUser();--> <update id="updateUser">update t_user set username='ybc',password='123' where id = 6</update> 4、查詢一個實體類對象 <!--User getUserById();--> <select id="getUserById" resultType="com.atguigu.mybatis.bean.User">select * from t_user where id = 2</select> 5、查詢集合 <!--List<User> getUserList();--> <select id="getUserList" resultType="com.atguigu.mybatis.bean.User">select * from t_user</select> 注意: 1、查詢的標簽select必須設置屬性resultType或resultMap,用于設置實體類和數據庫表的映射 關系 resultType:自動映射,用于屬性名和表中字段名一致的情況 resultMap:自定義映射,用于一對多或多對一或字段名和屬性名不一致的情況 2、當查詢的數據為多條時,不能使用實體類作為返回值,只能使用集合,否則會拋出異常 TooManyResultsException;但是若查詢的數據只有一條,可以使用實體類或集合作為返回值五、MyBatis獲取參數值的兩種方式(重點)
MyBatis獲取參數值的兩種方式:${}和#{} ${}的本質就是字符串拼接,#{}的本質就是占位符賦值 ${}使用字符串拼接的方式拼接sql,若為字符串類型或日期類型的字段進行賦值時,需要手動加單引 號;但是#{}使用占位符賦值的方式拼接sql,此時為字符串類型或日期類型的字段進行賦值時,可以自 動添加單引號1、單個字面量類型的參數
若mapper接口中的方法參數為單個的字面量類型 此時可以使用${}和#{}以任意的名稱獲取參數的值,注意${}需要手動加單引號2、多個字面量類型的參數
若mapper接口中的方法參數為多個時 此時MyBatis會自動將這些參數放在一個map集合中,以arg0,arg1...為鍵,以參數為值;以 param1,param2...為鍵,以參數為值;因此只需要通過${}和#{}訪問map集合的鍵就可以獲取相對應的 值,注意${}需要手動加單引號3、map集合類型的參數
若mapper接口中的方法需要的參數為多個時,此時可以手動創建map集合,將這些數據放在map中 只需要通過${}和#{}訪問map集合的鍵就可以獲取相對應的值,注意${}需要手動加單引號4、實體類類型的參數
若mapper接口中的方法參數為實體類對象時 此時可以使用${}和#{},通過訪問實體類對象中的屬性名獲取屬性值,注意${}需要手動加單引號5、使用@Param標識參數
可以通過@Param注解標識mapper接口中的方法參數 此時,會將這些參數放在map集合中,以@Param注解的value屬性值為鍵,以參數為值;以 param1,param2...為鍵,以參數為值;只需要通過${}和#{}訪問map集合的鍵就可以獲取相對應的值, 注意${}需要手動加單引號?六、MyBatis的各種查詢功能
1、查詢一個實體類對象
/*** 根據用戶id查詢用戶信息* @param id* @return */ User getUserById(@Param("id") int id); <!--User getUserById(@Param("id") int id);--> <select id="getUserById" resultType="User">select * from t_user where id = #{id}</select>2、查詢一個list集合
/*** 查詢所有用戶信息 * @return */ List<User> getUserList(); <!--List<User> getUserList();--> <select id="getUserList" resultType="User">select * from t_user</select>3、查詢單個數據
/** 查詢用戶的總記錄數 * @return ** 在MyBatis中,對于Java中常用的類型都設置了類型別名 * 例如:java.lang.Integer-->int|integer * 例如:int-->_int|_integer * 例如:Map-->map,List-->list */int getCount(); <!--int getCount();--> <select id="getCount" resultType="_integer">select count(id) from t_user</select>4、查詢一條數據為map集合
/*** 根據用戶id查詢用戶信息為map集合 * @param id * @return */ Map<String, Object> getUserToMap(@Param("id") int id); <!--Map<String, Object> getUserToMap(@Param("id") int id);--> <select id="getUserToMap" resultType="map">select * from t_user where id = #{id} </select> <!--結果:{password=123456, sex=男, id=1, age=23, username=admin}-->5、查詢多條數據為map集合
方式一: /*** 查詢所有用戶信息為map集合 * @return * 將表中的數據以map集合的方式查詢,一條數據對應一個map;若有多條數據,就會產生多個map集合,此 時可以將這些map放在一個list集合中獲取 */ List<Map<String, Object>> getAllUserToMap(); <!--Map<String, Object> getAllUserToMap();--> <select id="getAllUserToMap" resultType="map">select * from t_user</select> 方式二: /*** 查詢所有用戶信息為map集合 * @return * 將表中的數據以map集合的方式查詢,一條數據對應一個map;若有多條數據,就會產生多個map集合,并 且最終要以一個map的方式返回數據,此時需要通過@MapKey注解設置map集合的鍵,值是每條數據所對應的 map集合 */@MapKey("id")Map<String, Object> getAllUserToMap(); <!--Map<String, Object> getAllUserToMap();--> <select id="getAllUserToMap" resultType="map">select * from t_user </select> 結果: <!-- { 1={password=123456, sex=男, id=1, age=23, username=admin}, 2={password=123456, sex=男, id=2, age=23, username=張三}, 3={password=123456, sex=男, id=3, age=23, username=張三} }-->七、特殊SQL的執行
1、模糊查詢
/*** 測試模糊查詢 * @param mohu * @return */ List<User> testMohu(@Param("mohu") String mohu); <!--List<User> testMohu(@Param("mohu") String mohu);--> <select id="testMohu"resultType="User"> <!--select * from t_user where username like '%${mohu}%'--> <!--select * from t_user where username like concat('%',#{mohu},'%')-->select * from t_user where username like "%"#{mohu}"%" </select>2、批量刪除
/*** 批量刪除 * @param ids* @return */ int deleteMore(@Param("ids") String ids) <!--int deleteMore(@Param("ids") String ids);--> <delete id="deleteMore">delete from t_user where id in (${ids})</delete>3、動態設置表名
/*** 動態設置表名,查詢所有的用戶信息 * @param tableName * @return*/List<User> getAllUser(@Param("tableName") String tableName); <!--List<User> getAllUser(@Param("tableName") String tableName);--> <select id="getAllUser" resultType="User">select * from ${tableName}</select>4、添加功能獲取自增的主鍵
t_clazz(clazz_id,clazz_name) t_student(student_id,student_name,clazz_id) 1、添加班級信息 2、獲取新添加的班級的id 3、為班級分配學生,即將某學的班級id修改為新添加的班級的id /*** 添加用戶信息 * @param user * @return * useGeneratedKeys:設置使用自增的主鍵 * keyProperty:因為增刪改有統一的返回值是受影響的行數,因此只能將獲取的自增的主鍵放在傳輸的參 數user對象的某個屬性中 */ int insertUser(User user); <!--int insertUser(User user);--> <insert id="insertUser" useGeneratedKeys="true" keyProperty="id">insert into t_uservalues(null,#{username},#{password},#{age},#{sex}) </insert>八、自定義映射resultMap
1、resultMap處理字段和屬性的映射關系
若字段名和實體類中的屬性名不一致,則可以通過resultMap設置自定義映射 <!--resultMap:設置自定義映射 屬性: id:表示自定義映射的唯一標識 type:查詢的數據要映射的實體類的類型 子標簽: id:設置主鍵的映射關系 result:設置普通字段的映射關系 association:設置多對一的映射關系 collection:設置一對多的映射關系 屬性: property:設置映射關系中實體類中的屬性名 column:設置映射關系中表中的字段名 --> <resultMap id="userMap" type="User"><id property="id" column="id"></id><result property="userName" column="user_name"></result><result property="password" column="password"></result><result property="age" column="age"></result><result property="sex" column="sex"></result> </resultMap><!--List<User> testMohu(@Param("mohu") String mohu);--> <select id="testMohu" resultMap="userMap"> <!--select * from t_user where username like '%${mohu}%'--> select id,user_name,password,age,sex from t_user where user_name like concat('%',#{mohu},'%') </select> 若字段名和實體類中的屬性名不一致,但是字段名符合數據庫的規則(使用_),實體類中的屬性 名符合Java的規則(使用駝峰) 此時也可通過以下兩種方式處理字段名和實體類中的屬性的映射關系 a>可以通過為字段起別名的方式,保證和實體類中的屬性名保持一致 b>可以在MyBatis的核心配置文件中設置一個全局配置信息mapUnderscoreToCamelCase,可 以在查詢表中數據時,自動將_類型的字段名轉換為駝峰 例如:字段名user_name,設置了mapUnderscoreToCamelCase,此時字段名就會轉換為 userName2、多對一映射處理
查詢員工信息以及員工所對應的部門信息a>級聯方式處理映射關系
<resultMap id="empDeptMap" type="Emp"><id column="eid" property="eid"></id><result column="ename" property="ename"></result><result column="age" property="age"></result><result column="sex" property="sex"></result><result column="did" property="dept.did"></result><result column="dname" property="dept.dname"></result> </resultMap> <!--Emp getEmpAndDeptByEid(@Param("eid") int eid);--> <select id="getEmpAndDeptByEid"resultMap="empDeptMap">select emp.*,dept.* from t_emp emp left join t_dept dept on emp.did = dept.did where emp.eid = #{eid} </select>?b>使用association處理映射關系
<resultMap id="empDeptMap" type="Emp"><id column="eid" property="eid"></id><result column="ename" property="ename"></result><result column="age" property="age"></result><result column="sex" property="sex"></result><association property="dept" javaType="Dept"><id column="did" property="did"></id><result column="dname" property="dname"></result></association> </resultMap> <!--Emp getEmpAndDeptByEid(@Param("eid") int eid);--> <select id="getEmpAndDeptByEid"resultMap="empDeptMap">select emp.*,dept.* from t_emp emp left join t_dept dept on emp.did = dept.did where emp.eid = #{eid} </select> c>分步查詢 1)查詢員工信息 /*** 通過分步查詢查詢員工信息* @param eid * @return */ Emp getEmpByStep(@Param("eid") int eid); <resultMap id="empDeptStepMap" type="Emp"><id column="eid" property="eid"></id><result column="ename" property="ename"></result><result column="age" property="age"></result><result column="sex"property="sex"></result><!--select:設置分步查詢,查詢某個屬性的值的sql的標識(namespace.sqlId) column:將sql以及查詢結果中的某個字段設置為分步查詢的條件 --><association property="dept" select="com.atguigu.MyBatis.mapper.DeptMapper.getEmpDeptByStep"column="did"></association> </resultMap> <!--Emp getEmpByStep(@Param("eid") int eid);--> <select id="getEmpByStep" resultMap="empDeptStepMap">select * from t_emp where eid = #{eid} </select> 2)根據員工所對應的部門id查詢部門信息 /** * 分步查詢的第二步:根據員工所對應的did查詢部門信息 * @param did * @return */ Dept getEmpDeptByStep(@Param("did") int did); <!--Dept getEmpDeptByStep(@Param("did") int did);--> <select id="getEmpDeptByStep" resultType="Dept">select * from t_dept where did = #{did}</select>3、一對多映射處理
a>collection
/*** 根據部門id查新部門以及部門中的員工信息* @param did * @return */ Dept getDeptEmpByDid(@Param("did") int did); <resultMap id="deptEmpMap" type="Dept"><id property="did" column="did"></id><result property="dname" column="dname"></result> <!--ofType:設置collection標簽所處理的集合屬性中存儲數據的類型 --><collection property="emps" ofType="Emp"><id property="eid" column="eid"></id><result property="ename" column="ename"></result><result property="age" column="age"></result><result property="sex" column="sex"></result></collection> </resultMap> <!--Dept getDeptEmpByDid(@Param("did") int did);--> <select id="getDeptEmpByDid" resultMap="deptEmpMap"> select dept.*,emp.* from t_dept dept left join t_emp emp on dept.did = emp.did where dept.did = #{did} </select>b>分步查詢
/*** 分步查詢部門和部門中的員工 * @param did * @return*/ Dept getDeptByStep(@Param("did") int did); <resultMap id="deptEmpStep" type="Dept"><id property="did" column="did"></id><result property="dname" column="dname"></result><collection property="emps" fetchType="eager" select="com.atguigu.MyBatis.mapper.EmpMapper.getEmpListByDid"column="did"></collection> </resultMap> <!--Dept getDeptByStep(@Param("did") int did);--> <select id="getDeptByStep" resultMap="deptEmpStep">select * from t_dept where did = #{did} </select> 2)根據部門id查詢部門中的所有員工 /*** 根據部門id查詢員工信息 * @param did * @return*/ List<Emp> getEmpListByDid(@Param("did") int did); <!--List<Emp> getEmpListByDid(@Param("did") int did);--> <select id="getEmpListByDid" resultType="Emp">select * from t_emp where did = #{did}</select> 分步查詢的優點:可以實現延遲加載,但是必須在核心配置文件中設置全局配置信息: lazyLoadingEnabled:延遲加載的全局開關。當開啟時,所有關聯對象都會延遲加載 aggressiveLazyLoading:當開啟時,任何方法的調用都會加載該對象的所有屬性。 否則,每個 屬性會按需加載 此時就可以實現按需加載,獲取的數據是什么,就只會執行相應的sql。此時可通過association和 collection中的fetchType屬性設置當前的分步查詢是否使用延遲加載,fetchType="lazy(延遲加 載)|eager(立即加載)"?
九、動態SQL
Mybatis框架的動態SQL技術是一種根據特定條件動態拼裝SQL語句的功能,它存在的意義是為了解決 拼接SQL語句字符串時的痛點問題。1、if
if標簽可通過test屬性的表達式進行判斷,若表達式的結果為true,則標簽中的內容會執行;反之標簽中的內容不會執行 <!--List<Emp> getEmpListByMoreTJ(Emp emp);--> <select id="getEmpListByMoreTJ" resultType="Emp">select * from t_emp where 1=1 <if test="ename != '' and ename != null">and ename = #{ename} </if><if test="age != '' and age != null">and age = #{age}</if><if test="sex != '' and sex != null">and sex = #{sex}</if> </select>2、where
<select id="getEmpListByMoreTJ2" resultType="Emp">select * from t_emp<where><if test="ename != '' and ename != null">ename = #{ename}</if><if test="age != '' and age != null">and age = #{age}</if><if test="sex != '' and sex != null">and sex = #{sex}</if></where> </select> where和if一般結合使用: a>若where標簽中的if條件都不滿足,則where標簽沒有任何功能,即不會添加where關鍵字 b>若where標簽中的if條件滿足,則where標簽會自動添加where關鍵字,并將條件最前方多余的 and去掉 注意:where標簽不能去掉條件最后多余的and3、trim
<select id="getEmpListByMoreTJ" resultType="Emp">select * from t_emp<trim prefix="where" suffixOverrides="and"><if test="ename != '' and ename != null">ename = #{ename} and</if><if test="age != '' and age != null">age = #{age} and</if><if test="sex != '' and sex != null">sex = #{sex}</if></trim> </select> trim用于去掉或添加標簽中的內容 常用屬性: prefix:在trim標簽中的內容的前面添加某些內容 prefixOverrides:在trim標簽中的內容的前面去掉某些內容 suffix:在trim標簽中的內容的后面添加某些內容 suffixOverrides:在trim標簽中的內容的后面去掉某些內容4、choose、when、otherwise
choose、when、otherwise相當于if...else if..else <!--List<Emp> getEmpListByChoose(Emp emp);--> <select id="getEmpListByChoose" resultType="Emp">select <include refid="empColumns"></include> from t_emp<where><choose><when test="ename != '' and ename != null">ename = #{ename}</when><when test="age != '' and age != null">age = #{age}</when><when test="sex != '' and sex != null">sex = #{sex}</when><when test="email != '' and email != null">email = #{email}</when></choose></where> </select>5、foreach
<!--int insertMoreEmp(List<Emp> emps);--> <insert id="insertMoreEmp">insert into t_emp values<foreach collection="emps" item="emp" separator=",">(null,#{emp.ename},#{emp.age},#{emp.sex},#{emp.email},null)</foreach> </insert> <!--int deleteMoreByArray(int[] eids);--> <delete id="deleteMoreByArray">delete from t_emp where <foreach collection="eids" item="eid" separator="or">eid = #{eid}</foreach> </delete> <!--int deleteMoreByArray(int[] eids);--> <delete id="deleteMoreByArray">delete from t_emp where eid in <foreachcollection="eids" item="eid" separator="," open="(" close=")">#{eid} </foreach> </delete> 屬性: collection:設置要循環的數組或集合 item:表示集合或數組中的每一個數據 separator:設置循環體之間的分隔符 open:設置foreach標簽中的內容的開始符 close:設置foreach標簽中的內容的結束符6、SQL片段
sql片段,可以記錄一段公共sql片段,在使用的地方通過include標簽進行引入 <sql id="empColumns">eid,ename,age,sex,did</sql> select <include refid="empColumns"></include> from t_emp十、MyBatis的緩存
1、MyBatis的一級緩存
一級緩存是SqlSession級別的,通過同一個SqlSession查詢的數據會被緩存,下次查詢相同的數據,就 會從緩存中直接獲取,不會從數據庫重新訪問 使一級緩存失效的四種情況: 1) 不同的SqlSession對應不同的一級緩存 2) 同一個SqlSession但是查詢條件不同 3) 同一個SqlSession兩次查詢期間執行了任何一次增刪改操作 4) 同一個SqlSession兩次查詢期間手動清空了緩存2、MyBatis的二級緩存
二級緩存是SqlSessionFactory級別,通過同一個SqlSessionFactory創建的SqlSession查詢的結果會被 緩存;此后若再次執行相同的查詢語句,結果就會從緩存中獲取 二級緩存開啟的條件: a>在核心配置文件中,設置全局配置屬性cacheEnabled="true",默認為true,不需要設置 b>在映射文件中設置標簽<cache />c>二級緩存必須在SqlSession關閉或提交之后有效
d>查詢的數據所轉換的實體類類型必須實現序列化的接口 使二級緩存失效的情況: 兩次查詢之間執行了任意的增刪改,會使一級和二級緩存同時失效3、二級緩存的相關配置
在mapper配置文件中添加的cache標簽可以設置一些屬性: eviction屬性:緩存回收策略 LRU(Least Recently Used) – 最近最少使用的:移除最長時間不被使用的對象。 FIFO(First in First out) – 先進先出:按對象進入緩存的順序來移除它們。 SOFT – 軟引用:移除基于垃圾回收器狀態和軟引用規則的對象。 WEAK – 弱引用:更積極地移除基于垃圾收集器狀態和弱引用規則的對象。 默認的是 LRU。 flushInterval屬性:刷新間隔,單位毫秒 默認情況是不設置,也就是沒有刷新間隔,緩存僅僅調用語句時刷新 size屬性:引用數目,正整數 代表緩存最多可以存儲多少個對象,太大容易導致內存溢出 readOnly屬性:只讀,true/false true:只讀緩存;會給所有調用者返回緩存對象的相同實例。因此這些對象不能被修改。這提供了 很重要的性能優勢。 false:讀寫緩存;會返回緩存對象的拷貝(通過序列化)。這會慢一些,但是安全,因此默認是 false。4、MyBatis緩存查詢的順序
先查詢二級緩存,因為二級緩存中可能會有其他程序已經查出來的數據,可以拿來直接使用。 如果二級緩存沒有命中,再查詢一級緩存 如果一級緩存也沒有命中,則查詢數據庫 SqlSession關閉之后,一級緩存中的數據會寫入二級緩存5、整合第三方緩存EHCache
a>添加依賴
<!-- Mybatis EHCache整合包 --> <dependency><groupId>org.mybatis.caches</groupId><artifactId>mybatis-ehcache</artifactId><version>1.2.1</version> </dependency> <!-- slf4j日志門面的一個具體實現 --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency>b>各jar包功能
?
c>創建EHCache的配置文件ehcache.xml
<?xml version="1.0" encoding="utf-8" ?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <!-- 磁盤保存路徑 --><diskStore path="D:\atguigu\ehcache"/><defaultCache maxElementsInMemory="1000" maxElementsOnDisk="10000000" eternal="false" overflowToDisk="true"timeToIdleSeconds="120" timeToLiveSeconds="120" diskExpiryThreadIntervalSeconds="120"memoryStoreEvictionPolicy="LRU"></defaultCache> </ehcache>d>設置二級緩存的類型
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>e>加入logback日志
存在SLF4J時,作為簡易日志的log4j將失效,此時我們需要借助SLF4J的具體實現logback來打印日志。 創建logback的配置文件logback.xml <?xml version="1.0" encoding="UTF-8"?> <configuration debug="true"> <!-- 指定日志輸出的位置 --><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder> <!-- 日志輸出的格式 --><!-- 按照順序分別是:時間、日志級別、線程名稱、打印日志的類、日志主體內容、換行 --><pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n</pattern> </encoder> </appender> <!-- 設置全局日志級別。日志級別按順序分別是:DEBUG、INFO、WARN、ERROR --> <!-- 指定任何一個日志級別都只打印當前級別和后面級別的日志。 --><root level="DEBUG"> <!-- 指定打印日志的appender,這里通過“STDOUT”引用了前面配置的appender --><appender-ref ref="STDOUT"/></root> <!-- 根據特殊需求指定局部日志級別 --><logger name="com.atguigu.crowd.mapper" level="DEBUG"/> </configuration>f>EHCache配置文件說明
?
十一、MyBatis的逆向工程
正向工程:先創建Java實體類,由框架負責根據實體類生成數據庫表。Hibernate是支持正向工程 的。 逆向工程:先創建數據庫表,由框架負責根據數據庫表,反向生成如下資源: ? Java實體類 ? Mapper接口 ? Mapper映射文件1、創建逆向工程的步驟
a>添加依賴和插件
<!-- 依賴MyBatis核心包 --> <dependencies><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.7</version></dependency> </dependencies> <!-- 控制Maven在構建過程中相關配置 --> <build> <!-- 構建過程中用到的插件 --> <plugins> <!-- 具體插件,逆向工程的操作是以構建過程中插件形式出現的 --><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.3.0</version> <!-- 插件的依賴 --><dependencies> <!-- 逆向工程的核心依賴 --><dependency><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-core</artifactId><version>1.3.2</version></dependency> <!-- 數據庫連接池 --><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.2</version></dependency> <!-- MySQL驅動 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.8</version></dependency></dependencies></plugin> </plugins> </build>b>創建MyBatis的核心配置文件
c>創建逆向工程的配置文件
文件名必須是:generatorConfig.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfigurationPUBLIC"-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN""http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <!-- targetRuntime: 執行生成的逆向工程的版本 MyBatis3Simple: 生成基本的CRUD(清新簡潔版) MyBatis3: 生成帶條件的CRUD(奢華尊享版) --><context id="DB2Tables" targetRuntime="MyBatis3Simple"> <!-- 數據庫的連接信息 --><jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/mybatis"userId="root" password="123456"></jdbcConnection> <!-- javaBean的生成策略--><javaModelGenerator targetPackage="com.atguigu.mybatis.bean" targetProject=".\src\main\java"><property name="enableSubPackages" value="true"/><property name="trimStrings" value="true"/></javaModelGenerator> <!-- SQL映射文件的生成策略 --><sqlMapGenerator targetPackage="com.atguigu.mybatis.mapper" targetProject=".\src\main\resources"><property name="enableSubPackages" value="true"/></sqlMapGenerator> <!-- Mapper接口的生成策略 --><javaClientGenerator type="XMLMAPPER" targetPackage="com.atguigu.mybatis.mapper"targetProject=".\src\main\java"><property name="enableSubPackages" value="true"/></javaClientGenerator> <!-- 逆向分析的表 --> <!-- tableName設置為*號,可以對應所有表,此時不寫domainObjectName --> <!-- domainObjectName屬性指定生成出來的實體類的類名 --><table tableName="t_emp" domainObjectName="Emp"/><table tableName="t_dept" domainObjectName="Dept"/></context> </generatorConfiguration>d>執行MBG插件的generate目標
?
效果:?
2、QBC查詢
@Testpublic void testMBG() throws IOException {InputStream is = Resources.getResourceAsStream("mybatis-config.xml");SqlSession sqlSession = new SqlSessionFactoryBuilder().build(is).openSession(true);EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);EmpExample empExample = new EmpExample();//創建條件對象,通過andXXX方法為SQL添加查詢添加,每個條件之間是and關系 empExample.createCriteria().andEnameLike("a").andAgeGreaterThan(20).andDidIsNot Null(); //將之前添加的條件通過or拼接其他條件 empExample.or().andSexEqualTo("男"); List<Emp> list = mapper.selectByExample(empExample); for (Emp emp : list) { System.out.println(emp); } }}十二、分頁插件
1、分頁插件使用步驟
a>添加依賴
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper --> <dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.2.0</version> </dependency>b>配置分頁插件
在MyBatis的核心配置文件中配置插件 <plugins> <!--設置分頁插件--><plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin> </plugins>2、分頁插件的使用
a>在查詢功能之前使用PageHelper.startPage(int pageNum, int pageSize)開啟分頁功能 pageNum:當前頁的頁碼 pageSize:每頁顯示的條數 b>在查詢獲取list集合之后,使用PageInfo<T> pageInfo = new PageInfo<>(List<T> list, int navigatePages)獲取分頁相關數據 list:分頁之后的數據 navigatePages:導航分頁的頁碼數c>分頁相關數據
PageInfo{ pageNum=8, pageSize=4, size=2, startRow=29, endRow=30, total=30, pages=8, list=Page{count=true, pageNum=8, pageSize=4, startRow=28, endRow=32, total=30, pages=8, reasonable=false, pageSizeZero=false}, prePage=7, nextPage=0, isFirstPage=false, isLastPage=true, hasPreviousPage=true, hasNextPage=false, navigatePages=5, navigateFirstPage4, navigateLastPage8, navigatepageNums=[4, 5, 6, 7, 8] } 常用數據: pageNum:當前頁的頁碼 pageSize:每頁顯示的條數 size:當前頁顯示的真實條數 total:總記錄數 pages:總頁數 prePage:上一頁的頁碼 nextPage:下一頁的頁碼 isFirstPage/isLastPage:是否為第一頁/最后一頁 hasPreviousPage/hasNextPage:是否存在上一頁/下一頁 navigatePages:導航分頁的頁碼數 navigatepageNums:導航分頁的頁碼,[1,2,3,4,5]注:本文章來自尚硅谷2022最新mybatis教程,如文章中有疑問,可以結合視頻一起看
?
總結
以上是生活随笔為你收集整理的2022最新最全MyBatis(简单全面,一发入魂,内容超详细)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网校系统搭建攻略
- 下一篇: Android性能优化之内存优化