MyBatis的學習總結三——輸入對映和輸出對映以及多表關聯查詢
關於MyBatis的輸入對映和輸出對映,可輸入的型別很多,輸出型別亦是如此。如圖所示:
一、輸入型別是通過引數parameterType來設定的,引數型別有基本資料型別、包裝型別pojo、Map
基礎型別(String,int,long,double...)
pojo型別
pojo的包裝型別
map
二、輸出型別是通過引數resultType和resultMap來設定的,引數型別有基本型別、pojo型別、List型別、map
基礎型別
pojo型別
List型別
map
三、具體舉例:(使用的專案還是上一篇文章中的專案)
1.需求:根據使用者id查詢使用者物件。
輸入引數是使用者id(Int型別),輸出引數是User物件(pojo型別)
UserMapper介面如下:
package com.evil.mapper;
import com.evil.pojo.User;
public interface UserMapper {
User findUserById(Integer id);//按使用者Id進行查詢
}
對映檔案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"> <mapper namespace="com.evil.mapper.UserMapper"> <select id="findUserById" parameterType="int" resultType="User"> select * from user where id=#{id}; </select> </mapper>
測試類:
package com.evil.test; import org.junit.Before; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.evil.mapper.UserMapper; import com.evil.pojo.User; public class NewMapperTest { UserMapper userMapper; @Before public void initUserMapper() throws Exception { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); userMapper=context.getBean(UserMapper.class); } //根據id進行查詢 @Test public void findUserById(){ User user =userMapper.findUserById(1); System.out.println(user); } }
查詢結果:User [id=1, username=王五, sex=2, birthday=null, address=null, orders=null]
2.需求:查詢所有使用者的總數
輸入引數:無,輸出引數是基本資料型別(int)
UserMapper介面中新增方法:
int findAllUser(); //查詢使用者總數
UserMapper.xml中新增語句:
<select id="findAllUser" resultType="int">
select count(id) from user;
</select>
測試類程式碼:
@Test
public void findAllUser(){
int i = userMapper.findAllUser();
System.out.println("使用者的總數是"+i);
}
查詢結果:使用者的總數是8
3.需求:前臺在複選框裡勾選了多個使用者,做使用者資訊的查詢,此時傳到後臺的是一個String的字串,裡面是"1,3,5,11"型別
輸入引數是基本型別(String),輸出引數是List(List<User>)
userMapper介面新增方法:
List<User> findUserByIds2(String ids); //查詢使用者列表
userMapper.xml中新增sql語句,注意雖然輸出結果是List<User>,但是在填寫resultType的引數時,輸出對映依然使用User物件
//查詢所有的使用者總數
<!-- 前臺字串拼接穿ids -->
<select id="findUserByIds2" parameterType="String" resultType="User">//型別依然是User,但是輸出對映的結果是List
select * from user where id in(${value});
</select>
測試:
//前臺拼接ids,傳遞到mapper中
@Test
public void findByUserIds2(){
String ids="1,10,22,25";
List<User> list = userMapper.findUserByIds2(ids);
for (User user : list) {
System.out.println(user);
}
}
查詢結果:
User [id=1, username=王五, sex=2, birthday=null, address=null, orders=null]
User [id=10, username=張三, sex=1, birthday=Thu Jul 10 00:00:00 CST 2014, address=北京市, orders=null]
User [id=25, username=狗剩, sex=1, birthday=null, address=北海道, orders=null]
4.需求:做條件查詢,查詢條件一個是使用者性別和使用者姓名
輸入引數是兩個,可以用pojo來裝,所以輸入引數是pojo(User),輸出引數型別是List<User>
UserMapper介面新增程式碼:
List<User> findUserByIf(User user); //條件查詢
UserMapper.xml中新增sql語句:
使用if和where標籤實現動態sql
<!-- 條件查詢 -->
<select id="findUserByIf" parameterType="com.evil.pojo.User" resultType="com.evil.pojo.User">
select * from user
<!--where的兩個作用:
1.如果where標籤裡的任何一個if成立,就動態新增一個where關鍵詞
2.自動去除where關鍵字後的第一個and
-->
<where>
<if test="sex!=null and sex!=''">
and sex=#{sex}
</if>
<if test="username!=null and username!=''">
and username like '%${username}%';
</if>
</where>
</select>
測試:
//條件查詢
@Test
public void findUserByIf(){
User user = new User();
user.setSex("1");
user.setUsername("張");
List<User> list = userMapper.findUserByIf(user);
for (User user2 : list) {
System.out.println(user2);
}
}
查詢結果:
User [id=10, username=張三, sex=1, birthday=Thu Jul 10 00:00:00 CST 2014, address=北京市, orders=null]
User [id=16, username=張小明, sex=1, birthday=null, address=河南鄭州, orders=null]
User [id=24, username=張三丰, sex=1, birthday=null, address=河南鄭州, orders=null]
四、MyBatis的多表關聯查詢
現在有兩張表,User表(id,username,birthday,sex,address),Orders訂單表(id,user_id,number,createtime,note)
建立Orders的實體類:
package com.evil.pojo;
import java.util.Date;
public class Orders{
private Integer id; //訂單標識
private Integer userId; //使用者id
private String number; //購買數量
private Date createtime; //購買時間
private String note; //購買物品
private User user;
//..省略getXXX/setXXX.....
5.需求:查詢條件是使用者姓名,使用者購買的物品,很顯然來自於兩張表,查詢結果是該使用者的訂單資料,也是來源於兩張表,怎麼辦呢?
方法一:當前臺傳過來這兩個引數時,我們可以將其封裝在QueryVo中,裡面放置User和Orders的物件,這樣就可以接受到引數。但是輸出結果
來源於兩張表,無法直接對映成User物件或者Orders物件,所以使用Map<String,Object>來接收,第一個引數代表列,第二個引數代表值。
輸入引數是:包裝型別(QueryVo),輸出型別是List<Map<String,Object>>,輸出對映引數填Map
建立QueryVo:
package com.evil.pojo;
import java.util.List;
public class QueryVo {
User user;
Orders orders;
......
Mapper介面新增方法:
List<Map<String,Object>> findUserAndOrders(QueryVo vo);//查詢使用者和訂單資料
mapper.xml中新增sql:
<!-- 引數是包裝型別,返回時List<map<String,object>> -->
<select id="findUserAndOrders" parameterType="com.evil.pojo.QueryVo" resultType="map">
SELECT u.*,o.id AS oid,o.user_id,o.number,o.createtime,o.note FROM USER u JOIN orders o
ON u.id=o.user_id WHERE u.username=#{user.username} AND o.note LIKE '%${orders.note}%';
</select>
測試:
//兩表聯查,輸出對映是map,輸入對映是包裝型別
@Test
public void findUserAndOrders(){
QueryVo vo =new QueryVo();
User user=new User();
user.setUsername("王五");
vo.setUser(user);
Orders orders = new Orders();
orders.setNote("電腦");
vo.setOrders(orders);
List<Map<String,Object>> list = userMapper.findUserAndOrders(vo);
for (Map<String, Object> map : list) {
System.out.println(map);
}
}
查詢結果:
{createtime=2015-02-04 13:22:35.0, id=1, sex=2, username=王五, oid=3, number=1000010, user_id=1, note=華碩電腦}
{createtime=2015-02-03 13:22:41.0, id=1, sex=2, username=王五, oid=4, number=1000011, user_id=1, note=巨集碁電腦}
方法二:查詢條件是使用者姓名和使用者購買的物品,我們可以將其封裝在Map裡面,返回結果依然是來源於使用者表和訂單表(用List<Map<String,Object>>封裝)
輸入引數型別是map,輸出引數型別也是map
Mapper接口裡新增方法:
List<Map<String,Object>> findUserAndOrders2(Map<String,Object> map);//查詢使用者和訂單資料
mapper.xml裡新增sql查詢語句:
<!--引數是map型別,返回值也是包裝型別 -->
<select id="findUserAndOrders2" parameterType="map" resultType="map">
SELECT u.*,o.id AS oid,o.user_id,o.number,o.createtime,o.note FROM USER u JOIN orders o
ON u.id=o.user_id WHERE u.username=#{username} AND o.note LIKE '%${note}%';
</select>
測試:
//兩表聯查,輸出對映是Map,輸出對映也是map
@Test
public void findUserAndOrders2(){
Map map = new HashMap<>();
map.put("username", "王五");
map.put("note", "電腦");
List<Map<String,Object>> list =userMapper.findUserAndOrders2(map);
for (Map<String, Object> map2 : list) {
System.out.println(map2);
}
}
五、MyBatis多表關聯查詢之resultMap的使用輸出結果:
{createtime=2015-02-04 13:22:35.0, id=1, sex=2, username=王五, oid=3, number=1000010, user_id=1, note=華碩電腦}
{createtime=2015-02-03 13:22:41.0, id=1, sex=2, username=王五, oid=4, number=1000011, user_id=1, note=巨集碁電腦}
mybatis一對一(多對一)關係對映:在Orders得實體類中存在一個User物件,代表的關係是每個訂單都屬於唯一的一個使用者
1。需求:查詢所有的訂單(查詢結果中有使用者物件)
輸入型別:無,輸出型別list,但是resultMap的type填的是pojo型別
建立OrdersMapper介面:
package com.evil.mapper;
import java.util.List;
import com.evil.pojo.Orders;
public interface OrdersMapper {
public List<Orders> findUserByLink3(); //多表關聯查詢,手動對映
}
建立OrdersMapper.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.evil.mapper.OrdersMapper">
<!-- 一對一(多對一)的關聯查詢 -->
<select id="findUserByLink3" resultMap="map1">
SELECT u.*,o.id AS oid,o.user_id,o.number,o.createtime,o.note FROM USER u JOIN orders o
ON u.id=o.user_id
</select>
<!--resultMap:手動指定sql語句查詢出的列名與pojo的屬性值是意義對應的關係
type:輸出對映的型別,
id標籤:指定主鍵的對映關係
column:sql語句查詢出的列名,不是原列名
property:pojo的屬性名稱
result:指定非主鍵的對映關係
association:指定單個物件的對映關係(因為Orders中村的是User物件)
property:物件的屬性名稱
javaType:該物件的型別
-->
<resultMap type="com.evil.pojo.Orders" id="map1">
<id column="oid" property="id"/>
<result column="user_id" property="userId"/><!-- 注意這裡,查出來的列名和屬性名不一樣 -->
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
<association property="user" javaType="com.evil.pojo.User">
<id column="id" property="id"/>
<result column="address" property="address"/>
<result column="birthday" property="birthday"/>
<result column="sex" property="sex"/>
<result column="username" property="username"/>
</association>
</resultMap>
</mapper>
建立測試類OrdersMapperTest.java:
package com.evil.test;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.evil.mapper.OrdersMapper;
import com.evil.pojo.Orders;
public class OrderMapperTest {
OrdersMapper ordersMapper;
@Before
public void initUserMapper() throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
ordersMapper=context.getBean(OrdersMapper.class);
}
//第三種對映
@Test
public void findUserByLink3(){
List<Orders> list = ordersMapper.findUserByLink3();
for (Orders orders : list) {
System.out.println(orders);
}
}
}
查詢結果:
Orders [id=3, userId=1, number=1000010, createtime=Wed Feb 04 13:22:35 CST 2015, note=華碩電腦,
user=User [id=1, username=王五, sex=2, birthday=null, address=null, orders=null]]
Orders [id=4, userId=1, number=1000011, createtime=Tue Feb 03 13:22:41 CST 2015, note=巨集碁電腦,
user=User [id=1, username=王五, sex=2, birthday=null, address=null, orders=null]]
Orders [id=5, userId=10, number=1000012, createtime=Thu Feb 12 16:13:23 CST 2015, note=聯想電腦,
user=User [id=10, username=張三, sex=1, birthday=Thu Jul 10 00:00:00 CST 2014, address=北京市, orders=null]]
Orders [id=3, userId=1, number=1000010, createtime=Wed Feb 04 13:22:35 CST 2015, note=華碩電腦, user=User [id=1, username=王五, sex=2, birthday=null, address=null, orders=null]]
Orders [id=4, userId=1, number=1000011, createtime=Tue Feb 03 13:22:41 CST 2015, note=巨集碁電腦, user=User [id=1, username=王五, sex=2, birthday=null, address=null, orders=null]]
Orders [id=5, userId=10, number=1000012, createtime=Thu Feb 12 16:13:23 CST 2015, note=聯想電腦, user=User [id=10, username=張三, sex=1, birthday=Thu Jul 10 00:00:00 CST 2014, address=北京市, orders=null]]
mybatis的一對多的關係對映:一個使用者有多個訂單,在User得實體裡面有Orders的集合
2.需求,查詢所有的使用者,包含使用者下的訂單
輸入引數無,輸出引數List<User>
在UserMapper接口裡新增方法:
List<User> findUserByLink4();//查詢使用者資料,包含使用者下的訂單
在UesrMapper.xml中新增sql語句:
<!-- 一對多關係的對映 -->
<select id="findUserByLink4" resultMap="map2">
SELECT u.*,o.id AS oid,o.user_id,o.number,o.createtime,o.note FROM USER u JOIN orders o
ON u.id=o.user_id
</select>
<resultMap id="map2" type="com.evil.pojo.User">
<id column="id" property="id"/>
<result column="address" property="address"/>
<result column="birthday" property="birthday"/>
<result column="sex" property="sex"/>
<result column="username" property="username"/>
<collection property="orders" ofType="com.evil.pojo.Orders"><!-- ofType是些集合裡面的泛型的型別 -->
<id column="oid" property="id"/>
<result column="user_id" property="userId"/><!-- 注意這裡,查出來的列名和屬性名不一樣 -->
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
</collection>
</resultMap>
測試:
//關聯查詢的第四種方式:一對多,手動對映
@Test
public void findUserByLink4(){
List<User> list = userMapper.findUserByLink4();
for (User user : list) {
System.out.println(user);
}
}
查詢結果:
User [id=1, username=王五, sex=2, birthday=null, address=null,
orders=[Orders [id=3, userId=1, number=1000010, createtime=Wed Feb 04 13:22:35 CST 2015, note=華碩電腦, user=null],
Orders [id=4, userId=1, number=1000011, createtime=Tue Feb 03 13:22:41 CST 2015, note=巨集碁電腦, user=null]]]
User [id=10, username=張三, sex=1, birthday=Thu Jul 10 00:00:00 CST 2014, address=北京市,
orders=[Orders [id=5, userId=10, number=1000012, createtime=Thu Feb 12 16:13:23 CST 2015, note=聯想電腦, user=null]]]
六,關於在sql語句中,#{}和${}的使用規範:
#{}佔位符:
如果paramterType是基礎型別,那麼#{}裡面的變數可以任意填寫
如果parameterType是pojo型別,那麼#{}裡面的變數必須是屬性名稱
如果parameterType是pojo的包裝型別,那麼#{}裡面的變數必須是屬性.屬性....
如果parameterType是map型別,那麼#{}裡面的變數必須是map的key
${}拼接符:
如果paramterType是基礎型別,那麼${}裡面的變數必須填value
如果parameterType是pojo型別,那麼${}裡面的變數必須是屬性名稱
如果parameterType是pojo的包裝型別,那麼${}裡面的變數必須是屬性.屬性....
如果parameterType是map型別,那麼${}裡面的變數必須是map的key