1. 程式人生 > >Mybatis 學習筆記(四)——關聯(對映)關係(一對一,一對多)

Mybatis 學習筆記(四)——關聯(對映)關係(一對一,一對多)

一、背景知識

   在介紹對映關係之前需要我們對 resultMap 要足夠了解。在 resultMap 中有如下節點可配置:

  • id :唯一標識列,column 為資料庫ID列,property為 POJO 的id屬性,注意在查詢出的結果集中每一列都必須不一樣,標記結果作為 ID 可以幫助提高整體效能;
  • constructor :類在例項化時,用來注入結果到構造方法中id – 一個 ID 結果;標記結果作為 ID 可以幫助提高整體效能;注意:一是 constructor 中欄位的順序一定要與POJO中定義的欄位順序相同且型別匹配;二是如果POJO中只有有參構造方法時則必須配置;
    • idArg :ID 引數;標記結果作為 ID 可以幫助提高整體效能;
    • arg :注入到構造方法的一個普通結果。
  • result :注入到欄位或 POJO 屬性的普通結果
  • association :用於對映關聯查詢到單個物件的資訊
    • 嵌入結果對映 :結果對映自身的關聯,或者參考一個
  • collection :對關聯查詢到多條記錄對映到集合物件中,其中屬性ofType表示指定對映到集合屬性中pojo的型別;
    • 嵌入結果對映 :結果對映自身的關聯,或者參考一個
  • discriminator :使用結果值來決定使用哪個結果對映
    • case :基於某些值的結果對映
      • 嵌入結果對映 :這種情形結果也對映它本身,因此可以包含很多相同的元素,或者它可以參照一個外部的結果對映。

二、一對一對映關係

1. 需求:查詢訂單資訊,關聯查詢建立訂單的使用者資訊,ResultMap實現
2. 資料庫表有 ORDERS,USER,ORDERDETAIL,ITEMS。點選下載
3. POJO類

Orders 與 User 是一對一的關係,在 Orders 中 加入 User 物件。
User.java

package com.po;

import java.util.Date;
import java.util.List;

/**
 * 使用者類
 * @author 歐陽
 *
 */
public class User {
	private int id;				//id
	private String username;	//使用者名稱
	private String sex;			//性別
	private Date birthday;		//生日
	private String address;		//地址
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	
}

Orders.java

package com.po;

import java.util.Date;
import java.util.List;

/**
 * 訂單類
 * @author 歐陽
 *
 */
public class Orders {
    private Integer id; 		//id
    private Integer userId; 	//使用者id
    private String number; 		//數量
    private Date createtime;  	//建立時間
    private String note; 		//備註
    private User user;			//使用者資訊
    
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number == null ? null : number.trim();
    }

    public Date getCreatetime() {
        return createtime;
    }

    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note == null ? null : note.trim();
    }

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}
}
4. 編寫Mapper.xml

OrdersCustomMapper.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.mapper.OrdersCustomMapper">
	
	<!-- 
		查詢訂單資訊,關聯查詢建立訂單的使用者資訊(一對一查詢)
		使用resultMap將結果對映到OrdersCustom類中
	 -->
	<!-- 定義查詢訂單及關聯使用者資訊結果的resultMap -->
	<resultMap type="com.po.Orders" id="OrdersUserResultMap">
		<!-- 配置對映的訂單資訊 -->
		<id column="id" 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:將要關聯查詢的使用者資訊對映到Orders的哪個屬性
		 -->
		<association property="user" javaType="com.po.User">
			<id column="id_" property="id"/>
			<result column="username" property="username"/>
			<result column="sex" property="sex"/>
			<result column="address" property="address"/>
		</association>
	</resultMap>
	
	<select id="findOrdersUserResultMap" resultMap="OrdersUserResultMap">
		SELECT
			ORDERS.*, 
			u.id id_,
			u.USERNAME,
			u.SEX,
			u.address
		FROM
			ORDERS,
			USER u
		WHERE
			ORDERS.user_id = u.ID
	</select>

</mapper>

5. 編寫Mapper介面(採用Mapper代理的方式)

OrdersCustomMapper.java

package com.mapper;

import java.util.List;

import com.po.Orders;

public interface OrdersCustomMapper {

	/*
	 * 查詢訂單資訊,關聯查詢建立訂單的使用者資訊,ResultMap實現
	 */
	public List<Orders> findOrdersUserResultMap() throws Exception;
	
}

6. 測試

使用JUnit4 進行測試,下面是測試的主要程式碼。OrdersCustomMapperTest.java

private SqlSessionFactory  sqlSessionFactory;
//此方法是在執行testFindUserById之前執行
@Before
public void setUp() throws Exception {
	String resource = "config/SqlMapConfig.xml";
	InputStream inputStream = Resources.getResourceAsStream(resource);

	// 建立會話工廠
	this.sqlSessionFactory = new SqlSessionFactoryBuilder()
			.build(inputStream);
}
@Test
public void testFindOrdersUserResultMap() {
	SqlSession sqlsession = sqlSessionFactory.openSession();
	OrdersCustomMapper mapper = sqlsession
			.getMapper(OrdersCustomMapper.class);
	try {
		List<Orders> orders = mapper.findOrdersUserResultMap();
		System.out.println(orders.size());
	} catch (Exception e) {
		e.printStackTrace();
	}
}

三、一對多對映關係

1. 需求:查詢訂單及訂單明細
2. POJO類

Orders.java

package com.po;

import java.util.Date;
import java.util.List;

/**
 * 訂單類
 * @author 歐陽
 *
 */
public class Orders {
    private Integer id; 		//id
    private Integer userId; 	//使用者id
    private String number; 		//數量
    private Date createtime;  	//建立時間
    private String note; 		//備註
    private User user;			//使用者資訊
    
    private List<Orderdetail> orderdetail; //訂單明細
    
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number == null ? null : number.trim();
    }

    public Date getCreatetime() {
        return createtime;
    }

    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note == null ? null : note.trim();
    }

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}
	
	
	public List<Orderdetail> getOrderdetail() {
		return orderdetail;
	}

	public void setOrderdetail(List<Orderdetail> orderdetail) {
		this.orderdetail = orderdetail;
	}

}

User.java

package com.po;

import java.util.Date;
import java.util.List;

/**
 * 使用者類
 * @author 歐陽
 *
 */
public class User {
	private int id;				//id
	private String username;	//使用者名稱
	private String sex;			//性別
	private Date birthday;		//生日
	private String address;		//地址
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
}

Orderdetail.java

package com.po;

/**
 * 訂單詳情類
 * @author 歐陽
 *
 */
public class Orderdetail {
    private Integer id;

    private Integer ordersId;

    private Integer itemsId;

    private Integer itemsNum;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getOrdersId() {
        return ordersId;
    }

    public void setOrdersId(Integer ordersId) {
        this.ordersId = ordersId;
    }

    public Integer getItemsId() {
        return itemsId;
    }

    public void setItemsId(Integer itemsId) {
        this.itemsId = itemsId;
    }

    public Integer getItemsNum() {
        return itemsNum;
    }

    public void setItemsNum(Integer itemsNum) {
        this.itemsNum = itemsNum;
    }
}
3. 編寫對映關係

將下面的程式碼加入 OrdersCustomMapper.xml 中

<!-- 
查詢訂單及訂單明細(一對多查詢)
 -->
<!-- 定義查詢訂單及關聯訂單資訊商品資訊結果的resultMap -->
<resultMap type="com.po.Orders" id="OrdersAndOrderDetailResultMap">
	<!-- 配置對映的訂單資訊 -->
	<id column="id" 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.po.User">
		<id column="u_id" property="id"/>
		<result column="username" property="username"/>
		<result column="sex" property="sex"/>
		<result column="address" property="address"/>
	</association>
	
	<!-- 配置對映關係的訂單明細 -->
	<!-- 
		collection:對關聯查詢到多條記錄對映到集合物件中
		property:將要關聯查詢的使用者資訊對映到Orders的哪個屬性
		ofType:指定對映到集合屬性中pojo的型別
	 -->
	<collection property="orderdetail" ofType="com.po.Orderdetail">
		<id column="od_id" property="id"/>
		<result column="orders_id" property="ordersId"/>
		<result column="items_id" property="itemsId"/>
		<result column="items_num" property="itemsNum"/>
	</collection>
	
</resultMap>

<select id="findOrdersAndOrderDetailResultMap" resultMap="OrdersAndOrderDetailResultMap">
	SELECT
		o.*,
		od.id od_id,
		od.items_id,
		od.items_num,
	    od.orders_id,
		u.id u_id,
		u.USERNAME,
		u.SEX,
		u.address
	FROM
		orders o,
		orderDetail od,
		user u
	WHERE
		o.id = od.orders_id
	AND o.user_id = u.id
</select>
4. 編寫對映介面

將下面程式碼新增到 OrdersCustomMapper.java 中

/*
 * 查詢訂單及訂單明細
 */
public List<Orders> findOrdersAndOrderDetailResultMap() throws Exception;

5. 測試介面

將下面程式碼加入 OrdersCustomMapperTest.java 中

@Test
public void testFindOrdersAndOrderDetailResultMap() {
	SqlSession sqlsession = sqlSessionFactory.openSession();
	OrdersCustomMapper mapper = sqlsession
			.getMapper(OrdersCustomMapper.class);
	try {
		List<Orders> orders = mapper.findOrdersAndOrderDetailResultMap();
		System.out.println(orders.size());
	} catch (Exception e) {
		e.printStackTrace();
	}
}