天天看點

MyBatis03:ResultMap及分頁

MyBatis03:ResultMap及分頁

查詢為null問題

要解決的問題:屬性名和字段名不一緻

環境:建立一個項目,将之前的項目拷貝過來

1、檢視之前的資料庫的字段名

2、Java中的實體類設計

public class User {

   private int id;  //id
   private String name;   //姓名
   private String password;   //密碼和資料庫不一樣!
   
   //構造
   //set/get
   //toString()
}      

3、接口

//根據id查詢使用者
User selectUserById(int id);      

4、mapper映射檔案

<select id="selectUserById" resultType="user">
  select * from user where id = #{id}
</select>      

5、測試

@Test
public void testSelectUserById() {
   SqlSession session = MybatisUtils.getSession();  //擷取SqlSession連接配接
   UserMapper mapper = session.getMapper(UserMapper.class);
   User user = mapper.selectUserById(1);
   System.out.println(user);
   session.close();
}      

結果:

  • User{id=1, name='狂神', password='null'}
  • 查詢出來發現 password 為空 . 說明出現了問題!

分析:

  • select * from user where id = #{id} 可以看做

    select  id,name,pwd  from user where id = #{id}

  • mybatis會根據這些查詢的列名(會将列名轉化為小寫,資料庫不區分大小寫) , 去對應的實體類中查找相應列名的set方法設值 , 由于找不到setPwd() , 是以password傳回null ; 【自動映射】
解決方案

方案一:為列名指定别名 , 别名和java實體類的屬性名一緻 .

<select id="selectUserById" resultType="User">
  select id , name , pwd as password 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>

<select id="selectUserById" resultMap="UserMap">
  select id , name , pwd from user where id = #{id}
</select>      
ResultMap

自動映射

  • resultMap

    元素是 MyBatis 中最重要最強大的元素。它可以讓你從 90% 的 JDBC

    ResultSets

    資料提取代碼中解放出來。
  • 實際上,在為一些比如連接配接的複雜語句編寫映射代碼的時候,一份

    resultMap

    能夠代替實作同等功能的長達數千行的代碼。
  • ResultMap 的設計思想是,對于簡單的語句根本不需要配置顯式的結果映射,而對于複雜一點的語句隻需要描述它們的關系就行了。

你已經見過簡單映射語句的示例了,但并沒有顯式指定

resultMap

。比如:

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

上述語句隻是簡單地将所有的列映射到

HashMap

的鍵上,這由

resultType

屬性指定。雖然在大部分情況下都夠用,但是 HashMap 不是一個很好的模型。你的程式更可能會使用 JavaBean 或 POJO(Plain Old Java Objects,普通老式 Java 對象)作為模型。

ResultMap

最優秀的地方在于,雖然你已經對它相當了解了,但是根本就不需要顯式地用到他們。

手動映射

1、傳回值類型為resultMap

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

2、編寫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這些,我們将在之後講解,今天你們需要把這些知識都消化掉才是最重要的!了解結果集映射的這個概念!

分頁的幾種方式

日志工廠

思考:我們在測試SQL的時候,要是能夠在控制台輸出 SQL 的話,是不是就能夠有更快的排錯效率?

如果一個 資料庫相關的操作出現了問題,我們可以根據輸出的SQL語句快速排查問題。

對于以往的開發過程,我們會經常使用到debug模式來調節,跟蹤我們的代碼執行過程。但是現在使用Mybatis是基于接口,配置檔案的源代碼執行過程。是以,我們必須選擇日志工具來作為我們開發,調節程式的工具。

Mybatis内置的日志工廠提供日志功能,具體的日志實作有以下幾種工具:

  • SLF4J
  • Apache Commons Logging
  • Log4j 2
  • Log4j
  • JDK logging

具體選擇哪個日志實作工具由MyBatis的内置日志工廠确定。它會使用最先找到的(按上文列舉的順序查找)。如果一個都未找到,日志功能就會被禁用。

标準日志實作

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

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

測試,可以看到控制台有大量的輸出!我們可以通過這些輸出來判斷程式到底哪裡出了Bug

簡介:

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

使用步驟:

1、導入log4j的包

<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、測試,看控制台輸出!

  • 使用Log4j 輸出日志
  • 可以看到還生成了一個日志的檔案 【需要修改file的日志級别】
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();
}      
RowBounds分頁

我們除了使用Limit在SQL層面實作分頁,也可以使用RowBounds在Java代碼層面實作分頁,當然此種方式作為了解即可。我們來看下如何實作的!

1、mapper接口

//選擇全部使用者RowBounds實作分頁
List<User> getUserByRowBounds();      

2、mapper檔案

<select id="getUserByRowBounds" resultType="user">
select * from user
</select>      

3、測試類

在這裡,我們需要使用RowBounds類

@Test
public void testUserByRowBounds() {
   SqlSession session = MybatisUtils.getSession();

   int currentPage = 2;  //第幾頁
   int pageSize = 2;  //每頁顯示幾個
   RowBounds rowBounds = new RowBounds((currentPage-1)*pageSize,pageSize);

   //通過session.**方法進行傳遞rowBounds,[此種方式現在已經不推薦使用了]
   List<User> users = session.selectList("com.kuang.mapper.UserMapper.getUserByRowBounds", null, rowBounds);

   for (User user: users){
       System.out.println(user);
  }
   session.close();
}      
PageHelper

了解即可,可以自己嘗試使用

官方文檔:https://pagehelper.github.io/

在MyBatisPlus中,我們也講解到了分頁實作,是以實作方式很多,看自己的了解和熟練程度進行掌握即可!

會了簡單的結果集映射,後面我們就可以實作一對多和多對一操作了