日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【MyBatis】基础全网最全,看这篇就够了

發(fā)布時(shí)間:2023/12/15 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【MyBatis】基础全网最全,看这篇就够了 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、原始JDBC開發(fā)存在的問題

package com.qf.java2107.test; ? import org.junit.Test; ? import java.math.BigDecimal; import java.sql.*; ? /*** @author ghy* @version 1.0* @date 2021-12-22**/ public class JdbcTest { ?/*** 存在的問題:* ? ? 1. 需要頻繁的手動(dòng)獲取連接* ? ? 2. 需要手動(dòng)封裝查詢結(jié)果集* ? ? 3. 需要手動(dòng)釋放資源* ? ? 4. SQL硬編碼* ? 有自己封裝的工具類,也有DBUtils等工具類API。但是都沒有從根本上解決上面的問題*/@Testpublic void testJdbc(){ ?Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null; ?try {//1.反射加載驅(qū)動(dòng)Class.forName("com.mysql.jdbc.Driver"); ?//2.獲取數(shù)據(jù)庫連接connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/java2106_hotel", "root", "root"); ?//3.編寫SQLString sql = "SELECT * FROM t_user WHERE user_id = ?"; ?//4.獲取執(zhí)行SQL的載體對象,預(yù)編譯SQLpreparedStatement = connection.prepareStatement(sql);//填充占位符preparedStatement.setLong(1, 3); ?//5.執(zhí)行SQLresultSet = preparedStatement.executeQuery(); ?//6.處理結(jié)果if (resultSet.next()) {//user_id : 結(jié)果集的列名long userId = resultSet.getLong("user_id");String username = resultSet.getString("username");BigDecimal balance = resultSet.getBigDecimal("balance");System.out.println(userId + "," + username + "," + balance );}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();} finally { ?//7.釋放資源//先開后關(guān)try {if(null != resultSet) {resultSet.close();}} catch (SQLException e) {e.printStackTrace();}try {if(null != preparedStatement) {preparedStatement.close();}} catch (SQLException e) {e.printStackTrace();}try {if(null != connection) {connection.close();}} catch (SQLException e) {e.printStackTrace();}} ?} }
  • 存在的問題

    • 需要頻繁的手動(dòng)獲取連接
    • 需要手動(dòng)封裝查詢結(jié)果集
    • 需要手動(dòng)釋放資源
    • SQL硬編碼

二、ORM框架

  • 通過ORM框架解決JDBC存在的問題

1、ORM

  • Object Relation Mapping:對象關(guān)系映射

Java對象數(shù)據(jù)庫表
類名表名
屬性名列名【字段名】
對象行【記錄】

2、框架

  • 概述:就是一個(gè)半成品軟件

    • 需要使用框架幫我們完成JavaEE應(yīng)用的開發(fā)

  • 作用

    • 能夠幫我們快速有效的開發(fā)JavaEE應(yīng)用

    • 有自己對應(yīng)用場景的完整解決方案

三、Mybatis

1、概述

  • 是一款開源的、優(yōu)秀的、支持定制SQL的ORM框架

  • 官網(wǎng):mybatis – MyBatis 3 | 簡介

    MyBatis 是一款優(yōu)秀的持久層框架,它支持自定義 SQL、存儲(chǔ)過程以及高級映射。MyBatis 免除了幾乎所有的 JDBC 代碼以及設(shè)置參數(shù)和獲取結(jié)果集的工作。MyBatis 可以通過簡單的 XML 或注解來配置和映射原始類型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 對象)為數(shù)據(jù)庫中的記錄。

2、快速入門

  • 參考官網(wǎng)案例

3.2.1 實(shí)現(xiàn)步驟

  • 創(chuàng)建數(shù)據(jù)庫表

  • 導(dǎo)入依賴

  • 實(shí)體類

  • Mapper接口【Dao接口】

  • SQL映射文件

  • 全局配置文件

  • 測試

  • 3.2.2 具體實(shí)現(xiàn)

    • 創(chuàng)建數(shù)據(jù)庫表

    CREATE TABLE `t_user` (`user_id` bigint(100) NOT NULL AUTO_INCREMENT COMMENT '主鍵',`username` varchar(20) DEFAULT NULL COMMENT '用戶名',`password` varchar(32) DEFAULT NULL COMMENT '密碼',`nick_name` varchar(20) DEFAULT NULL COMMENT '昵稱',`is_admin` tinyint(4) DEFAULT NULL COMMENT '是否管理員 0:否 1:是',`phone` varchar(11) DEFAULT NULL COMMENT '手機(jī)',`gender` tinyint(4) DEFAULT NULL COMMENT '性別 0:保密 1:男 2:女',`birth` date DEFAULT NULL COMMENT '生日',`user_status` tinyint(4) DEFAULT NULL COMMENT '狀態(tài)(是否激活) 0:否 1:是',`user_create_time` datetime DEFAULT NULL COMMENT '創(chuàng)建時(shí)間',`user_update_time` datetime DEFAULT NULL COMMENT '更新時(shí)間',`is_delete` tinyint(4) DEFAULT NULL COMMENT '是否刪除 0:否 1:是',`is_member` tinyint(4) DEFAULT NULL COMMENT '是否會(huì)員 0:否 1:是',`balance` decimal(20,2) DEFAULT NULL COMMENT '賬戶余額',PRIMARY KEY (`user_id`) ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 COMMENT='這是一個(gè)用戶表'; ? ? insert ?into `t_user`(`user_id`,`username`,`password`,`nick_name`,`is_admin`,`phone`,`gender`,`birth`,`user_status`,`user_create_time`,`user_update_time`,`is_delete`,`is_member`,`balance`) values (1,'aa','e10adc3949ba59abbe56e057f20f883e','666',1,'13566778899',1,'1990-07-18',0,'2021-10-15 10:56:40','2021-10-22 10:56:43',0,1,10000.00), (2,'bb','bb','666',1,'111111',1,'1990-07-18',0,'2021-11-02 14:20:25','2021-11-03 09:25:58',0,1,1111.00), (3,'cc','mark123','666',1,'13512341234',0,'1990-07-18',0,'2021-11-03 10:05:37','2021-11-03 10:05:37',0,1,10000.00), (5,'dd','BB','666',1,'13512341234',0,'1990-07-18',0,'2021-11-03 10:15:00','2021-11-03 10:15:00',0,1,10000.00), (6,'ee','CC','666',1,'13512341234',2,'1990-07-18',0,'2021-11-03 10:40:01','2021-11-03 10:40:01',0,1,10000.00), (7,'ff','mark123','666',0,'13512341234',0,'1990-07-18',0,'2021-11-05 11:23:45','2021-11-05 11:23:45',0,1,10000.00);
    • 導(dǎo)入依賴

    <dependencies> ?<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.6</version></dependency> ?<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.2</version></dependency> ?<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency> ?<!-- lombok : 能夠快速幫我們生成實(shí)體的getter/setter方法 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.22</version><scope>provided</scope></dependency> ? </dependencies>
    • 實(shí)體類

    @Data @NoArgsConstructor @AllArgsConstructor public class User { ?private Long userId;private String username; ? //成員變量private String password;private String nickName;private Integer isAdmin;private String phone;private Integer gender;private Date birth;private Integer userStatus;private Date userCreateTime;private Date userUpdateTime;private Integer isDelete;private Integer isMember;private BigDecimal balance; ? }
    • Mapper接口

    public interface IUserMapper { ?/*** 查詢所有* @return*/List<User> findAll(); ? }
    • SQL【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"> <!--mybatis代理接口開發(fā)的要求:1.mapper映射文件的namespace 寫 mapper接口的全類名2.mapper映射文件的statementId 寫 mapper接口的對應(yīng)方法名3.mapper映射文件的resultType 寫 mapper接口的對應(yīng)方法返回值類型。如果是集合,寫泛型4.mapper映射文件的parameterType 寫 mapper接口的對應(yīng)方法形參類型。高版本mybatis可以不寫,但是不推薦--> <mapper namespace="com.qf.java2107.mapper.IUserMapper"><select id="findAll" resultType="com.qf.java2107.pojo.User"><!-- 原生SQL -->SELECTuser_id userId,username,password,nick_name,is_admin,phone,gender,birth,user_status,user_create_time,user_update_time,is_delete,is_member,balanceFROMt_user</select> </mapper>
    • 全局配置文件

    <?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><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/java2107"/><property name="username" value="root"/><property name="password" value="root"/></dataSource></environment></environments><mappers><mapper resource="com/qf/java2107/mapper/IUserMapper.xml"/></mappers> </configuration>
    • 測試代碼

    /*** mapper接口代理測試,掌握**/ @Test public void test02() {SqlSession session = null;try {String resource = "mybatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resource);SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); ?session = sqlSessionFactory.openSession();//獲取mapper代理IUserMapper userMapper = session.getMapper(IUserMapper.class);List<User> users = userMapper.findAll();//mybatis能夠幫我們自動(dòng)完成查詢結(jié)果集和實(shí)體間的映射,前提結(jié)果集列名和實(shí)體屬性名相同for (User user : users) {System.out.println(user);}} catch (IOException e) {e.printStackTrace();} finally {if(null != session) {session.close();}} }

    四、CURD操作

    • 增刪改操作涉及事務(wù),務(wù)必要提交,查詢不需要進(jìn)行事務(wù)提交

    1、增加

    • Mapper接口

    /*** 增加* @param user*/ void save(User user); Mapper映射文件<!-- void save(User user);--> <insert id="save" parameterType="com.qf.java2107.pojo.User">INSERT INTO t_user (username,password,nick_name,is_admin,phone,gender,birth,user_status,user_create_time,user_update_time,is_delete,is_member,balance)VALUES(#{username}, #{password}, #{nickName}, #{isAdmin}, #{phone}, #{gender}, #{birth}, #{userStatus},#{userCreateTime}, #{userUpdateTime}, #{isDelete}, #{isMember}, #{balance}) </insert>
    • 測試類

    /*** 增加**/ @Test public void test03() throws Exception {SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));SqlSession sqlSession = factory.openSession();IUserMapper userMapper = sqlSession.getMapper(IUserMapper.class);User user = new User();user.setUsername("lucy");user.setPassword("lucy123");user.setNickName("露西");user.setIsAdmin(0);user.setPhone("13566778899");user.setGender(0);user.setBirth(java.sql.Date.valueOf("2005-10-30"));user.setUserStatus(1);user.setUserCreateTime(new Date());user.setUserUpdateTime(new Date());user.setIsDelete(0);user.setIsMember(1);user.setBalance(new BigDecimal(2000));userMapper.save(user); ?//提交事務(wù)sqlSession.commit(); ?if(null != sqlSession) {sqlSession.close();} ? }

    1.1 主鍵回填

    • 主鍵自增

      • 方式一【Mapper映射文件】

      <!--void saveReturnPrimaryKey(User user);--> <insert id="saveReturnPrimaryKey" parameterType="com.qf.java2107.pojo.User"> ?<!--selectKey : 是指要執(zhí)行的相關(guān)的SQLorder: selectKey中SQL的執(zhí)行順序,after代表之后,before代表之前resultType : selectKey中SQL的返回值類型keyProperty : selectKey中SQL的返回值要賦值給哪個(gè)JavaBean的屬性keyColumn : selectKey中SQL的返回值對應(yīng)的數(shù)據(jù)庫表的列【這個(gè)值可以不寫,會(huì)自動(dòng)映射】--><selectKey order="AFTER" resultType="java.lang.Long" keyProperty="userId" keyColumn="user_id">SELECT LAST_INSERT_ID()</selectKey>INSERT INTO t_user (username,password,nick_name,is_admin,phone,gender,birth,user_status,user_create_time,user_update_time,is_delete,is_member,balance)VALUES(#{username}, #{password}, #{nickName}, #{isAdmin}, #{phone}, #{gender}, #{birth}, #{userStatus},#{userCreateTime}, #{userUpdateTime}, #{isDelete}, #{isMember}, #{balance}) </insert>
      • 方式二

      <!-- void saveReturnPrimaryKey2(User user); --> <!--useGeneratedKeys : 是否使用主鍵生成策略true:是這種方式可以獲取批量插入的主鍵值--> <insert id="saveReturnPrimaryKey2" parameterType="com.qf.java2107.pojo.User"useGeneratedKeys="true" keyProperty="userId" keyColumn="user_id">INSERT INTO t_user(username,password,nick_name,is_admin,phone,gender,birth,user_status,user_create_time,user_update_time,is_delete,is_member,balance)VALUES(#{username}, #{password}, #{nickName}, #{isAdmin}, #{phone}, #{gender}, #{birth}, #{userStatus},#{userCreateTime}, #{userUpdateTime}, #{isDelete}, #{isMember}, #{balance}) </insert>

    2、修改

    <!--int update(User user);--> <update id="update">UPDATE t_userSET PASSWORD = #{password}, nick_name = #{nickName}, user_update_time = #{userUpdateTime}WHERE user_id = #{userId} </update>

    3、刪除

    <!--boolean deleteById(Long userId);--> <delete id="deleteById" parameterType="long">DELETE FROM t_user WHERE user_id = #{userId} </delete>

    4、主鍵是字符串實(shí)現(xiàn)主鍵回填

    • 實(shí)體類

    import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; /*** @author ghy* @version 1.0* @date**/ @Data @NoArgsConstructor @AllArgsConstructor public class Stu { ?private String stuId;private String stuName; ? }

    • 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"> <mapper namespace="com.qf.java2107.mapper.IStuMapper"> ?<!-- int saveReturnPrimaryKey(Stu stu); --><insert id="saveReturnPrimaryKey" parameterType="com.qf.java2107.pojo.Stu"><selectKey order="BEFORE" keyProperty="stuId" resultType="string" keyColumn="stu_id">SELECT REPLACE(UUID(), '-', '')</selectKey>insert into t_stu (stu_id, stu_name) values (#{stuId},#{stuName})</insert> ? </mapper>

    五、日志

    1、日志體系

    • Slf4j:接口【門面】

      • Log4j

      • Logback

      • commons-logging

    2、日志作用

    • 沒日志:很難判斷問題來源

    • 有日志:一般都可以判斷問題來源。

      • 可以通過日志把問題錯(cuò)誤信息給記錄下來

    3、使用

    • 引入依賴

    <!-- 日志 --> <dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.7</version> </dependency> <dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version> </dependency>
    • 日志配置文件【log4j.properties】

    log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.err log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n log4j.appender.file=org.apache.log4j.FileAppender log4j.appender.file.File=ssm.log log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n log4j.rootLogger=debug, stdout, file
    • 日志級別

    級別描述
    ALL LEVEL打開所有日志記錄開關(guān);是最低等級的,用于打開所有日志記錄。
    DEBUG輸出調(diào)試信息;指出細(xì)粒度信息事件對調(diào)試應(yīng)用程序是非常有幫助的。【開發(fā)使用】
    INFO輸出提示信息;消息在粗粒度級別上突出強(qiáng)調(diào)應(yīng)用程序的運(yùn)行過程。【線上使用】
    WARN輸出警告信息;表明會(huì)出現(xiàn)潛在錯(cuò)誤的情形。
    ERROR輸出錯(cuò)誤信息;指出雖然發(fā)生錯(cuò)誤事件,但仍然不影響系統(tǒng)的繼續(xù)運(yùn)行。
    FATAL輸出致命錯(cuò)誤;指出每個(gè)嚴(yán)重的錯(cuò)誤事件將會(huì)導(dǎo)致應(yīng)用程序的退出。
    OFF LEVEL關(guān)閉所有日志記錄開關(guān);是最高等級的,用于關(guān)閉所有日志記錄。
    • 直接使用API即可

    package com.qf.java2107.test; ? import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; ? /*** @author ghy* @version 1.0* @date 2021-12-23**/ public class LoggerTest { ?Logger logger = LoggerFactory.getLogger(LoggerTest.class); ?/*****/@Testpublic void logTest() throws Exception {logger.debug("debug---->{}", "debug level");logger.info("info--->{}---{}", "aa", "bb");logger.warn("warn----->");logger.error("error---->");} } ?

    4、常用插件

    六、Mapper接口參數(shù)綁定

    1、單個(gè)簡單類型參數(shù)

    基本數(shù)據(jù)類型及其包裝類,String

    Mapper映射文件獲取參數(shù)值時(shí),名稱可以隨意。但是強(qiáng)烈建議參數(shù)名跟形參名一致

    2、實(shí)體類型參數(shù)

    JavaBean

    Mapper映射文件獲取參數(shù)值時(shí),使用#{},{}中寫JavaBean的屬性名

    3、Map入?yún)?/h2> Mapper映射文件獲取參數(shù)值時(shí),使用#{},{}中寫Map中key的名稱

    4、多個(gè)參數(shù)

    mybatis會(huì)把參數(shù)封裝成一個(gè)Map,第一個(gè)參數(shù)的key為arg0【param1】,第二參數(shù)的key為arg1【param2】,以此類推。

    以上方式不推薦使用,可讀性太差。

    Mapper映射文件獲取參數(shù)值時(shí),使用@Param來為Mapper接口方法指定入?yún)⒌膮?shù)名,使用#{}取值

    七、ORM映射

    把查詢結(jié)果集跟JavaBean進(jìn)行映射綁定

    1、映射規(guī)則

    • 當(dāng)查詢結(jié)果集的列名跟JavaBean屬性名相同時(shí),自動(dòng)映射

    • 當(dāng)查詢結(jié)果集的列名跟JavaBean屬性名不相同時(shí),需要手動(dòng)映射

    2、不滿足映射規(guī)則

    • 如果滿足駝峰

      • 使用別名進(jìn)行映射【但是SQL太長】

      <!-- User findByIdMapping1(Long userId); --> <select id="findByIdMapping1" parameterType="java.lang.Long" resultType="com.qf.java2107.pojo.User">SELECTuser_id userId,username,password,nick_name nickName,is_admin isAdmin,phone,gender,birth,user_status userStatus,user_create_time userCreateTime,user_update_time userUpdateTime,is_delete isDelete,is_member isMember,balanceFROMt_userWHERE user_id = #{userId} </select>
      • 全局配置文件【mybatis-config.xml】開啟駝峰映射

      <settings><!-- 開啟駝峰映射,編寫的SQL就不用使用別名了 --><setting name="mapUnderscoreToCamelCase" value="true"/> </settings> <!-- User findByIdMapping2(Long userId); --> <select id="findByIdMapping2" parameterType="java.lang.Long" resultType="com.qf.java2107.pojo.User">SELECTuser_id,username,password,nick_name,is_admin,phone,gender,birth,user_status,user_create_time,user_update_time,is_delete,is_member,balanceFROMt_userWHERE user_id = #{userId} </select>

    3、ResultMap

    • 自定義結(jié)果集映射

      • mybatis內(nèi)部已經(jīng)集成了結(jié)果集映射,就是Mapper映射文件的resultType屬性。resultType底層使用其實(shí)也是ResultMap

      • resultType和resultMap最好只使用一個(gè)

        • 如果滿足駝峰并且不使用別名的情況下,可以使用resultType

        • resultMap可以在查詢結(jié)果集封裝中自定義使用。連表查詢只能使用resultMap

    <!--resultMap: 自定義結(jié)果集id : resultMap的名稱,是一個(gè)唯一標(biāo)識(shí),用于被select的resultMap屬性所引用type : 查詢的結(jié)果集要映射到的實(shí)體類型--> <resultMap id="myResultMap" type="com.qf.java2107.pojo.User"><!--id : 映射主鍵列,只是一個(gè)標(biāo)識(shí)作用,也可以用resultcolumn : 查詢的結(jié)果集的列名property : JavaBean的屬性名--><id column="uid" property="userId"/><!-- result : 映射普通列 --><result column="username" property="username"/><result column="password" property="password"/><result column="name" property="nickName"/><result column="is_admin" property="isAdmin"/><result column="phone" property="phone"/><result column="sex" property="gender"/><result column="birth" property="birth"/><result column="user_status" property="userStatus"/><result column="ctime" property="userCreateTime"/><result column="user_update_time" property="userUpdateTime"/><result column="is_delete" property="isDelete"/><result column="is_member" property="isMember"/><result column="balance" property="balance"/> </resultMap> ? <!-- User findByIdUseResultMap(Long userId); --> <select id="findByIdUseResultMap" parameterType="java.lang.Long" resultMap="myResultMap">SELECTuser_id uid, username, password, nick_name name, is_admin, phone, gender sex, birth, user_status, user_create_time ctime, user_update_time, is_delete, is_member, balanceFROMt_userWHERE user_id = #{userId} </select> resultMap的使用

    八、全局配置文件【了解】

    • 現(xiàn)在:會(huì)

    • 以后:配置文件不見了,放到Spring中

    全局配置文件支持的標(biāo)簽

    1、properties

    <!--properties : 加載外部properties文件resource : properties文件基于classpath的路徑 --> <properties resource="jdbc.properties" />

    2、settings

    <!-- 全局設(shè)置 --> <settings><!-- 開啟駝峰映射 --><setting name="mapUnderscoreToCamelCase" value="true"/> </settings>

    3、typeAliases

    內(nèi)置別名【推薦使用】

    • 自定義別名

    <!-- 別名設(shè)置 --> <typeAliases><!-- 單個(gè)取別名 --><!--<typeAlias type="com.qf.java2107.pojo.User" alias="user"></typeAlias><typeAlias type="com.qf.java2107.pojo.Student" alias="student"></typeAlias>--><!-- 批量取別名,默認(rèn)別名是類名,別名不區(qū)分大小寫 --><package name="com.qf.java2107.pojo"/> </typeAliases>

    4、plugins

    4.1 分頁插件概述

    • 可以屏蔽底層數(shù)據(jù)庫的差異,實(shí)現(xiàn)同一API實(shí)現(xiàn)不同數(shù)據(jù)庫的分頁功能

    • Mybatis_PageHelper: Mybatis分頁插件

    4.2 使用步驟

    • 導(dǎo)入依賴

    <dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.1.10</version> </dependency>
    • 全局配置文件

    <plugins><!-- com.github.pagehelper為PageHelper類所在包名 --><plugin interceptor="com.github.pagehelper.PageInterceptor"><!-- 配置方言,不配置,則使用數(shù)據(jù)庫連接來判斷 --><property name="helperDialect" value="mysql"/><!-- 合理化參數(shù) --><property name="reasonable" value="true"/></plugin> </plugins>
    • 使用

      • Mapper映射文件

      <!-- List<User> findAll(); --> <select id="findAll" resultType="User">select * from t_user </select>
      • 測試代碼

      /*** 分頁**/ @Test public void Test() throws Exception {IUserMapper userMapper = sqlSession.getMapper(IUserMapper.class); ?//分頁設(shè)置跟查詢之間不要出現(xiàn)其他操作//參數(shù)一:頁碼//參數(shù)二:顯示條數(shù)PageHelper.startPage(3, 5);List<User> list = userMapper.findAll(); ?PageInfo<User> pageInfo = new PageInfo<>(list);System.out.println("當(dāng)前頁:" + pageInfo.getPageNum());System.out.println("當(dāng)前頁集合:" + pageInfo.getList());System.out.println("總頁數(shù):" + pageInfo.getPages());System.out.println("總條數(shù):" + pageInfo.getTotal());System.out.println("顯示條數(shù):" + pageInfo.getPageSize()); ?//顯示條數(shù)System.out.println("實(shí)際顯示條數(shù):" + pageInfo.getSize()); ?//實(shí)際顯示條數(shù) ? }

    5、environments

    • 環(huán)境配置

    <!-- 環(huán)境配置 --> <!--default 默認(rèn)使用哪個(gè)環(huán)境,這個(gè)值是指environments下的某個(gè)environment子標(biāo)簽的id屬性--> <environments default="mysqldb"><!--mysql環(huán)境id :就是當(dāng)前環(huán)境的唯一標(biāo)識(shí),可能被environments的default引用--><environment id="mysqldb"><!--transactionManager : 事務(wù)管理器type : JDBC--><transactionManager type="JDBC"></transactionManager><!--dataSource : 數(shù)據(jù)源type : POOLED 池化 ?--><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><!-- oracle環(huán)境 --><!--<environment id="oracledb"><transactionManager type="JDBC"></transactionManager><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>

    6、mappers

    • 用來加載Mapper映射文件

    <!-- 加載mapper映射文件 --> <mappers><!--mapper : 加載單個(gè)mapper映射文件resource :基于classpath路徑下的mapper映射文件class : 基于mapper接口,mybatis注解開發(fā)方式。寫mapper接口全類名--><!--<mapper resource="com/qf/java2107/mapper/IUserMapper.xml" ></mapper>--><!--批量加載mapper映射文件要求:mapper映射文件跟mapper接口在編譯后必須在同一個(gè)路徑下--><package name="com.qf.java2107.mapper"/> </mappers>

    九、連表查詢

    1、表與表之間的關(guān)系

    • 數(shù)據(jù)庫層面

      • 一對多:部門對員工、公司對部門

      • 多對多:項(xiàng)目跟程序員、學(xué)生跟老師

      • 多對一:學(xué)生對班級、員工對部門

      • 一對一:人跟身份證、旅客跟護(hù)照

    • mybatis層面

      • 一對多【多對多】

      • 一對一【多對一】

    2、部門表跟員工表為例

    • 一對多:查詢部門關(guān)聯(lián)查詢員工

    • 一對一:查詢員工關(guān)聯(lián)查詢部門

    2.1 準(zhǔn)備工作

    • 數(shù)據(jù)庫表

    CREATE TABLE `t_department` (`id` INT(11) NOT NULL AUTO_INCREMENT,`dept_name` VARCHAR(20) NOT NULL,PRIMARY KEY (`id`) ) ENGINE=INNODB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; ? INSERT ?INTO `t_department`(`id`,`dept_name`) VALUES (1,'研發(fā)部'), (2,'市場部'), (3,'財(cái)務(wù)部'), (4,'測試部'); ? ? CREATE TABLE `t_employee` (`id` INT(11) NOT NULL AUTO_INCREMENT,`emp_name` VARCHAR(20) NOT NULL,`gender` INT(1) DEFAULT NULL COMMENT '1:男 0:女',`birthday` DATE DEFAULT NULL,`hire_date` DATETIME DEFAULT NULL,`salary` INT(11) DEFAULT NULL,`address` VARCHAR(200) DEFAULT NULL,`dept_id` INT(11) DEFAULT NULL,PRIMARY KEY (`id`) ) ENGINE=INNODB AUTO_INCREMENT=101 DEFAULT CHARSET=utf8; ? ? INSERT ?INTO `t_employee`(`id`,`emp_name`,`gender`,`birthday`,`hire_date`,`salary`,`address`,`dept_id`) VALUES (1,'寶寶',0,'2000-10-31','2021-10-01 09:00:00',8000,'杭州江干',2), (2,'李四',1,'1985-11-10','2006-12-12 18:10:10',9000,'李家村',1), (3,'王五',0,'1991-10-02','2009-12-02 00:00:00',1500,'王家村',2), (5,'測試更新2',1,'2021-10-04','2021-11-11 00:00:00',15000,'杭州',2), (7,'大CC',1,'2019-05-12','2021-11-07 00:00:00',6000,'杭州',2), (8,'DD',1,'2021-11-05','2021-11-05 00:00:00',6000,'杭州',1), (9,'九妹',0,'2021-11-11','2005-12-06 00:00:00',11111,'遠(yuǎn)古時(shí)期',NULL), (10,'蕭炎',1,'1999-12-12','2021-02-03 00:00:00',5000,'牛田村',1), (11,'蕭媚',1,'1985-11-11','2006-12-12 00:00:00',9000,'李家村',1), (12,'小醫(yī)仙',0,'1991-10-02','2009-12-02 00:00:00',1500,'王家村',2), (13,'林動(dòng)',1,'2021-11-05','2021-11-05 00:00:00',6000,'杭州',1), (14,'凌青竹',1,'2021-11-05','2021-11-05 00:00:00',6000,'杭州',1), (15,'紀(jì)寧',1,'2021-11-05','2021-11-05 00:00:00',6000,'杭州',2), (16,'北冥',1,'2021-11-05','2021-11-05 00:00:00',6000,'杭州',1), (17,'葉伏天',0,'2021-11-11','2005-12-06 00:00:00',11111,'遠(yuǎn)古時(shí)期',NULL), (18,'余生',0,'2021-11-11','2005-12-06 00:00:00',11111,'遠(yuǎn)古時(shí)期',2), (19,'花解語',0,'2021-11-11','2005-12-06 00:00:00',11111,'遠(yuǎn)古時(shí)期',1), (100,'張三',1,'1999-12-12','2021-02-03 00:00:00',5000,'牛田村',1); 部門表跟員工表

    • 實(shí)體

    部門

    員工

    2.2 一對多

    • 根據(jù)ID查詢部門信息且關(guān)聯(lián)員工信息

    2.2.1 修改部門實(shí)體

    修改部門實(shí)體

    2.2.2 Mapper接口和Mapper映射文件

    Mapper接口和Mapper映射文件

    • Mapper接口

    public interface IDepartmentMapper { ?Department findByIdAndEmps(Integer id); ? }
    • Mapper映射文件

    ? ?<resultMap id="DeptAndEmpsResultMap" type="com.qf.java2107.pojo.Department" extends="BaseResultMap"> ?<!-- 映射一對多【集合】 --><!--collection: 映射一對多【集合】property: 集合名ofType : 集合中的元素類型--><collection property="employees" ofType="com.qf.java2107.pojo.Employee"><!-- 映射單個(gè)員工 --><id column="emp_id" property="id"/><result column="emp_name" property="empName"/><result column="gender" property="gender"/><result column="birthday" property="birthday"/><result column="hire_date" property="hireDate"/><result column="salary" property="salary"/><result column="address" property="address"/><result column="dept_id" property="deptId"/></collection></resultMap> ?<resultMap id="BaseResultMap" type="com.qf.java2107.pojo.Department"><id column="id" property="id"/><result column="dept_name" property="deptName"/></resultMap> ?<!-- Department findByIdAndEmps(Integer id); --><select id="findByIdAndEmps" parameterType="int" resultMap="DeptAndEmpsResultMap">SELECTd.id,d.dept_name,e.id emp_id,e.emp_name,e.gender,e.birthday,e.hire_date,e.salary,e.address,e.dept_idFROMt_department d, t_employee eWHERE d.id = e.dept_idAND d.id = #{id}</select>

    2.3 一對一

    • 根據(jù)ID查詢員工信息且關(guān)聯(lián)部門信息

    2.3.1 修改員工實(shí)體

    修改員工實(shí)體

    2.3.2 Mapper接口和Mapper映射文件

    Mapper接口和Mapper映射文件

    • Mapper接口

    public interface IEmployeeMapper { ?Employee findByIdAndDept(Integer id); ? }
    • 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"> ? <mapper namespace="com.qf.java2107.mapper.IEmployeeMapper"> ?<resultMap id="BaseResultMap" type="com.qf.java2107.pojo.Employee"><id column="id" property="id"/><result column="emp_name" property="empName"/><result column="gender" property="gender"/><result column="birthday" property="birthday"/><result column="hire_date" property="hireDate"/><result column="salary" property="salary"/><result column="address" property="address"/><result column="dept_id" property="deptId"/></resultMap> ?<resultMap id="EmpAndDeptResultMap" type="com.qf.java2107.pojo.Employee" extends="BaseResultMap"><!--association : 映射實(shí)體property : 實(shí)體屬性名javaType : 實(shí)體屬性全類名--><association property="department" javaType="com.qf.java2107.pojo.Department"><id column="did" property="id"/><result column="dept_name" property="deptName"/></association></resultMap> ?<!-- Employee findByIdAndDept(Integer id); --><select id="findByIdAndDept" parameterType="int" resultMap="EmpAndDeptResultMap">SELECTe.id id,e.emp_name,e.gender,e.birthday,e.hire_date,e.salary,e.address,e.dept_id,d.id did,d.dept_nameFROMt_employee e JOIN t_department dON e.dept_id = d.idWHERE e.id = #{id}</select> </mapper>

    十、分步查詢、延遲加載

    1、分步查詢

    • 是連表查詢的另一種方式

      • 把連表查詢的SQL進(jìn)行拆分出多個(gè)單表查詢的SQL

    2、一對多

    • 查詢部門信息關(guān)聯(lián)查詢員工信息

    2.1 IDeparmentMapper映射文件

    <!-- =================分步查詢====================== --> <resultMap id="DeptAndEmpStepQueryResultMap" type="com.qf.java2107.pojo.Department"><id column="id" property="id"/><result column="dept_name" property="deptName"/><!-- 映射集合 --><collection property="employees" ofType="com.qf.java2107.pojo.Employee"select="com.qf.java2107.mapper.IEmployeeMapper.findByDeptId" column="id"></collection> </resultMap><!--Department findByIdUseStepQuery(Integer id);--> <select id="findByIdUseStepQuery" parameterType="int" resultMap="DeptAndEmpStepQueryResultMap">SELECT id, dept_name FROM t_department WHERE id = #{id} </select>

    2.2 IEmployeeMapper映射文件

    <!--==================分步查詢相關(guān)======================== --> <!--List<Employee> findByDeptId(Integer deptId);--> <select id="findByDeptId" parameterType="int" resultMap="BaseResultMap">SELECT * FROM t_employee WHERE dept_id = #{deptId} </select>

    2.3 執(zhí)行流程

    執(zhí)行流程

    3、延遲加載【面試題】

    也叫懶加載,也叫按需加載

    當(dāng)需要使用到關(guān)聯(lián)的數(shù)據(jù)時(shí),才去執(zhí)行查詢操作

    實(shí)現(xiàn)原理:Cglib動(dòng)態(tài)代理【基于繼承】

    延遲加載只會(huì)出現(xiàn)在分步查詢中。一般延遲加載的數(shù)據(jù)都是大數(shù)據(jù)【如集合】

    • 即時(shí)加載:先執(zhí)行完所有的SQL,再打印數(shù)據(jù)

    • 延遲加載,先執(zhí)行需要獲取數(shù)據(jù)的SQL,再打印數(shù)據(jù)。后面如果還需要獲取數(shù)據(jù),再執(zhí)行SQL,再打印數(shù)據(jù)

    3.1 具體實(shí)現(xiàn)

    • 全局配置文件開啟延遲加載的開頭

    全局配置文件開啟延遲加載的開頭

    • DepartmentMapper接口和映射文件

    DepartmentMapper接口和映射文件

    • 測試

    即時(shí)加載

    延遲加載

    十一、動(dòng)態(tài)SQL

    • if

    • choose (when, otherwise)

    • trim (where, set)

    • foreach

    1、if

    • 條件判斷

      • 成立,就拼接SQL

    2、where

    • 功能相當(dāng)于數(shù)據(jù)庫的where關(guān)鍵字

    <!-- List<Employee> findWithIf(Employee employee); --> <select id="findWithIf" parameterType="com.qf.java2107.pojo.Employee" resultType="com.qf.java2107.pojo.Employee">SELECT * FROM t_employee<!--WHERE 1=1--><!-- where 會(huì)忽略條件成立的最前面的多余的and或者or --><where><if test="empName != null and empName.trim() != ''">AND emp_name LIKE #{empName}</if><if test="salary != null and salary > 0">AND salary = #{salary}</if><if test="gender == 0 || gender == 1">AND gender = #{gender}</if><if test="deptId != null">AND dept_id = #{deptId} </if><!-- 除SQL之外的地方都是JavaBean的屬性名 --></where> </select>

    3、trim【理解】

    • 可以自定義的拼接或去掉SQL片段前后綴

    <!-- List<Employee> findWithTrim(Employee employee); --><select id="findWithTrim" parameterType="com.qf.java2107.pojo.Employee" resultType="com.qf.java2107.pojo.Employee">SELECT * FROM t_employee<!--prefix : 要加的前綴prefixOverrides : 要去掉的前綴suffix : 要加的后綴suffixOverrides : 要去掉的后綴--><!--<trim prefix="where" prefixOverrides="and | or" suffix="" suffixOverrides=""><if test="empName != null and empName.trim() != ''">AND emp_name LIKE #{empName}</if><if test="salary != null and salary > 0">AND salary = #{salary}</if><if test="gender == 0 || gender == 1">AND gender = #{gender}</if><if test="deptId != null">AND dept_id = #{deptId}</if></trim>--><trim prefix="where" prefixOverrides="" suffix="" suffixOverrides="AND | OR"><if test="empName != null and empName.trim() != ''">emp_name LIKE #{empName} AND</if><if test="salary != null and salary > 0">salary = #{salary} AND</if><if test="gender == 0 || gender == 1">gender = #{gender} AND</if><if test="deptId != null">dept_id = #{deptId} AND</if></trim></select>

    4、forEach

    <!-- List<Employee> findByIds(List<Integer> ids); --> <select id="findByIds" parameterType="list" resultType="com.qf.java2107.pojo.Employee"><!--SELECT * FROM t_employee WHERE id IN (1,25,3,62)-->SELECT * FROM t_employee<where><if test="list != null and list.size() > 0"><!--id IN (1,25,3,62)--><!--collection : 要遍歷的集合,可以使用別名,但是如果使用了@Param指定入?yún)ey,那么就指定這個(gè)keyitem : 正在迭代的元素名,自己起名separator : 元素之間的分隔符open : 要遍歷的元素開始之前的SQL片段close : 要遍歷的元素結(jié)束之后的SQL片段--><foreach collection="list" item="id" separator="," open="id IN (" close=")">#{id}</foreach></if></where> </select>

    5、choose...when...otherwise【了解】

    <!-- List<Employee> findWithChoose(Employee employee); --> <select id="findWithChoose" parameterType="com.qf.java2107.pojo.Employee" resultType="com.qf.java2107.pojo.Employee">SELECT * FROM t_employee<where><choose><when test="empName != null and empName.trim() != ''">AND emp_name LIKE #{empName}</when><when test="salary != null and salary > 0">AND salary = #{salary}</when><when test="gender == 0 or gender == 1">AND gender = #{gender}</when><otherwise>dept_id = 1</otherwise></choose></where> </select>

    6、sql...include

    <!-- List<Employee> findByIds(List<Integer> ids); --><select id="findByIds" parameterType="list" resultType="com.qf.java2107.pojo.Employee"><include refid="BaseSelect"></include><where><if test="list != null and list.size() > 0"><foreach collection="list" item="id" separator="," open="id IN (" close=")">#{id}</foreach></if></where></select><sql id="BaseSelect">SELECT<include refid="BaseColumn"></include>FROM t_employee</sql><sql id="BaseColumn">id,emp_name,gender,birthday,hire_date,salary,address,dept_id</sql>

    7、set

    • 僅用于更新,跟if配套使用

    <!-- int updateWithSet(Employee employee); --> <update id="updateWithSet" parameterType="Employee">update t_employee<set><if test="empName != null and empName.trim() != ''">emp_name = #{empName},</if><if test="salary != null and salary > 0">salary = #{salary},</if><if test="gender == 0 or gender == 1">gender = #{gender},</if></set>where id = #{id} </update>

    十二、緩存機(jī)制【理解】

    • 作用

      • 提高查詢效率

      • 減輕數(shù)據(jù)庫訪問壓力

    1、分類

    • 一級緩存

    • 二級緩存

    2、區(qū)別

    • 一級緩存

      • 級別:SqlSession

      • 存儲(chǔ)介質(zhì):內(nèi)存

      • 存儲(chǔ)類型:對象副本

      • 失效情況

    • 二級緩存

      • 級別:NameSpace

      • 存儲(chǔ)介質(zhì):磁盤

      • 存儲(chǔ)類型:散裝數(shù)據(jù)

      • 觸發(fā)條件

    3、Mybatis執(zhí)行查詢流程

    Mybatis執(zhí)行查詢流程

    4、一級緩存

    • 一級緩存默認(rèn)開啟,我們無法關(guān)閉他

    • 在執(zhí)行兩次相同的查詢時(shí),第一次會(huì)向數(shù)據(jù)庫發(fā)送SQL,并且寫入一份到一級緩存中,那么后面的查詢操作就直接從緩存中獲取數(shù)據(jù)。不會(huì)向數(shù)據(jù)庫發(fā)送SQL

    • 一級緩存失效的情況

      • 不是同一個(gè)SqlSession

      • 兩次相同的查詢中間執(zhí)行增刪改

      • 兩次相同的查詢中間手動(dòng)清空緩存

      • 兩次相同的查詢中間手動(dòng)提交事務(wù)

    @Test public void firstLevelCacheTest() throws Exception {IEmployeeMapper employeeMapper = sqlSession.getMapper(IEmployeeMapper.class);Employee employee1 = employeeMapper.findById(10);System.out.println(employee1);//1.兩個(gè)SqlSession//sqlSession = factory.openSession();//employeeMapper = sqlSession.getMapper(IEmployeeMapper.class);//2.執(zhí)行增刪改//employeeMapper.deleteById(111111);//3.手動(dòng)清空緩存//sqlSession.clearCache();//4.手動(dòng)提交事務(wù)sqlSession.commit();Employee employee2 = employeeMapper.findById(10);System.out.println(employee2);System.out.println(employee1 == employee2);}

    5、二級緩存

    • 二級緩存默認(rèn)開啟,我們可以通過配置文件對其關(guān)閉

    • 二級緩存

      • 必須在SqlSession關(guān)閉之后,數(shù)據(jù)才會(huì)被寫入到二級緩存中。

      • 存儲(chǔ)介質(zhì)是磁盤,所以寫入的字節(jié)數(shù)據(jù),那么要被寫入的對象所在的類必須實(shí)現(xiàn)Serializable接口

    • 實(shí)現(xiàn)步驟

      • 全局配置文件開啟

      • 在要使用二級緩存的namespace中配置一個(gè)<cache/>標(biāo)簽

      • 關(guān)閉SqlSession

    /*** 二級緩存**/ @Test public void secondLevelCacheTest() throws Exception {IEmployeeMapper employeeMapper = sqlSession.getMapper(IEmployeeMapper.class);Employee employee1 = employeeMapper.findById(10);System.out.println(employee1);sqlSession.close();sqlSession = factory.openSession();employeeMapper = sqlSession.getMapper(IEmployeeMapper.class);Employee employee2 = employeeMapper.findById(10);System.out.println(employee2);System.out.println(employee1 == employee2);}

    十三、#{}和${}的區(qū)別

    • #{}

      • 在填充參數(shù)時(shí),是通過?占位符的方式,能夠避免SQL注入

      • 只是獲取跟數(shù)據(jù)庫表列相關(guān)的值

    • ${}

      • 在填充參數(shù)時(shí),使用的是直接進(jìn)行字符串拼接,會(huì)有SQL注入的風(fēng)險(xiǎn)

      • 使用其可以操作非數(shù)據(jù)庫表列的取值

    優(yōu)先選擇#{}取值,如果不行,則使用${}

    十四、注解開發(fā)【會(huì)用】

    • 注解開發(fā)跟配置文件開發(fā),選擇一種

    package com.qf.java2107.mapper;import com.qf.java2107.pojo.Department; import org.apache.ibatis.annotations.*;import java.util.List;/*** @author ghy* @version 1.0* @date 2021-12-27**/ public interface IDepartmentMapper {@Insert("insert into t_department (dept_name) values (#{deptName})")@SelectKey(statement = "select last_insert_id()",keyProperty = "id",keyColumn = "dept_id",before = false,resultType = int.class)int save(Department department);/*** @Results 等同于配置文件的resultMap標(biāo)簽* id 等同于配置文件的resultMap標(biāo)簽中id屬性** @Result : 映射單個(gè)屬性,用boolean來區(qū)分是否是主鍵映射*/@Results(id = "BaseResultMap",value = {@Result(id = true, column = "id", property = "id"),@Result(id = false, column = "dept_name", property = "deptName")})@Select("select id, dept_name from t_department")List<Department> findAll();@ResultMap("BaseResultMap") //引用其他已經(jīng)定義好的ResultMap@Select("select id, dept_name from t_department where id = #{id}")Department findById(Integer id);}
    • 分步查詢【IEmployeeAnnoMapper.class】

    package com.qf.java2107.mapper;import com.qf.java2107.pojo.Employee; import org.apache.ibatis.annotations.One; import org.apache.ibatis.annotations.Result; import org.apache.ibatis.annotations.Results; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.mapping.FetchType;/*** @author ghy* @version 1.0* @date 2021-12-27**/ public interface IEmployeeAnnoMapper {/*** 根據(jù)ID查詢員工關(guān)聯(lián)部門* @param id* @return*/@Results({@Result(id = true, column = "id", property = "id"),@Result(id = false, column = "emp_name", property = "empName"),@Result(id = false, column = "gender", property = "gender"),@Result(id = false, column = "birthday", property = "birthday"),@Result(id = false, column = "hire_date", property = "hireDate"),@Result(id = false, column = "salary", property = "salary"),@Result(id = false, column = "address", property = "address"),@Result(id = false, column = "dept_id", property = "deptId"),@Result(id = false, property = "dept", column = "dept_id",//one 一對一映射one = @One(select = "com.qf.java2107.mapper.IDepartmentMapper.findById",fetchType = FetchType.LAZY))})@Select("select * from t_employee where id = #{id}") //dept_idEmployee findByIdUseStep(Integer id);}

    十五、源碼分析【聽一遍】

    1、查詢

    • 查詢單個(gè)

      • DefaultSqlSession的selectOne方法

        • DefaultSqlSession的selectList方法,得到結(jié)果后,進(jìn)行集合數(shù)量判斷,如果是1,直接返回。>1,否則就報(bào)錯(cuò)。0返回null

          • CachingExecutor的query方法

            • BaseExecutor的query方法

              • BaseExecutor的queryFromDatabase方法

                • BaseExecutor的doQuery方法

                  • 通過SimpleExecutor中去調(diào)用JDBC的execute()

    • 查詢集合

      • DefaultSqlSession的selectList方法,得到結(jié)果后,直接返回

        • CachingExecutor的query方法

          • BaseExecutor的query方法

            • BaseExecutor的queryFromDatabase方法

              • BaseExecutor的doQuery方法

                • 通過SimpleExecutor中去調(diào)用JDBC的execute()

    2、增刪改方法

    • 修改

      • DefaultSqlSession的update方法

        • CachingExecutor的update方法:會(huì)清空緩存操作

          • BaseExecutor的doUpdate方法

            • 通過SimpleExecutor中去調(diào)用JDBC的execute()

    • 增加、刪除

      • 先調(diào)用DefaultSqlSession的insert方法或者delete方法

        • 接下來就會(huì)執(zhí)行DefaultSqlSession的update方法

    十六、面試題

    1、Mybatis支持延遲加載嗎?

    2、#{}和${}的區(qū)別

    3、Mybatis應(yīng)用到的設(shè)計(jì)模式

    • 構(gòu)建者模式

    • 工廠模式

    • 代理模式

    4、Mybatis的Mapper接口是否支持方法重載

    • 不支持

      • mapper接口的方法名就是mapper映射文件的statementId,是用來獲取執(zhí)行SQL的唯一標(biāo)識(shí)

    5、Mybatis的Mapper映射文件的標(biāo)簽,你知道哪些?

    • 除之前講的之外

      • sql:抽取的SQL片段

      • include:引用抽取的SQL片段

    <!-- List<Employee> findByIds(List<Integer> ids); --><select id="findByIds" parameterType="list" resultType="com.qf.java2107.pojo.Employee"><include refid="BaseSelect"></include><where><if test="list != null and list.size() > 0"><foreach collection="list" item="id" separator="," open="id IN (" close=")">#{id}</foreach></if></where></select><sql id="BaseSelect">SELECT<include refid="BaseColumn"></include>FROM t_employee</sql><sql id="BaseColumn">id,emp_name,gender,birthday,hire_date,salary,address,dept_id</sql>

    總結(jié)

    以上是生活随笔為你收集整理的【MyBatis】基础全网最全,看这篇就够了的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。