在前面幾篇文章的例子中也可以看到mybatis中輸入映射和輸出映射的身影,但是沒有系統的總結一下,這篇博客主要對這兩個東東做一個總結。我們知道mybatis中輸入映射和輸出映射可以是基本數據類型、hashmap或者pojo的包裝類型,這裡主要來總結一下pojo包裝類型的使用,因為這個在開發中比較常用 ...
在前面幾篇文章的例子中也可以看到mybatis中輸入映射和輸出映射的身影,但是沒有系統的總結一下,這篇博客主要對這兩個東東做一個總結。我們知道mybatis中輸入映射和輸出映射可以是基本數據類型、hashmap或者pojo的包裝類型,這裡主要來總結一下pojo包裝類型的使用,因為這個在開發中比較常用。
1、輸入映射
輸入映射,是在映射文件中通過parameterType指定輸入參數的類型,類型可以是簡單類型、hashmap、pojo的包裝類型。假設現在有個比較複雜的查詢需求:完成用戶信息的綜合查詢,需要傳入查詢條件很複雜(可能包括用戶信息、其它信息,比如商品、訂單的),那麼我們單純的傳入一個User就不行了,所以首先我們得根據查詢條件,自定義一個新的pojo,在這個pojo中包含所有的查詢條件。
1.1、定義包裝類型pojo
定義一個UserQueryVo類,將要查詢的條件包裝進去。這裡為了簡單起見,就不添加其他的查詢條件了,UserQueryVo中就包含一個User,假設複雜的查詢條件在User中都已經包含了。
package com.mybatis.entity; public class UserQueryVo { //在這裡添加所需要的查詢條件 //用戶查詢條件,這裡假設一個User就已經夠了 private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } //可以包裝其他的查詢條件,比如訂單、商品等 //...... }
1.2、配置UserMapper.xml文件
定義好了我們自己的pojo後,需要在UserMapper.xml映射文件中配置查詢的statement,如下:
<!-- 模擬包裝類型組合查詢 #{user.sex}:取出pojo包裝對象中性別值 ${user.username}:取出pojo對象中姓名值 --> <select id="findUserList" parameterType="com.mybatis.entity.UserQueryVo" resultType="com.mybatis.entity.User"> select * from t_user where sex = #{user.sex} and username like '%${user.username}%' </select>
我們看到,輸入的parameterType的值是我們自己定義的pojo,輸出的是User,當然這裡的User也可以換成另一個用戶自定義的pojo,包含用戶所需要的條件,都行,不僅僅局限為User。然後查詢條件使用OGNL表達式,取出UserQueryVo中User的相應屬性即可。
1.3、UserMapper.java類的代碼
package com.mybatis.mapper; import java.util.List; import com.mybatis.entity.User; import com.mybatis.entity.UserQueryVo; /** * 用戶管理mapper介面 * @author lixiaoxi * 2017-02-06 */ public interface UserMapper { //用戶信息綜合查詢 public List<User> findUserList(UserQueryVo userQueryVo); }
1.4、JUnit單元測試代碼
package com.mybatis.test; import java.io.InputStream; import java.util.Date; import java.util.List; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Before; import org.junit.Test; import com.mybatis.entity.User; import com.mybatis.entity.UserQueryVo; import com.mybatis.mapper.UserMapper; public class UserMapperTest { private SqlSessionFactory sqlSessionFactory; // 此方法是在執行@Test標註的方法之前執行 @Before public void setUp() throws Exception { String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); // 創建SqlSessionFcatory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } @Test public void testFindUserList() { SqlSession sqlSession = sqlSessionFactory.openSession(); //創建包裝對象,設置查詢條件 UserQueryVo userQueryVo = new UserQueryVo(); User user = new User(); user.setSex("1"); user.setUsername("小"); userQueryVo.setUser(user); // 創建UserMapper對象,mybatis自動生成mapper代理對象 UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User>list=mapper.findUserList(userQueryVo); System.out.println(list); sqlSession.commit(); sqlSession.close(); } }
2、輸出映射
2.1、resultType
使用resultType進行輸出映射,只有查詢出來的列名和pojo中的屬性名一致,該列才可以映射成功。如果查詢出來的列名和pojo中的屬性名全部不一致,沒有創建pojo對象。
只要查詢出來的列名和pojo中的屬性有一個一致,就會創建pojo對象。
2.1.1、輸出簡單類型
需求:用戶信息的綜合查詢列表,通過查詢總數才能實現分頁功能。
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命名空間,作用就是對sql進行分類化的管理,理解為sql隔離 註意:使用mapper代理開發時,namespace有特殊作用,namespace等於mapper介面地址 --> <mapper namespace="com.mybatis.mapper.UserMapper"> <!-- 用戶信息綜合查詢總數 parameterType:指定輸入類型,和findUserList一致。 resultType:輸出結果類型. --> <select id="findUserCount" parameterType="com.mybatis.entity.UserQueryVo" resultType="int"> select count(*) from t_user where sex=#{user.sex} and username like '%${user.username}%' </select> </mapper>
UserMapper.java的代碼:
public interface UserMapper { //用戶信息綜合查詢總數 public int findUserCount(UserQueryVo userQueryVo); }
JUnit測試代碼:
package com.mybatis.test; import java.io.InputStream; import java.util.Date; import java.util.List; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Before; import org.junit.Test; import com.mybatis.entity.User; import com.mybatis.entity.UserQueryVo; import com.mybatis.mapper.UserMapper; public class UserMapperTest { private SqlSessionFactory sqlSessionFactory; // 此方法是在執行@Test標註的方法之前執行 @Before public void setUp() throws Exception { String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); // 創建SqlSessionFcatory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } @Test public void findUserCountTest() { SqlSession sqlSession = sqlSessionFactory.openSession(); //創造查詢條件 UserQueryVo userQueryVo = new UserQueryVo(); User user = new User(); user.setSex("1"); user.setUsername("小"); userQueryVo.setUser(user); // 創建UserMapper對象,mybatis自動生成mapper代理對象 UserMapper mapper = sqlSession.getMapper(UserMapper.class); int count=mapper.findUserCount(userQueryVo); System.out.println(count); sqlSession.commit(); sqlSession.close(); } }
小結:查詢出來的結果集只有一行一列,可以使用簡單類型進行輸出映射。
2.1.2、輸出pojo對象和pojo列表
不管是輸出的pojo單個對象還是一個列表(list中包括pojo),在mapper.xml中resultType指定的類型是一樣的。但在mapper.java指定的方法返回值類型不一樣。
輸出單個pojo對象,方法返回值是單個對象類型
public interface UserMapper { /** 根據ID查詢用戶信息 */ public User findUserById(int id); }
輸出pojo對象list,方法返回值是List<pojo>
public interface UserMapper { /** 根據用戶名稱模糊查詢用戶信息 */ public List<User> findUserByName(String username); }
小結:生成的動態代理對象中是根據mapper.java方法的返回值類型確定是調用selectOne(返回單個對象調用)還是selectList(返回集合對象調用)
2.2、resultMap
我們知道,通過resultType輸出映射的時候,查詢出來的列名和pojo中對應的屬性名要一致才可以做正確的映射,如果不一致就會映射錯誤。但是如果不一致呢?該如何解決這個問題呢?這就要使用resultMap來映射了。
假設現在映射文件中有個sql語句:select id id_,username username_ from t_user where id=#{id},從這個sql語句中可以看出,查詢出了id和username兩列,但是都起了別名了,也就是說,如果我們現在用resultType去映射到User中的話,肯定會出問題,所以我們現在要定義一個resultMap來做查詢結果列與User的屬性之間的一個映射。
2.2.1、resultMap使用方法
(1).定義resultMap
(2).使用resultMap作為statement的輸出映射類型
2.2.2、demo例子
(1).需求:將下麵的sql使用resultMap完成映射
select id id_,username username_ from t_user where id=?
User類中屬性名和上邊的列名不一致。
(2).在SqlMapConfig.xml中自定義別名
<!-- 批量別名的定義: package:指定包名,mybatis會自動掃描包中的pojo類,自動定義別名,別名就是類名(首字母大寫或小寫都可以) --> <typeAliases> <package name="com.mybatis.entity"/> </typeAliases>
(3).定義resultMap
<?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命名空間,作用就是對sql進行分類化的管理,理解為sql隔離 註意:使用mapper代理開發時,namespace有特殊作用,namespace等於mapper介面地址 --> <mapper namespace="com.mybatis.mapper.UserMapper"> <!-- 定義resultMap select id id_,username username_ from t_user和User類中的屬性作為一個映射關係 type:resultMap最終映射的java對象類型,可以使用別名; id:對resultMap的唯一標識 --> <resultMap type="user" id="userResultMap"> <!--id表示查詢結果中的唯一標識, column:查詢出來的列名 property:type指定的pojo類型中的屬性名 最終resultMap對column和property作一個映射關係(對應關係) --> <id column="id_" property="id"/> <!--result:表示對普通列名的映射, column:查詢出來的列名 property:type指定的pojo類型中的屬性名 最終resultMap對column和property作一個映射關係(對應關係) --> <result column="username_" property="username"/> </resultMap> </mapper>
(4).使用resultMap作為statement的輸出類型映射
<!-- 使用resultMap作為輸出映射 resultMap:指定定義的resultMap的id,如果這個resultMap在其它的mapper.xml文件中,前邊需要添加namespace命名空間 --> <select id="findUserByIdResultMap" parameterType="int" resultMap="userResultMap" > select id id_,username username_ from t_user where id=#{id} </select>
(5).UserMapper.java代碼:
public interface UserMapper { /** 根據ID查詢用戶信息,使用resultMap進行輸出 */ public User findUserByIdResultMap(int id); }
(6).JUnit測試代碼:
package com.mybatis.test; import java.io.InputStream; import java.util.Date; import java.util.List; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Before; import org.junit.Test; import com.mybatis.entity.User; import com.mybatis.entity.UserQueryVo; import com.mybatis.mapper.UserMapper; public class UserMapperTest { private SqlSessionFactory sqlSessionFactory; // 此方法是在執行@Test標註的方法之前執行 @Before public void setUp() throws Exception { String resource = "SqlMapConfig.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); // 創建SqlSessionFcatory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } @Test public void testFindUserByIdResultMap() { SqlSession sqlSession = sqlSessionFactory.openSession(); // 創建Usermapper對象,mybatis自動生成mapper代理對象 UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user = mapper.findUserByIdResultMap(1); System.out.println(user); sqlSession.close(); } }
3、小結:
用resultType進行輸出映射,只有查詢出來的列名和pojo中的屬性名一致,該列才可以映射成功。
如果查詢出來的列名和pojo的屬性名不一致,通過定義一個resultMap對列名和pojo屬性名之間作一個映射關係。
原文:https://www.cnblogs.com/xiaoxi/p/6378960.html