Mybatis筆記-詳細手寫!


鏈接【 https://github.com/Davis-Samuel/Mybatis-order

1.第一個Mybatis程序

第一步:項目:Mybatyis(刪除src),模塊:mybatis-01

  • 創建Mybatis的maven項目(父項目要把src刪掉) 父pom.xml導包 和 子maven項目,不用導包

  • 在父,子pom.xml里都需要加入一下代碼

  • <!--依賴如下-->
    <dependencies>
    
        <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.16</version>
        </dependency>
        <!--
         https://mvnrepository.com/artifact/org.mybatis/mybatis
        -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.3</version>
        </dependency>
    
        <!--  https://mvnrepository.com/artifact/junit/junit  -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    
    </dependencies>         
    
    
    <!--    所有的maven項目都需要加進去這個文件,在父,子pom.xml里都需要加入一下代碼   -->   
    <!--在build中配置resources,來防止我們資源導出失敗的問題-->
        <build>
            <resources>
    
                <resource>
                    <directory>src/main/resources</directory>
                    <includes>
                        <include>**/*.properties</include>
                        <include>**/*.xml</include>
                    </includes>
                    <filtering>true</filtering>
                </resource>
    
                <resource>
                    <directory>src/main/java</directory>
                    <includes>
                        <include>**/*.properties</include>
                        <include>**/*.xml</include>
                    </includes>
                    <filtering>true</filtering>
                </resource>
    
            </resources>
        </build>
    

第二步

  • 根據
  • 編寫resources資源文件里的mybatis-config.xml核心配置文件

  • <?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核心配置文件 -->
    
    <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?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai"/>
                    <property name="username" value="root"/>
                    <property name="password" value="3105311"/>
                </dataSource>
            </environment>
        </environments>
        
        <!--每一個Mapper.xml都需要在mybatis-config.xml核心配置文件中注冊-->
        <mappers>
            <mapper resource="com/it/Dao/UserMapper.xml"/>
        </mappers>
        
    </configuration>
    

第三步:

  • 在java下創建一個com.it.utils的工具包,根據文檔寫號工具類

  • package com.it.utils;
    
    //通過 sqlSessionFactory →→→→拿到→→→→ SqlSession
    
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.jdbc.SQL;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    public class MybaticUtils {
        private static SqlSessionFactory sqlSessionFactory;
    //    使用Mabatis的第一步,獲取sqlSessionFactory對象
        static {
            try {
                String resource = "mybatis-config.xml";
                InputStream inputStream = Resources.getResourceAsStream(resource);
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    //    既然有了 SqlSessionFactory,顧名思義,我們就可以從中獲得 SqlSession 的實例了。
    //     SqlSession 完全包含了面向數據庫執行 org.apache.ibatis.jdbc.SQL 命令所需的所有方法。你可以通過 SqlSession 實例來直接執行已映射的 SQL 語句。
        public static SqlSession getSqlSession() {
    //        SqlSession sqlSession = //sqlSessionFactory.openSession();
    //        return sqlSession;
            return sqlSessionFactory.openSession();
        }
    }
    

第四步:

  • 創建com.it.pojo包,編寫數據庫表的關系映射(例如:user表對應user類)

  • package com.it.pojo;
    
    public class User {
        private int id;
        private String name;
        private String pwd;
    
        public User() {
        }
    
        public User(int id, String name, String pwd) {
            this.id = id;
            this.name = name;
            this.pwd = pwd;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPwd() {
            return pwd;
        }
    
        public void setPwd(String pwd) {
            this.pwd = pwd;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", pwd='" + pwd + '\'' +
                    '}';
        }
    }
    
    

第五步:

  • 創建com.it.Dao包,編寫UserMapper接口(填寫增刪改查)

  • package com.it.Dao;
    
    import com.it.pojo.User;
    
    import java.util.List;
    
    public interface UserMapper {
        List<User> getUserList();
    }
    
    

第六步:

  • 在com.it.Dao包,中創建UserMapper.xml配置文件(Dao=Mapper)。(由原來的UserDaoImpl.java實現類 轉換 為UserMapper.xml配置文件)

  • <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <!--namespace 綁定一對應的Dao/Mapper接口 -->
    <mapper namespace="com.it.Dao.UserMapper">
    
    <!--select查詢 id就是UserDao接口里面的方法的名字 resultType/Map是返回一個/多個結果集
    路徑就寫表的映射的路徑-->
     <select id="getUserList" resultType="com.it.pojo.User">
      select * from mybatis.user;
     </select>
    </mapper>
    

第七步

  • 編寫測試類

  • Junit測試類代碼

    package com.it.Dao;
    
    //test的路徑盡量要跟要測試的類的路徑匹配
    
    import com.it.pojo.User;
    import com.it.utils.MybatisUtils;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import java.util.List;
    
    public class UserDaoTest {
        @Test
        public void test(){
    //        第一步獲取SqlSession對象
            SqlSession sqlSession = MybatisUtils.getSqlSession();
    //        執行sql:方法一
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            List<User> userList = mapper.getUserList();
            for (User user : userList) {
                System.out.println(user);
            }
    //        關閉sqlSession
            sqlSession.close();
        }
    }
    
    
  • 錯誤一:

    org.apache.ibatis.binding.BindingException: Type interface com.it.Dao.UserMapper is not known to the MapperRegistry.

    <!--每一個Mapper.xml都需要在mybatis-config.xml核心配置文件中注冊-->**


    **

  • 錯誤二:

    The error may exist in org/mybatis/example/BlogMapper.xml

    Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration.

    Cause: java.io.IOException: Could not find resource org/mybatis/example/BlogMapper.xml

       <!--    所有的maven項目都需要加進去這個文件,在父,子pom.xml里都需要加入一下代碼   -->   
    <!--在build中配置resources,來防止我們資源導出失敗的問題-->
        <build>
            <resources>
    
                <resource>
                    <directory>src/main/resources</directory>
                    <includes>
                        <include>**/*.properties</include>
                        <include>**/*.xml</include>
                    </includes>
                    <filtering>true</filtering>
                </resource>
    
                <resource>
                    <directory>src/main/java</directory>
                    <includes>
                        <include>**/*.properties</include>
                        <include>**/*.xml</include>
                    </includes>
                    <filtering>true</filtering>
                </resource>
    
            </resources>
        </build>
    
  • 錯誤三:

  • 錯誤四:value="com.mysql.cj.jdbc.Driver" 要有 cj

  • 錯誤五:時區設置。

    1. 進入命令窗口(Win + R),連接數據庫 mysql -hlocalhost -uroot -p,回車,輸入密碼,回車
    2. 繼續輸入 show variables like'%time_zone'; (注意不要漏掉后面的分號),顯示 SYSTEM 就是沒有設置時區啦。
    3. 輸入set global time_zone = '+8:00'; 注意不要漏掉后面的分號)

2.Mybatis-CRUD

增刪改must提交事務,模塊mybatis-02

1.namespace

  • namespace中的名要和UserMapper.xml的接口一致

2.Select

  • 此時表格映射(pojo),工具類(utiles),resources-mybatis-config.xml(配置文件)都已經建立好了。只需要改接口和接口實現.xml和測試類就可以了。

  • 帶參數的查詢:根據id查詢用戶

    1.接口(UserMapper):

    User getUserById(int id);
    

    2.接口實現.xml(UserMapper.xml):

    id:接口里的方法名;resultType:返回值類型是User,要寫權限路徑;parameterType:要傳入的參數的類型;where id = #{id}:要傳入的參數,書寫格式

    <select id="getUserById" resultType="com.it.pojo.User" parameterType="int">
            select * from mybatis.user where id = #{id}
    </select>
    

    3.測試:

    第一步和最后一步不變,只改中間即可

        @Test
        public void getUserById(){
            //        第一步獲取SqlSession對象
            SqlSession sqlSession = MybatisUtils.getSqlSession();
    
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            User user = mapper.getUserById(1);
            System.out.println(user);
    
            //        最后一步關閉sqlSession
            sqlSession.close();
    

3.Insert

  1. 接口:

  2. //    insert一個用戶
        int addUser(User user);
    
  3. 接口實現.xml(UserMapper.xml):

  4. <!--    對象中的屬性可以直接取出來 -->
    <insert id="addUser" parameterType="com.it.pojo.User">
        insert into mybatis.user(id,name,pwd) values (#{id},#{name},#{pwd})
    </insert>
    
  5. 測試:

  6. @Test
       public void addUser(){
           //        第一步獲取SqlSession對象
           SqlSession sqlSession = MybatisUtils.getSqlSession();
      
           UserMapper mapper = sqlSession.getMapper(UserMapper.class);
           int user = mapper.addUser(new User(4, "wc", "444"));
           if (user>0){
               System.out.println("insert success !");
           }
      
           //增刪改都需要提交事務 !!!
           sqlSession.commit();
           
           //        最后一步關閉sqlSession
           sqlSession.close();
       }
    

4.Update

  1. 接口:

  2. //    修改用戶
        int updateUser(User user);
    
  3. 接口實現.xml(UserMapper.xml):

  4. <update id="updateUser" parameterType="com.it.pojo.User">
            update mybatis.user set name = #{name},pwd =  #{pwd} where id = #{id} ;
    </update>
    
  5. 測試:

  6. @Test
        public void updateUser(){
            //        第一步獲取SqlSession對象
            SqlSession sqlSession = MybatisUtils.getSqlSession();
    
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            int user = mapper.updateUser(new User(4, "haha", "123123"));
            if (user>0){
                System.out.println("insert success !");
            }
    
            //增刪改都需要提交事務 !!!
            sqlSession.commit();
    
            //        最后一步關閉sqlSession
            sqlSession.close();
        }
    

5.Delete

  1. 接口:

  2. //    刪除用戶
        int deleteUser(int id);
    
  3. 接口實現.xml(UserMapper.xml):

  4. <delete id="deleteUser" parameterType="int">
          delete from mybatis.user where id = #{id}
      </delete>
    
  5. 測試:

  6. @Test
        public void deleteUser(){
            //        第一步獲取SqlSession對象
            SqlSession sqlSession = MybatisUtils.getSqlSession();
    
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            int user = mapper.deleteUser(4);
            if (user>0){
                System.out.println("insert success !");
            }
    
            //增刪改都需要提交事務 !!!
            sqlSession.commit();
    
            //        最后一步關閉sqlSession
            sqlSession.close();
        }
    

6.萬能的Map

  1. 例子:使用update,只修改pwd

  2. 接口:

  3. //    萬能的Map,當數據或者屬性很多的時候,可以選擇性的單獨改變密碼或者用戶名等等。
        int updateUserByMap(Map<String,Object> map);
    
  4. 接口實現.xml(UserMapper.xml):

  5. <!--    利用Map進行的update,只修改pwd。如果是User對象的話則所有的屬性都需要寫入。使用Map可以寫你需要修改的-->
        <update id="updateUserByMap" parameterType="map">
            update mybatis.user set pwd = #{userpwd} where id = #{userid} ;
        </update>
    
  6. 測試:

  7. @Test
       public void updateUserByMap(){
           //        第一步獲取SqlSession對象
           SqlSession sqlSession = MybatisUtils.getSqlSession();
           UserMapper mapper = sqlSession.getMapper(UserMapper.class);
      
           Map<String,Object> map = new HashMap<String,Object>();
           map.put("userid",4);
           map.put("userpwd","789798789798797");
           int user = mapper.updateUserByMap(map);
           if (user>0){
               System.out.println("insert success !");
           }
           //增刪改都需要提交事務 !!!
           sqlSession.commit();
      
           //        最后一步關閉sqlSession
           sqlSession.close();
       }
    

7.模糊查詢

  1. 例子:使用List

  2. 接口:

  3. //  模糊查詢
        List<User> getUserListByLike(String like);
    
  4. 接口實現.xml(UserMapper.xml):

  5. <!--    模糊查詢-->
        <select id="getUserListByLike" resultType="com.it.pojo.User">
            select * from mybatis.user where name like #{like} ;
        </select>
    
  6. 測試:

  7. //    模糊查詢
        @Test
        public void getUserListByLike(){
            //        第一步獲取SqlSession對象
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            List<User> userListByLike = mapper.getUserListByLike("%w%");
            for (User user : userListByLike) {
                System.out.println(user);
            }
            //        最后一步關閉sqlSession
            sqlSession.close();
        }
    

3.配置解析

模塊mybatis-02

1.核心配置文件

2.environments-環境配置

  • MyBatis 可以配置成適應多種環境,不過要記住:盡管可以配置多個環境,但每個 SqlSessionFactory 實例只能選擇一種環境。
  • 可以設置多套運行環境,但只能同時使用一套。Mybatis默認的事務管理是JDBC(當然不止一種事務管理),連接池:POOLED。

3.屬性

  • 我們可以通過properties屬性來實現引用配置文件【db.properties】

4.開始改造,模塊mybatis-02

1.創建db.properties配置文件,.將(db.properties)配置文件引入(mybatis-config.xml)核心配置文件中

  • 在resources文件夾中創建新文件:db.properties

  • driver=com.mysql.cj.jdbc.Driver
    url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai
    username=root
    password=3105311
    
  • 標簽寫在(mybatis-config.xml)核心配置文件的第一位。並修改核心配置文件中的driver,url...的value。

    <?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核心配置文件 -->
    <configuration>
    
            
    <!--    引入外部(db.properties)配置文件-->
        <properties resource="db.properties"/>
    
        
    <!--    環境 1 -->
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    
                    
                    <property name="driver" value="${driver}"/>
                    <property name="url" value="${url}"/>
                    <property name="username" value="${username}"/>
                    <property name="password" value="${password}"/>
                    
                    
                </dataSource>
            </environment>
        </environments>
    
    <!--每一個Mapper.xml都需要在mybatis-config.xml核心配置文件中注冊-->
        <mappers>
            <mapper resource="com/it/Dao/UserMapper.xml"/>
        </mappers>
    </configuration>
    

2.typeAliases(類型別名)

  • 在" mybatis-config.xml "中編寫別名,在 "引入外部(db.properties)配置文件" 的下方編寫別名。

  • mybatis-config.xml代碼:

  • <?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核心配置文件 -->
    <configuration>
    <!--    引入外部(db.properties)配置文件-->
        <properties resource="db.properties"/>
    
        
    <!--    起別名方法一:使用於實體類少的情況。目的,編寫接口xml的sql語句時,type寫的簡單-->
        <typeAliases>
            <typeAlias type="com.it.pojo.User" alias="user"/>
        </typeAliases>
        
    <!--    起別名方法二:使用於實體類多的情況
            意思: com.it.pojo.User的別名默認就是pojo包中User的小寫類名。
            在利用方法二的情況下:如果在User類加入注解" @Alias("hellow") ",就能使用注解中的別名
        <typeAliases>
            <package name="com.it.pojo.User"/>
        </typeAliases>
    -->
    
    
    <!--    環境 1 -->
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="${driver}"/>
                    <property name="url" value="${url}"/>
                    <property name="username" value="${username}"/>
                    <property name="password" value="${password}"/>
                </dataSource>
            </environment>
        </environments>
    
    <!--每一個Mapper.xml都需要在mybatis-config.xml核心配置文件中注冊-->
        <mappers>
            <mapper resource="com/it/Dao/UserMapper.xml"/>
        </mappers>
    
    </configuration>
    
  • 接口實現xml代碼:

  • <?xml version="1.0" encoding="UTF-8" ?>
            <!DOCTYPE mapper
                    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
            <!--namespace 綁定一對應的Dao/Mapper接口 -->
            <!--namespace中的名要和UserMapper.xml的接口一致-->
    <mapper namespace="com.it.Dao.UserMapper">
    
        <!--select查詢 id就是UserDao接口里面的方法的名字 resultType/Map是返回一個/多個結果集
        路徑就寫表的映射的路徑-->
        <select id="getUserList" resultType="user">
           select * from mybatis.user;
          </select>
    
        <select id="getUserById" resultType="user" parameterType="int">
                select * from mybatis.user where id = #{id}
            </select>
    
        <!--    對象中的屬性可以直接取出來 -->
        <insert id="addUser" parameterType="user">
            insert into mybatis.user(id,name,pwd) values (#{id},#{name},#{pwd})
        </insert>
    
        <update id="updateUser" parameterType="user">
            update mybatis.user set name = #{name},pwd = #{pwd} where id = #{id}
        </update>
    
        <delete id="deleteUser" parameterType="int">
            delete from mybatis.user where id = #{id}
        </delete>
    
    
    </mapper>
    

3.設置(settings)

  • 目前需要記住的(都在mybatis文檔中)

  • image-20200209145944601

  • image-20200209145912295

  • <settings>
      <setting name="cacheEnabled" value="true"/>
      <setting name="lazyLoadingEnabled" value="true"/>
      <setting name="multipleResultSetsEnabled" value="true"/>
      <setting name="useColumnLabel" value="true"/>
      <setting name="useGeneratedKeys" value="false"/>
      <setting name="autoMappingBehavior" value="PARTIAL"/>
      <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
      <setting name="defaultExecutorType" value="SIMPLE"/>
      <setting name="defaultStatementTimeout" value="25"/>
      <setting name="defaultFetchSize" value="100"/>
      <setting name="safeRowBoundsEnabled" value="false"/>
      <setting name="mapUnderscoreToCamelCase" value="false"/>
      <setting name="localCacheScope" value="SESSION"/>
      <setting name="jdbcTypeForNull" value="OTHER"/>
      <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
    </settings>
    

4.其他配置

  • typeHandlers(類型處理器)
  • objectFactory(對象工廠)
  • plugins(插件)

5.映射器(mappers)

  • 采用mybatis文檔。
  • 設置時,接口和接口.xml的名字要一致。

6.生命周期和作用域

  • 參考mybatis文件

4.ResultMap結果集映射

解決屬性名和字段名不一致的問題

模塊mybatis-03

  • pojo代碼:

  • package com.it.pojo;
    public class User {
        private int id;
        private String name;
    
    //    此時屬性名和數據庫表中的字段名字不相同,結果就是查不出pwd的結果
    //    原因:sql=select name,id,pwd from user。
    //    數據庫表中名為pwd而映射表中是password
        
        private String password;
    
        public User() {
        }
    
        public User(int id, String name, String password) {
            this.id = id;
            this.name = name;
            this.password = password;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getpassword() {
            return password;
        }
    
        public void setpsaaword(String password) {
            this.password = password;
        }
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", pwd='" + password + '\'' +
                    '}';
        }
    }
    
  • 接口實現.xml代碼:

  • <?xml version="1.0" encoding="UTF-8" ?>
                <!DOCTYPE mapper
                        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
        <mapper namespace="com.it.Dao.UserMapper">
    
            
    <!--    id為你添加的resultMap標簽的名字。。type為要映射的類的名字-->
        <resultMap id="UserMap" type="User">
    <!--    column是列的意思,就是對應數據庫表中的列的名字,
            property是屬性的意思,也就是對應類的屬性名字。
    -->
            <result column="pwd" property="password"/>
            <result column="id" property="id"/>
            <result column="name" property="name"/>
        </resultMap>
    
            
    <!--添加一個resultMap標簽-->
        <select id="getUserById" resultMap="UserMap">
                select * from mybatis.user where id = #{id}
        </select>
    
    
        </mapper>
    

5.日志

1.日志工廠

模塊mybatis-04

  • 如果一個數據庫的操作,出現了異常,我們需要排錯,那么日志就是最好的幫手。
  • 根據mybatis文檔setting(設置)
  • LOG4J (掌握)
  • STDOUT_LOGGING(掌握)(默認的標准的日志工廠)

2.開始編寫

使用STDOUT_LOGGING默認日志工廠

  • 寫在"引入外部配置文件"的下面。

  • mybatis-config.xml代碼:

  • <?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核心配置文件 -->
    <configuration>
    
    <!--    引入外部(db.properties)配置文件-->
        <properties resource="db.properties"/>
    
    <!--    使用標准的默認的日志工廠-->
        <settings>
            <setting name="logImpl" value="STDOUT_LOGGING"/>
        </settings>
        
    
    <!--    起別名方法一:使用於實體類少的情況-->
        <typeAliases>
            <typeAlias type="com.it.pojo.User" alias="user"/>
        </typeAliases>
    
    <!--    起別名方法二:使用於實體類多的情況
            意思: com.it.pojo.User的別名默認就是pojo包中User的類名。
            在利用方法二的情況下:如果在User類加入注解" @Alias("hellow") ",就能使用注解中的別名
        <typeAliases>
            <package name="com.it.pojo.User"/>
        </typeAliases>
    -->
    
    
    <!--    環境 1 -->
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="${driver}"/>
                    <property name="url" value="${url}"/>
                    <property name="username" value="${username}"/>
                    <property name="password" value="${password}"/>
                </dataSource>
            </environment>
        </environments>
    
    <!--每一個Mapper.xml都需要在mybatis-config.xml核心配置文件中注冊-->
        <mappers>
            <mapper resource="com/it/Dao/UserMapper.xml"/>
        </mappers>
    
    </configuration>
    
  • 運行過后,看關鍵部分

使用LOG4J日志工廠

  • 導入LOG4J的jar:

    <!-- https://mvnrepository.com/artifact/log4j/log4j -->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    
  • 在resource文件夾中創建log4j.properties文件,內容:

    #將等級為DEBUG的日志信息輸出到console和file這兩個目的地,console和file的定義在下面的代碼
    log4j.rootLogger=DEBUG,console,file
    
    #控制台輸出的相關設置
    log4j.appender.console = org.apache.log4j.ConsoleAppender
    log4j.appender.console.Target = System.out
    log4j.appender.console.Threshold=DEBUG
    log4j.appender.console.layout = org.apache.log4j.PatternLayout
    log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
    
    #文件輸出的相關設置
    log4j.appender.file = org.apache.log4j.RollingFileAppender
    log4j.appender.file.File=./log/kuang.log
    log4j.appender.file.MaxFileSize=10mb
    log4j.appender.file.Threshold=DEBUG
    log4j.appender.file.layout=org.apache.log4j.PatternLayout
    log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
    
    #日志輸出級別
    log4j.logger.org.mybatis=DEBUG
    log4j.logger.java.sql=DEBUG
    log4j.logger.java.sql.Statement=DEBUG
    log4j.logger.java.sql.ResultSet=DEBUG
    log4j.logger.java.sql.PreparedStatement=DEBUG
    
  • 在mybatis-config.xml中加入配置,代碼:

    <?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核心配置文件 -->
    <configuration>
    
    <!--    引入外部(db.properties)配置文件-->
        <properties resource="db.properties"/>
    
    
    <!--    使用STDOUT_LOGGING標准的默認的日志工廠
        <settings>
            <setting name="logImpl" value="STDOUT_LOGGING"/>
        </settings>
    -->
    <!--    使用log4j日志工廠-->
        <settings>
            <setting name="logImpl" value="LOG4J"/>
        </settings>
    
    
    <!--    起別名方法一:使用於實體類少的情況-->
        <typeAliases>
            <typeAlias type="com.it.pojo.User" alias="user"/>
        </typeAliases>
    
    <!--    起別名方法二:使用於實體類多的情況
            意思: com.it.pojo.User的別名默認就是pojo包中User的類名。
            在利用方法二的情況下:如果在User類加入注解" @Alias("hellow") ",就能使用注解中的別名
        <typeAliases>
            <package name="com.it.pojo.User"/>
        </typeAliases>
    -->
    
    
    <!--    環境 1 -->
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="${driver}"/>
                    <property name="url" value="${url}"/>
                    <property name="username" value="${username}"/>
                    <property name="password" value="${password}"/>
                </dataSource>
            </environment>
        </environments>
    
    <!--每一個Mapper.xml都需要在mybatis-config.xml核心配置文件中注冊-->
        <mappers>
            <mapper resource="com/it/Dao/UserMapper.xml"/>
        </mappers>
    
    </configuration>
    

    簡單使用

  • 在測試類代碼:

    package Dao;
    
    //test的路徑盡量要跟要測試的類的路徑匹配
    import com.it.Dao.UserMapper;
    import com.it.pojo.User;
    import com.it.utils.MybatisUtils;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    import org.apache.log4j.Logger;
    
    
    public class UserDaoTest {
    
    //    log4j,獲取類字節碼
        static Logger logger = Logger.getLogger(UserDaoTest.class);
    
        @Test
        public void getUserById(){
            //        第一步獲取SqlSession對象
            SqlSession sqlSession = MybatisUtils.getSqlSession();
    
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            User user = mapper.getUserById(1);
            System.out.println(user);
    
            //        最后一步關閉sqlSession
            sqlSession.close();
    
        }
    
        @Test
        public void testLog4j(){
            //日志級別
        logger.info("info進入了:testLog4j");
        logger.debug("debug進入了:testLog4j");
        logger.error("error進入了:testLog4j");
        }
    }
    
    
  • 在當前文件目錄下生成一個log日志文件,運行testLog4j()方法時,將結果存在在log日志文件中

6.分頁

模塊mybatis-04

Limit分頁

  • 接口代碼:

    //    分頁
        List<User> getUserByLimit(Map<String,Integer> map);
    
  • 接口實現類.xml代碼:

    <?xml version="1.0" encoding="UTF-8" ?>
                <!DOCTYPE mapper
                        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
                <!--namespace 綁定一對應的Dao/Mapper接口 -->
                <!--namespace中的名要和UserMapper.xml的接口一致-->
        <mapper namespace="com.it.Dao.UserMapper">
    
    <!--    id為你添加的resultMap標簽的名字。。type為要映射的類的名字-->
        <resultMap id="UserMap" type="User">
    <!--    column是列的意思,就是對應數據庫表中的列的名字,
            property是屬性的意思,也就是對應類的屬性名字。
    -->
            <result column="pwd" property="password"/>
            <result column="id" property="id"/>
            <result column="name" property="name"/>
        </resultMap>
    
    
    <!--添加一個resultMap標簽-->
        <select id="getUserById" resultMap="UserMap">
                select * from mybatis.user where id = #{id}
        </select>
    <!--    分頁; 使用參數為Map時,parameterType一定要寫,Map的別名是'map',int的別名是 '_int' -->
        <select id="getUserByLimit" resultMap="UserMap" parameterType="map">
                select * from mybatis.user limit #{startIndex},#{pageSize}
        </select>
    
        </mapper>
    
  • 測試代碼:

    package Dao;
    
    //test的路徑盡量要跟要測試的類的路徑匹配
    import com.it.Dao.UserMapper;
    import com.it.pojo.User;
    import com.it.utils.MybatisUtils;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    import org.apache.log4j.Logger;
    
    import java.io.LineNumberReader;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    
    public class UserDaoTest {
    
    //    log4j,獲取類字節碼
        static Logger logger = Logger.getLogger(UserDaoTest.class);
    
        @Test
        public void getUserById(){
            //        第一步獲取SqlSession對象
            SqlSession sqlSession = MybatisUtils.getSqlSession();
    
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            User user = mapper.getUserById(1);
            System.out.println(user);
    
            //        最后一步關閉sqlSession
            sqlSession.close();
    
        }
        @Test
        public void testLog4j(){
    //        日志級別
        logger.info("info進入了:testLog4j");
        logger.debug("debug進入了:testLog4j");
        logger.error("error進入了:testLog4j");
        }
        @Test
        public void getUserByLimit(){
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    
            Map<String, Integer> map = new HashMap<String, Integer>();
            map.put("startIndex",1);
            map.put("pageSize",3);
    
            List<User> userList = userMapper.getUserByLimit(map);
            for (User user : userList) {
                System.out.println(user);
            }
            sqlSession.close();
        }
    }
    
    

RowBounds分頁(不推薦)

分頁插件

7.使用注解開發

模塊mybatis-05

在MybatisUtils.java中使用自動提交事務。只能適用於簡單的sql,不能多表聯查。

  • utils包中MybatisUtils.java代碼:

    public static SqlSession getSqlSession() {
    //        SqlSession sqlSession = sqlSessionFactory.openSession();
    //        return sqlSession;
    
    //        設置增刪改查自動提交事務,true。
            return sqlSessionFactory.openSession(true);
        }
    

增刪改查注解

  • 只需修改接口和測試類即可。

  • mybatis-config.xml中

    <!--每一個Mapper.xml都需要在mybatis-config.xml核心配置文件中注冊
    注解就用class。class的路徑和resource的路徑不同,class(.不加.xml),否則就寫resource(/加.xml)。
    Mapper.xml和接口在同一包下且必須同名,用clss。
    -->
        <mappers>
            <mapper class="com.it.Dao.UserMapper"/>
        </mappers>
    
  • 接口UserMapper代碼:

    package com.it.Dao;
    import com.it.pojo.User;
    import org.apache.ibatis.annotations.*;
    import java.util.List;
    import java.util.Map;
    public interface UserMapper {
    //    查詢全部用戶
        @Select("select * from user")
        List<User> getUserList();
        
    //    存在多個參數
        @Select("select * from user where id = #{id} and pwd = #{pwd}")
        User getUserByIdPwd(@Param("id")int id,@Param("pwd") String pwd);
        
    //    增:返回值類型只能用int不能用User,否則會報錯org.apache.ibatis.binding.BindingException: Mapper method 'com.it.Dao.UserMapper.addUser' has an unsupported return type: class com.it.pojo.User
        @Insert("insert into user(id,name,pwd) values (#{id},#{name},#{pwd})")
        int addUser(User user);
        
    //  改 @Param,只要有基本類型參數,有幾個參數就寫幾個@Param。
        @Update("update user set name=#{name} where id=#{id}")
        int updateUser(@Param("name") String name,@Param("id") int id);
    
    //    刪
        @Delete("delete from user where id = #{id}")
        int deleteUser(@Param("id") int id);
    }
    
  • 測試代碼:

    package Dao;
    
    //test的路徑盡量要跟要測試的類的路徑匹配
    
    import com.it.Dao.UserMapper;
    import com.it.pojo.User;
    import com.it.utils.MybatisUtils;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    public class UserDaoTest {
        @Test
        public void getUserList(){
            SqlSession sqlSession = MybatisUtils.getSqlSession();
                UserMapper mapper = sqlSession.getMapper(UserMapper.class);
                List<User> userList = mapper.getUserList();
                sqlSession.close();
        }
        @Test
        public void getUserByIdPwd(){
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            User userByIdPwd = mapper.getUserByIdPwd(1,"111");
            System.out.println(userByIdPwd);
            sqlSession.close();
        }
        @Test
        public void addUser(){
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            mapper.addUser(new User(7,"c5","253"));
            sqlSession.close();
        }
        @Test
        public void updateUser(){
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            mapper.updateUser("qqq",1);
            sqlSession.close();
        }
        @Test
        public void deleteUser(){
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            mapper.deleteUser(7);
            sqlSession.close();
        }
    }
    

IDEA中的Lombok

  • IDEA中:File→Settings→Plugins→搜索Lombok

  • 引入Lombok的maven依賴。

    <dependencies>
    
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.8</version>
            </dependency>
    
        </dependencies>
    
  • @注解加載加載單獨的一個變量上時,只生成這一個變量的方法

  • @Getter@Setter
    @FieldNameConstants
    @ToString
    @EqualsAndHashCode
    @AllArgsConstructor(所有參數構造)
    @NoArgsConstructor(無參構造)
    @Data(相當於添加了@Getter@Setter@ToString@NoArgsConstructor(無參構造))
    
  • pojo包數據庫表的映射類-User.java代碼:

    package com.it.pojo;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    
    @Data
    @AllArgsConstructor
    public class User {
        private int id;
        private String name;
        private String pwd;
    }
    
    

8.復雜查詢環境搭建

模塊mybatis-06

  • 添加2張新表和內容

  • CREATE TABLE `student` (
      `id` int(10) NOT NULL,
      `name` varchar(30) DEFAULT NULL,
      `tid` int(10) DEFAULT NULL,
      PRIMARY KEY (`id`),
      KEY `ftkid` (`tid`),
      CONSTRAINT `ftkid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    CREATE TABLE `teacher` (
      `id` int(10) NOT NULL,
      `name` varchar(30) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
  • 結構如下:

  • image-20200213152632620

  • 注:接口.xml文件放在了resource資源文件中,注意包結構是使用可以展開的包結構。使用Lombok注解。

  • src.Dao中數據為空,src.pojo中為空,resource.Dao中為空,Test為空,utils不變。

  • mybatis-config.xml代碼為:

    <?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核心配置文件 -->
    <configuration>
    
        <!--    引入外部(db.properties)配置文件-->
        <properties resource="db.properties"/>
    
    
        <!--    使用STDOUT_LOGGING標准的默認的日志工廠    -->
            <settings>
                <setting name="logImpl" value="STDOUT_LOGGING"/>
            </settings>
    
        <!--    使用log4j日志工廠(需要maven導入依賴)
        <settings>
            <setting name="logImpl" value="LOG4J"/>
        </settings>
    -->
    
    
        <!--    起別名方法一:使用於實體類少的情況。目的,編寫接口xml的sql語句時,type寫的簡單-->
        <typeAliases>
            <typeAlias type="com.it.pojo.Teacher" alias="Teacher"/>
            <typeAlias type="com.it.pojo.Student" alias="Student"/>
        </typeAliases>
    
        <!--    起別名方法二:使用於實體類多的情況
                意思: com.it.pojo.User的別名默認就是pojo包中User的類名。
                在利用方法二的情況下:如果在User類加入注解" @Alias("hellow") ",就能使用注解中的別名
            <typeAliases>
                <package name="com.it.pojo.User"/>
            </typeAliases>
        -->
    
    
        <!--    環境 1 -->
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="${driver}"/>
                    <property name="url" value="${url}"/>
                    <property name="username" value="${username}"/>
                    <property name="password" value="${password}"/>
                </dataSource>
            </environment>
        </environments>
    
        <!--每一個Mapper.xml都需要在mybatis-config.xml核心配置文件中注冊-->
    <!--    讀入2個接口路徑-->
        <mappers>
            <mapper class="com.it.Dao.StudentMapper"/>
            <mapper class="com.it.Dao.TeacherMapper"/>
        </mappers>
    
    </configuration>
    

9.多對一

模塊mybatis-06

通過多個學生查詢一個老師,通過學生查詢老師的信息

方法一(按查詢嵌套處理)

  • Dao中TeacherMapper接口為空,StudentMapper代碼為:

    package com.it.Dao;
    import com.it.pojo.Student;
    import java.util.List;
    public interface StudentMapper {
    
    //    多表聯查,查詢學生的所有信息以及老師的信息
        List<Student> getStudent();
    }
    
    
  • pojo中Teacher為空,Student代碼為:

    package com.it.pojo;
    import lombok.Data;
    @Data
    public class Student {
        private int id;
        private String name;
    //通過多個學生查老師。此處使用老師類型作為參數,意為返回一個老師對象。
        private Teacher tid;
    }
    
    
  • resources.com.it.Dao.TeacherMapper.xml為空,resources.com.it.Dao.StudentMapper.xml代碼為:

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <!--namespace 綁定一對應的Dao/Mapper接口 -->
    <!--namespace中的名要和UserMapper.xml的接口一致-->
    <mapper namespace="com.it.Dao.StudentMapper">
    
    <!--    1.查出學生信息 2.通過學生的tid查詢到老師的信息-->
    
    <!--    第一個id為方法名-->
        <select id="getStudent" resultMap="student→teacher">
            select * from student
        </select>
    
    <!--    id為select的resultMap的值,type是映射的類是名字-Student,,相當於select和resulMap連接了起來-->
        <resultMap id="student→teacher" type="Student">
            <result property="id" column="id"/>
            <result property="name" column="name"/>
    <!--    在Student.java中第三個變量類型是Teacher類型,是復雜類型,處理:將result換成,
            若是對象:association,若是集合:collection
            property對應javaType,column對應select
            javaType:給property一個類型
            select:表明colum要干什么,要select="getTeacher"
            select:接着連接下一個id="getTeacher"-->
            <association property="tid" column="tid" javaType="Teacher" select="getTeacher"/>
        </resultMap>
    
    <!--此時TeacherMapper接口沒方法,那就設一個getTeacher方法-->
        <select id="getTeacher" resultType="Teacher">
            select * from teacher where id = #{tid}
        </select>
    
    
    
    </mapper>
    

方法二(按結果嵌套處理)

  • 其他與方法一相同resources.com.it.Dao.TeacherMapper.xml為空,修改resources.com.it.Dao.StudentMapper.xml代碼為:

    <!--方法二:直接寫出完整sql。
        然后寫出resultMap,此時第三個屬性仍是復雜類型。
        在association只寫property對應javaType="Teacher"
        然后我們查詢老師的id和name,然后在association里面再編寫Teacher的property和columu-->
        <select id="getStudent2" resultMap="student→teacher2">
            select s.id sid,s.name,sname,t.name tname,t.id tid from student s,teacher t where s.tid = t.id
        </select>
    
        <resultMap id="student→teacher2" type="Student">
    <!-- 注意:查詢的就是一個表。此處的column(數據庫中的列),就變成了s.id的別名sid等-->
            <result property="id" column="sid"/>
            <result property="name" column="sname"/>
            <association property="tid" javaType="Teacher">
                <result property="name" column="tname"/>
                <result property="id" column="tid"/>
            </association>
        </resultMap>
    

10.一對多

模塊mybatis-07

通過一個老師查詢多個學生,通過老師查詢學生的信息

  • 接口StudentMapper為空,TeacherMapper代碼:

    package com.it.Dao;
    import com.it.pojo.Teacher;
    import org.apache.ibatis.annotations.Param;
    public interface TeacherMapper {
    //    獲取老師的信息以及老師下的所有學生
        Teacher getTeacher(@Param("id")int id);
    }
    
  • pojo.Student代碼:

    package com.it.pojo;
    
    import lombok.Data;
    
    @Data
    public class Student {
        private int id;
        private String name;
        private int tid;
    }
    
    
  • pojo.Teacher代碼:

    package com.it.pojo;
    import lombok.Data;
    import java.util.List;
    @Data
    public class Teacher {
        private int id;
        private String name;
    //    一個老師擁有多個學生
        private List<Student> students;
    }
    
  • 其他與方法一相同resources.com.it.Dao.StudentMapper.xml為空,修改resources.com.it.Dao.TeacherMapper.xml代碼為:

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <!--namespace 綁定一對應的Dao/Mapper接口 -->
    <!--namespace中的名要和UserMapper.xml的接口一致-->
    <mapper namespace="com.it.Dao.TeacherMapper">
    
        <select id="getTeacher" resultMap="teacher→student">
            select s.name sname,s.id sid,t.name tname,t.id tid from teacher t,student s where s.tid = t.id and t.id = #{id}
        </select>
    
        <resultMap id="teacher→student" type="Teacher">
            <result property="id" column="tid"/>
            <result property="name" column="tname"/>
    <!--        集合中泛型,使用ofType獲取。如果的對象的時候用javaType給定類型-->
        <collection property="students" ofType="Student">
            <result property="id" column="sid"/>
            <result property="name" column="sname"/>
            <result property="tid" column="sid"/>
        </collection>
    </resultMap>
    </mapper>
    

11.動態SQL

模塊mybatis-08(開啟自動提交事務)

小拓展

  • 在com.it.utils中加入IDUtils類,作為可以生成隨機id的類,代碼:

    package com.it.utils;
    import org.junit.jupiter.api.Test;
    import java.util.UUID;
    public class IDUtils {
        public static String getID(){
            return UUID.randomUUID().toString().replaceAll("-","...");
        }
        @Test
        public void test(){
            System.out.println(IDUtils.getID());
        }
    }
    
    
  • mapUnderscoreToCamelCase 自動駝峰命名規則(camel case)映射,即從經典數據庫列名 A_COLUMN 到經典 Java 屬性名 aColumn 的類似映射。
    代碼:

開始改造:(Where-IF,Where-choose-when-otherwise,Set-IF)

  • 接口代碼:

    package com.it.Dao;
    import com.it.pojo.Blog;
    import org.apache.ibatis.annotations.Insert;
    import java.util.List;
    import java.util.Map;
    public interface BlogMapper {
    //    插入語句
        int insertBlog(Blog blog);
    
    //    Where-IF語句,查詢blog。動態的根據插入的不同參數,進行不同的查詢
        List<Blog> queryBlogIF(Map map);
    
    //    Where-choose-when-otherwise語句,查詢blog。類似switch語句
        List<Blog> queryBlogChoose(Map map);
    
    //    set-if語句更新blog
        int updateBlog(Map map);
    
    }
    
    
  • 接口.xml代碼:

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <!--namespace 綁定一對應的Dao/Mapper接口 -->
    <!--namespace中的名要和UserMapper.xml的接口一致-->
    <mapper namespace="com.it.Dao.BlogMapper">
    <!--插入數據-->
        <insert id="insertBlog" parameterType="blog">
            insert into mybatis.blog(id,title,author,create_time,views) values (#{id},#{title},#{author},#{createTime},#{views})
        </insert>
    <!--Where-IF語句。有了where標簽,當只滿足title時,語句前面的and會被忽略-->
        <select id="queryBlogIF" parameterType="map" resultType="blog">
                select * from blog
                <where>
                <if test="id != null">
                --如果id !=null,就追加一個and id=#{id}
                    id = #{id}
                </if>
                <if test="title != null">
                    and title = #{title}
                </if>
                <if test="author != null">
                    and author = #{author}
                </if>
                <if test="create_time != null">
                    and create_time = #{create_time}
                </if>
                <if test="views != null">
                    and views = #{views}
                </if>
                </where>
            </select>
    <!--Where-choose-when-otherwise語句。當傳入的參數都不在when中存在時,就執行otherwise-->
        <select id="queryBlogChoose" parameterType="map" resultType="blog">
                select * from blog
            <where>
                <choose>
                    <when test="id != null">id = #{id}</when>
                    <when test="title != null">and title = #{title}</when>
                    <when test="author != null">and author = #{author}</when>
                    <when test="create_time != null">and create_time = #{create_time}</when>
                    <when test="views != null">and views = #{views}</when>
                    <otherwise>
                        1=1
                    </otherwise>
                </choose>
            </where>
        </select>
    <!--set-if語句更新Blog-->
        <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="create_time != null">create_time = #{create_time},</if>
                <if test="views != null">views = #{views}</if>
            </set>
            where id = #{id}
        </update>
    </mapper>
    
  • 測試代碼:

    package Dao;
    
    import com.it.Dao.BlogMapper;
    import com.it.pojo.Blog;
    import com.it.utils.IDUtils;
    import com.it.utils.MybatisUtils;
    import org.apache.ibatis.session.SqlSession;
    import org.junit.Test;
    
    import java.util.Date;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    public class MyTest {
        @Test //插入語句
       public void insert(){
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    
            Blog blog = new Blog();
    
            blog.setId(IDUtils.getID());
            blog.setTitle("Mybatis so easy");
            blog.setAuthor("Mr.1");
            blog.setCreateTime(new Date());
            blog.setViews(999);
            mapper.insertBlog(blog);
    
            blog.setId(IDUtils.getID());
            blog.setTitle("Spring so easy");
            mapper.insertBlog(blog);
    
            blog.setId(IDUtils.getID());
            blog.setTitle("Math so easy");
            mapper.insertBlog(blog);
    
            blog.setId(IDUtils.getID());
            blog.setTitle("Mysql so easy");
            mapper.insertBlog(blog);
    
            sqlSession.close();
        }
        @Test//Where-IF語句,查詢blog。動態的根據插入的不同參數,進行不同的查詢。可以同時滿足多個條件
         public void queryBlogIF(){
             SqlSession sqlSession = MybatisUtils.getSqlSession();
             BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    
             Map map = new HashMap();
             map.put("title","Mybatis so easy");
             map.put("views","888");
    
             List<Blog> blogs = mapper.queryBlogIF(map);
             for (Blog blog : blogs) {
                  System.out.println(blog);
             }
             sqlSession.close();
        }
        @Test//Where-choose-when-otherwise語句,查詢blog。類似switch語句。只能滿足最先的那個條件。
        public void queryBlogChoose(){
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    
            Map map = new HashMap();
            map.put("title","Mybatis so easy");
    
            mapper.queryBlogChoose(map);
            System.out.println(map);
            sqlSession.close();
        }
        @Test//    set-if語句更新Blog
        public void updateBlog(){
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    
            Map map = new HashMap();
            map.put("id","92036d82.bd3b.4a78.b602.9d3c5ec71a46");
            map.put("views",777);
            mapper.updateBlog(map);
            sqlSession.close();
        }
    }
    
    

SQL片段

  • 接口.xml代碼:

    <!--將每次都要編寫的IF語句提取出來,id隨便取-->
    <sql id = "sql-if">
    <if test="title != null">title = #{title},</if>
    <if test="author != null">author = #{author},</if>
    <if test="create_time != null">create_time = #{create_time},</if>
    <if test="views != null">views = #{views}</if>
    </sql>
        
    <select id="queryBlogIF" parameterType="map" resultType="blog">
       select * from blog
       <where>
    <!--引用提取出來的SQL片段SQL-->
           <include refid="sql-if"/>     
        </where>
    </select>
    

For each

  • 接口.xml代碼:

    <!--查詢where 1=1 and (id=0 or id=2 or id=3)用foreach-->
    <select id="queryBlogForEach" parameterType="map" resultType="blog">
        select * from blog
        <where>
    <!--類似集合的foreach循環。foreach標簽內容分別為:給定一個集合的名字,將取出的內容給定一個名字,開始是的樣子and (,結尾的樣子),分開分隔是or。id和#{id}對應-->
            <foreach clloection="list" item="id" open="and (" close=")" separator="or"> id = #{id} </foreach>
        </where>
    
  • 測試代碼(主要部分):

    //通過id查詢。將List集合存到Map里面,List里面都是id
    Map map = new HashMap();
    List<Integer> list = new ArraryList<Integer>();
    list.add(1);
    map.put(list);
    mapper.queryBlogForEach(map);
    

12.緩存

模塊mybatis-09

開啟自動提交日志

一級緩存

  • 一級緩存默認開啟,只在一次sqlSession中有效,也就是從getSqlSession()到close()的過程

  • 兩次查詢只執行了一次sql語句,次sql查詢被加入到緩存當中。

  • image-20200215005441929

  • 緩存失效的情況:

    查詢不同的東西,如不同的id
    增刪改語句就會可能改變sql的內容。因此,執行完增刪改之后,就會重新執行sql,刷新緩存。
    查詢不同的Mapper.xml
    手動清理緩存:sqlSession.clearCache();

二級緩存

步驟:

  • 開啟全局緩存,默認是開啟的,但是要主動聲明一下。在mybatis文檔是(setting配置)中。

    cacheEnabled 全局地開啟或關閉配置文件中的所有映射器已經配置的任何緩存。
    默認 true
  • pojo.User.java加@AllArgsConstructor注解並實現序列化:

    package com.it.pojo;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import java.io.Serializable;
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User implements Serializable {
        private int id;
        private String name;
        private String pwd;
    }
    
  • 在UserMapper.xml中配置緩存,代碼:

    <?xml version="1.0" encoding="UTF-8" ?>
                <!DOCTYPE mapper
                        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
                <!--namespace 綁定一對應的Dao/Mapper接口 -->
                <!--namespace中的名要和UserMapper.xml的接口一致-->
        <mapper namespace="com.it.Dao.UserMapper">
    
        
    <!--    配置二級緩存。以IO流為格式,每隔60s緩存一次,最多緩存512個,是否只讀,(此些配置完全可以不寫),pojo加@AllArgsConstructor注解並實現序列化-->
        <cache
                eviction="FIFO"
                flushInterval="60000"
                size="512"
                readOnly="true"/>
    
    
    <!--  useCache=false表示這條語句不進入緩存,true是進入緩存  -->
        <select id="quaryUserById" resultType="user" useCache="true">
            select * from mybatis.user where id = #{id}
        </select>
    
        </mapper>
    

查詢順序:

  • 先找二級緩存,再找一級緩存,如果都沒有,就去連接數據庫

自定義緩存(Ehcache)

步驟:

  • 導入依賴:

    <!-- https://mvnrepository.com/artifact/org.mybatis.caches/mybatis-ehcache -->
    <dependency>
        <groupId>org.mybatis.caches</groupId>
        <artifactId>mybatis-ehcache</artifactId>
        <version>1.1.0</version>
    </dependency>
    
  • 在接口實現Mapper.xml中:

    <cache type="org.mybatis.caches.encache.EhcacheCache"/>
    
  • 在resource中創建ehcache.xml文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
             updateCheck="false">
        
        <defaultCache
                eternal="false"
                maxElementsInMemory="10000"
                overflowToDisk="false"
                diskPersistent="false"
                timeToIdleSeconds="1800"
                timeToLiveSeconds="259200"
                memoryStoreEvictionPolicy="LRU"/>
     
        <cache
                name="cloud_user"
                eternal="false"
                maxElementsInMemory="5000"
                overflowToDisk="false"
                diskPersistent="false"
                timeToIdleSeconds="1800"
                timeToLiveSeconds="1800"
                memoryStoreEvictionPolicy="LRU"/>
        
        <!--
           diskStore:為緩存路徑,ehcache分為內存和磁盤兩級,此屬性定義磁盤的緩存位置。參數解釋如下:
           user.home – 用戶主目錄
           user.dir  – 用戶當前工作目錄
           java.io.tmpdir – 默認臨時文件路徑
         -->
        <diskStore path="java.io.tmpdir/Tmp_EhCache"/>
        <!--
           defaultCache:默認緩存策略,當ehcache找不到定義的緩存時,則使用這個緩存策略。只能定義一個。
         -->
        <!--
          name:緩存名稱。
          maxElementsInMemory:緩存最大數目
          maxElementsOnDisk:硬盤最大緩存個數。
          eternal:對象是否永久有效,一但設置了,timeout將不起作用。
          overflowToDisk:是否保存到磁盤,當系統當機時
          timeToIdleSeconds:設置對象在失效前的允許閑置時間(單位:秒)。僅當eternal=false對象不是永久有效時使用,可選屬性,默認值是0,也就是可閑置時間無窮大。
          timeToLiveSeconds:設置對象在失效前允許存活時間(單位:秒)。最大時間介於創建時間和失效時間之間。僅當eternal=false對象不是永久有效時使用,默認是0.,也就是對象存活時間無窮大。
          diskPersistent:是否緩存虛擬機重啟期數據 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
          diskSpoolBufferSizeMB:這個參數設置DiskStore(磁盤緩存)的緩存區大小。默認是30MB。每個Cache都應該有自己的一個緩沖區。
          diskExpiryThreadIntervalSeconds:磁盤失效線程運行時間間隔,默認是120秒。
          memoryStoreEvictionPolicy:當達到maxElementsInMemory限制時,Ehcache將會根據指定的策略去清理內存。默認策略是LRU(最近最少使用)。你可以設置為FIFO(先進先出)或是LFU(較少使用)。
          clearOnFlush:內存數量最大時是否清除。
          memoryStoreEvictionPolicy:可選策略有:LRU(最近最少使用,默認策略)、FIFO(先進先出)、LFU(最少訪問次數)。
          FIFO,first in first out,這個是大家最熟的,先進先出。
          LFU, Less Frequently Used,就是上面例子中使用的策略,直白一點就是講一直以來最少被使用的。如上面所講,緩存的元素有一個hit屬性,hit值最小的將會被清出緩存。
          LRU,Least Recently Used,最近最少使用的,緩存的元素有一個時間戳,當緩存容量滿了,而又需要騰出地方來緩存新的元素的時候,那么現有緩存元素中時間戳離當前時間最遠的元素將被清出緩存。
       -->
    </ehcache>
    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM