MyBatis筆記(三)

linzeliang發表於2021-04-12

1. ResultMap

查詢結果為null:要解決屬性和欄位名不一致的問題

我們先來看下步驟:

  1. 資料庫中的欄位名

    image-20210411110417116

  2. Java中的實體類

    public class User {
     
        private int id;  //id
        private String name;   //姓名
        private String password;   //密碼和資料庫不一樣!
        
        //構造
        //set/get
        //toString()
    }
    
  3. mapper介面方法

    //根據id查詢使用者
    User selectUserById(int id);
    
  4. mapper配置檔案

    <select id="selectUserById" resultType="user">
        select * from user where id = #{id}
    </select>
    
  • 這樣子我們得到的結果是password為空,MyBatis會根據這些查詢的列名(會將列名自動轉化為小寫,資料庫不區分大小寫),去對應的實體類中查詢相應列名的set方法設值,由於找不到setPwd,所以password返回null(自動對映)

  • 解決方法:

    1. 為列名指定別名,別名和Java實體類的屬性名一致

      <select id="selectUserById" resultType="User">
          select id , name , pwd as password from user where id = #{id}
      </select>
      
    2. 使用結果集對映(推薦)

      <resultMap id="UserMap" type="User">
          <!-- id為主鍵 -->
          <id column="id" property="id"/>
          <!-- column是資料庫表的列名 , property是對應實體類的屬性名 -->
          <result column="name" property="name"/>
          <result column="pwd" property="password"/>
      </resultMap>
       
      <select id="selectUserById" resultMap="UserMap">
          select id , name , pwd from user where id = #{id}
      </select>
      

自動對映:

  • resultMap 元素是 MyBatis 中最重要最強大的元素。它可以讓你從 90% 的 JDBC ResultSets 資料提取程式碼中解放出來

  • 實際上,在為一些比如連線的複雜語句編寫對映程式碼的時候,一份 resultMap 能夠代替實現同等功能的長達數千行的程式碼

  • ResultMap 的設計思想是,對於簡單的語句根本不需要配置顯式的結果對映,而對於複雜一點的語句只需要描述它們的關係就行了

    <select id="selectUserById" resultType="map">
    select id , name , pwd
        from user
        where id = #{id}
    </select>
    

手動對映:

  • 返回值型別為resultMap

    <select id="selectUserById" resultMap="UserMap">
        select id , name , pwd from user where id = #{id}
    </select>
    
  • 編寫resultMap,實現手動對映

    <resultMap id="UserMap" type="User">
        <!-- id為主鍵 -->
        <id column="id" property="id"/>
        <!-- column是資料庫表的列名 , property是對應實體類的屬性名 -->
        <result column="name" property="name"/>
        <result column="pwd" property="password"/>
    </resultMap>
    
  • 但是在資料庫中,存在一對多、多對一的情況,我們之後會使用到一些高階的結果集對映,association,collection等

2. 日誌工廠

2.1 概念

Mybatis內建的日誌工廠提供日誌功能,具體的日誌實現有以下幾種工具:

  • SLF4J
  • Apache Commons Logging
  • Log4j2
  • Log4j
  • JDK logging
  • 具體選擇哪個日誌實現工具由MyBatis的內建日誌工廠確定。它會使用最先找到的(按上文列舉的順序查詢)。如果一個都未找到,日誌功能就會被禁用

標準的日誌實現:

  • 指定 MyBatis 應該使用哪個日誌記錄實現。如果此設定不存在,則會自動發現日誌記錄實現

    <settings>
            <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    

2.2 Log4j

關於Log4j的簡介:

  • Log4j是Apache的一個開源專案
  • 通過使用Log4j,我們可以控制日誌資訊輸送的目的地:控制檯,文字,GUI元件等
  • 我們也可以控制每一條日誌的輸出格式
  • 通過定義每一條日誌資訊的級別,我們能夠更加細緻地控制日誌的生成過程。最令人感興趣的就是,這些可以通過一個配置檔案來靈活地進行配置,而不需要修改應用的程式碼

使用步驟:

  1. 導包

    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    
  2. 配置檔案的編寫

    #將等級為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
    
  3. setting設定日誌的實現

    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>
    
  4. 在程式中使用Log4j進行輸出

    //注意導包:org.apache.log4j.Logger
    static Logger logger = Logger.getLogger(MyTest.class);
     
    @Test
    public void selectUser() {
        logger.info("info:進入selectUser方法");
        logger.debug("debug:進入selectUser方法");
        logger.error("error: 進入selectUser方法");
        SqlSession session = MybatisUtils.getSession();
        UserMapper mapper = session.getMapper(UserMapper.class);
        List<User> users = mapper.selectUser();
        for (User user: users){
            System.out.println(user);
        }
        session.close();
    }
    
  5. 進行測試

3. 分頁

3.1 limit實現分頁

為什麼要使用分頁?

  • 在學習mybatis等持久層框架的時候,會經常對資料進行增刪改查操作,使用最多的是對資料庫進行查詢操作,如果查詢大量資料的時候,我們往往使用分頁進行查詢,也就是每次處理小部分資料,這樣對資料庫壓力就在可控範圍內

使用Limit實現分頁:

#語法
SELECT * FROM table LIMIT stratIndex,pageSize
 
SELECT * FROM table LIMIT 5,10; // 檢索記錄行 6-15  
 
#為了檢索從某一個偏移量到記錄集的結束所有的記錄行,可以指定第二個引數為 -1:   
SELECT * FROM table LIMIT 95,-1; // 檢索記錄行 96-last.  
 
#如果只給定一個引數,它表示返回最大的記錄行數目:   
SELECT * FROM table LIMIT 5; //檢索前 5 個記錄行  
 
#換句話說,LIMIT n 等價於 LIMIT 0,n。 

步驟:

  1. 修改Mapper配置檔案

    <select id="selectUser" parameterType="map" resultType="user">
        select * from user limit #{startIndex}, #{pageSize}
    </select>
    
  2. 修改Mapper介面,引數為map

    //選擇全部使用者實現分頁
    List<User> selectUser(Map<String,Integer> map);
    
  3. 進行測試(推斷:起始位置 = (當前頁面 - 1) * 頁面大小)

    //分頁查詢 , 兩個引數startIndex , pageSize
    @Test
    public void testSelectUser() {
        SqlSession session = MybatisUtils.getSession();
        UserMapper mapper = session.getMapper(UserMapper.class);
    
        int currentPage = 1;  //第幾頁
        int pageSize = 2;  //每頁顯示幾個
        Map<String,Integer> map = new HashMap<String,Integer>();
        map.put("startIndex",(currentPage-1)*pageSize);
        map.put("pageSize",pageSize);
    
        List<User> users = mapper.selectUser(map);
    
        for (User user: users){
            System.out.println(user);
        }
    
        session.close();
    }
    

3.2 RowBounds分頁

我們除了使用Limit在SQL層面實現分頁,也可以使用RowBounds在Java程式碼層面實現分頁,當然此種方式作為了解即可,使用步驟如下:

  1. 新增Mapper介面方法

    //選擇全部使用者RowBounds實現分頁
    List<User> getUserByRowBounds();
    
  2. 邊界Mapper配置檔案

    <select id="getUserByRowBounds" resultType="user">
        select * from user
    </select>
    
  3. 進行測試(需要用到RowBonds類)

    @Test
    public void testUserByRowBounds() {
        SqlSession session = MybatisUtils.getSession();
     
        // 頁數
        int currentPage = 2;
        // 每頁記錄數
        int pageSize = 2;
        RowBounds rowBounds = new RowBounds((currentPage - 1) * pageSize, pageSize);
     
        //通過session.xxx方法進行傳遞rowBounds,(此種方式現在已經不推薦使用了)
        List<User> users = session.selectList("top.linzelaing.mapper.UserMapper.getUserByRowBounds", null, rowBounds);
     
        for (User user: users){
            System.out.println(user);
        }
        session.close();
    }
    
    • 這種方法其實也就是先把資料全部查詢出來,然後再篩選,這樣子會導致伺服器的壓力增大,不推薦使用

3.3 PageHelper實現分頁

相關文章