1. 程式人生 > >MyBatis的學習總結三——輸入對映和輸出對映以及多表關聯查詢

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);
	}	
}

輸出結果:

{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多表關聯查詢之resultMap的使用

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