1. 程式人生 > >mybatis高階對映

mybatis高階對映

mybatis動態代理實現高階對映,主要整合了mybatis和mysql間的複雜查詢方法。在本專案中主要在使用者,訂單,訂單明細,商品明細間進行關聯查詢操作來理解高階對映。

以下一對一查詢,一對多查詢,多對多查詢三種查詢方法主要以resultType(resultMap(對結果有特殊的對映要求)兩種封裝方法完成。如果對結果沒有特殊的對映要求建議使用resultType,但resultMap 可以實現延遲載入, resultType 無法實現延遲載入。

工程結構搭建

  1. 在工程src下建立一個總包cn.mybatis.xhchen
  2. 在總包下建立兩個包,cn.mybatis.xhchen.entity實體類包和cn.mybatis.xhchen.mapper介面mapper包
  3. 工程下建立config檔案集與src同級
  4. Config下建立mapper包,資料來源檔案db.properties,日誌檔案log4j.properties和mybatis的核心配置檔案SqlMapConfig.xml

工程環境搭建

Jar包

db.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root

log4j.properties

# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

SqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration 
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>

	<!-- 載入db.properties配置 -->
	<properties resource="db.properties"></properties>

	<!-- 和spring整合後 environments配置將廢除 -->
	<environments default="development">
		<environment id="development">
			<!-- 使用jdbc事務管理 -->
			<transactionManager type="JDBC" />
			<!-- 資料庫連線池 -->
			<dataSource type="POOLED">
				<property name="driver" value="${jdbc.driver}" />
				<property name="url" value="${jdbc.url}" />
				<property name="username" value="${jdbc.username}" />
				<property name="password" value="${jdbc.password}" />
			</dataSource>
		</environment>
	</environments>

	<!-- 載入對映檔案 -->
	<mappers>
		<!-- 動態代理資料庫操作配置檔案 -->
		<mapper resource="mapper/ordersMapper.xml"/>
	</mappers>

</configuration>

工程編寫

一對一查詢

將查詢結果對映到pojo封裝,為了更好的瞭解和區別兩種方法,在一對一查詢中用了兩種封裝方法進行查詢 。

專案用到的需求:查詢訂單資訊,關聯查詢使用者資訊

  1. resultType的封裝方法查詢

實現較為簡單,如果 pojo 中沒有包括查詢出來的列名,需要增加列名對應的屬性,即可完成對映。

對映思路

在Orders.java中新增使用者資訊欄位private Customer customer; 並生成getter/setter。最終會將訂單資訊對映到 orders 中,訂單所對應的使用者資訊對映到 orders 中的 customer屬性中。

cn.mybatis.xhchen.entity下建立訂單類Orders.java及其拓展類OrdersCustomer.java,使用者類Customer.java

Orders.java

package cn.mybatis.xhchen.entity;

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

/**
 * 
 * ClassName: Orders
 * 
 * @Description: 訂單實體類
 * @author XHChen
 * @date 2018年10月12日 下午2:29:25
 */
public class Orders {

	private Integer id; // 訂單Id

	private Integer user_id; // 下單使用者id

	private String number; // 訂單號

	private Date createtime; // 建立訂單時間

	private String note; // 備註

	private Customer customer; // 使用者資訊

	private List<OrderDetail> orderDetail; // 訂單明細

	public Integer getId() {
		return id;
	}

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

	public Integer getUser_id() {
		return user_id;
	}

	public void setUser_id(Integer user_id) {
		this.user_id = user_id;
	}

	public String getNumber() {
		return number;
	}

	public void setNumber(String number) {
		this.number = number;
	}

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

	public Customer getCustomer() {
		return customer;
	}

	public void setCustomer(Customer customer) {
		this.customer = customer;
	}

	public List<OrderDetail> getOrderDetail() {
		return orderDetail;
	}

	public void setOrderDetail(List<OrderDetail> orderDetail) {
		this.orderDetail = orderDetail;
	}

	@Override
	public String toString() {
		return "Orders [id=" + id + ", user_id=" + user_id + ", number="
				+ number + ", createtime=" + createtime + ", note=" + note
				+ ", customer=" + customer + ", orderDetail=" + orderDetail
				+ "]";
	}

}

OrdersCustomer.java

package cn.mybatis.xhchen.entity;

/**
 * 
 * ClassName: OrdersCustom
 * 
 * @Description: Custom的拓展類
 * @author XHChen
 * @date 2018年10月12日 下午2:29:44
 */
public class OrdersCustom extends Orders {	

	// 新增使用者其他的屬性

}

Customer.java

package cn.mybatis.xhchen.entity;

import java.util.List;

/**
 * 
 * ClassName: Customer
 * 
 * @Description: 使用者資訊
 * @author XHChen
 * @date 2018年10月12日 下午2:34:13
 */
public class Customer {

	private Integer id; // 使用者id

	private String username; // 使用者名稱稱

	private String sex; // 使用者性別

	private String address; // 使用者地址

	private List<Orders> orderslist; // 訂單列表

	public List<Orders> getOrderslist() {
		return orderslist;
	}

	public void setOrderslist(List<Orders> orderslist) {
		this.orderslist = orderslist;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer 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 String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	@Override
	public String toString() {
		return "Customer [id=" + id + ", username=" + username + ", sex=" + sex
				+ ", address=" + address + ", orderslist=" + orderslist + "]";
	}

}

/config/mapper下建立sql編寫檔案ordersMapper.xml 編寫sql語句

<?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="cn.mybatis.xhchen.mapper.OrdersCustomMapper">

	<!-- 一對一查詢 -->
	<!-- 查詢訂單,關聯查詢使用者資訊,使用resultType實現 -->
	<select id="findOrderCustomerResultType" resultType="cn.mybatis.xhchen.entity.OrdersCustom">
		SELECT
			orders.*,
			customer.username,
			customer.sex,
			customer.address
		FROM
			orders,
			customer
		WHERE 
			orders.user_id=customer.id

	</select>
</mapper>

cn.mybatis.xhchen.mapper下編寫OrdersCustomMapper.java介面方法(後面只提供方法內容)

package cn.mybatis.xhchen.mapper;

import java.util.List;

import cn.mybatis.xhchen.entity.Customer;
import cn.mybatis.xhchen.entity.Orders;
import cn.mybatis.xhchen.entity.OrdersCustom;

/**
 * 
 * ClassName: OrdersCustomMapper
 * 
 * @Description: 查詢訂單
 * @author XHChen
 * @date 2018年10月12日 下午2:26:05
 */
public interface OrdersCustomMapper {

	// 一對一查詢訂單,關聯查詢使用者資訊,resultType實現
	public List<OrdersCustom> findOrderCustomerResultType() throws Exception;

}

編寫Junit Test Case測試類方法(後面測試只提供方法內容)

package cn.mybatis.xhchen.mapper;

import java.io.IOException;
import java.io.InputStream;
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 cn.mybatis.xhchen.entity.Customer;
import cn.mybatis.xhchen.entity.Orders;
import cn.mybatis.xhchen.entity.OrdersCustom;

public class OrdersCustomMapperTest {

	// 建立會話工廠
	private SqlSessionFactory sqlSessionFactory;

	@Before
	/**
	 * 
	 * @Description: 載入mapper
	 * @param @throws IOException   
	 * @return void  
	 * @throws
	 * @author XHChen
	 * @date 2018年10月12日 下午2:40:23
	 */
	public void setUp() throws IOException {

		// 定義核心配置檔案
		String resource = "SqlMapConfig.xml";

		// 獲得核心配置檔案流
		InputStream inputStream = Resources.getResourceAsStream(resource);

		// 建立會話工廠,載入配置檔案流
		sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

	}

	@Test
	/**
	 * 
	 * @Description: 一對一查詢訂單,關聯查詢使用者資訊,ResultType實現
	 * @param @throws Exception   
	 * @return void  
	 * @throws
	 * @author XHChen
	 * @date 2018年10月12日 下午3:02:42
	 */
	public void testfindOrderCustomerResultType() throws Exception {

		// 開啟sqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();

		// 動態代理
		OrdersCustomMapper ordersCustomMapper = sqlSession.getMapper(OrdersCustomMapper.class);

		List<OrdersCustom> list = ordersCustomMapper.findOrderCustomerResultType();

		// 遍歷結果
		for (OrdersCustom ordersCustom : list) {
			System.out.println(ordersCustom);
		}
		System.out.println(list.size());

		sqlSession.close();

	}

}

2.resultMap的封裝方法查詢

如果對查詢結果有特殊的要求,使用 resultMap 可以完成將關聯查詢對映 pojo 的屬性中.

/config/mapper下建立sql編寫檔案ordersMapper.xml 編寫sql語句

注意:<select>標籤中的resultMap與<resultMap>標籤中的id保持一致

        <resultMap type="cn.mybatis.xhchen.entity.Orders" id="OrdersCustomerResultMap">
		<!-- 配置對映的訂單資訊 -->
		<!-- id:查詢列中的唯一標識,訂單資訊中的唯一標識 column:訂單資訊的唯一標識 列 property:訂單資訊的唯一標識列所對映到orders中的那個屬性 -->
		<id column="id" property="id" />
		<result column="user_id" property="user_id" />
		<result column="number" property="number" />
		<result column="createtime" property="createtime" />
		<result column="note" property="note" />

		<!-- 配置對映的關聯使用者資訊 -->
		<!--association:用於對映關聯查詢單個物件的資訊 property:要將關聯查詢的使用者資訊對映到Orders中那個屬性 -->

		<association property="customer" javaType="cn.mybatis.xhchen.entity.Customer">
			<!-- id:關聯查詢使用者的唯一標識 column:指定唯一標識使用者資訊的列 property:對映到user的那個屬性 -->
			<id column="id" property="id" />
			<result column="username" property="username" />
			<result column="sex" property="sex" />
			<result column="address" property="address" />

		</association>
	</resultMap>

	<!-- 查詢訂單,關聯查詢使用者資訊,使用resultMap實現 -->
	<select id="findOrderCustomerResultMap" resultMap="OrdersCustomerResultMap">
		SELECT
			orders.*,
			customer.username,
			customer.sex,
			customer.address
		FROM
			orders,
			customer
		WHERE 
			orders.user_id=customer.id

	</select>

cn.mybatis.xhchen.mapper下編寫OrdersCustomMapper.java介面方法

// 一對一查詢訂單,關聯查詢使用者資訊,ResultMap實現
public List<Orders> findOrderCustomerResultMap() throws Exception;

編寫Junit Test Case測試類方法

        @Test
	/**
	 * 
	 * @Description: 一對一查詢訂單,關聯查詢使用者資訊,ResultMap實現
	 * @param @throws Exception
	 * @return void
	 * @throws
	 * @author XHChen
	 * @date 2018年10月12日 下午3:22:30
	 */
	public void testfindOrderCustomerResultMap() throws Exception {

		// 開啟sqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();

		// 動態代理
		OrdersCustomMapper ordersCustomMapper = sqlSession.getMapper(OrdersCustomMapper.class);

		List<Orders> list = ordersCustomMapper.findOrderCustomerResultMap();

		// 遍歷結果
		for (Orders orders : list) {
			System.out.println(orders);
		}
		System.out.println(list.size());

		sqlSession.close();

	}

一對多查詢

使用 association將關聯查詢資訊對映到一個pojo物件中 和 collection將關聯查詢資訊對映到一個list集合中 完成一對多高階對映

專案用到的需求:查詢訂單關聯查詢使用者及訂單明細

對映思路

在Orders.java中新增訂單明細欄位private List<OrderDetail> orderDetail;並生成getter/setter。最終會將訂單資訊對映到 orders 中,訂單所對應的訂單明細對映到 orders 中的 orderDetails 屬性中。

cn.mybatis.xhchen.entity下建立訂單明細類OrdersDetail.java

package cn.mybatis.xhchen.entity;

/**
 * 
 * ClassName: OrderDetail
 * 
 * @Description: 訂單明細
 * @author XHChen
 * @date 2018年10月12日 下午4:30:50
 */
public class OrderDetail {

	private Integer id; // 明細主鍵id

	private Integer items_id; // 明細專案

	private Integer items_num; // 明細編號

	private Integer orders_id; // 訂單id

	private Items items; // 商品資訊

	public Items getItems() {
		return items;
	}

	public void setItems(Items items) {
		this.items = items;
	}

	public Integer getId() {
		return id;
	}

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

	public Integer getItems_id() {
		return items_id;
	}

	public void setItems_id(Integer items_id) {
		this.items_id = items_id;
	}

	public Integer getItems_num() {
		return items_num;
	}

	public void setItems_num(Integer items_num) {
		this.items_num = items_num;
	}

	public Integer getOrders_id() {
		return orders_id;
	}

	public void setOrders_id(Integer orders_id) {
		this.orders_id = orders_id;
	}

	@Override
	public String toString() {
		return "OrderDetail [id=" + id + ", items_id=" + items_id
				+ ", items_num=" + items_num + ", orders_id=" + orders_id
				+ ", items=" + items + "]";
	}

}

/config/mapper下建立sql編寫檔案ordersMapper.xml 編寫sql語句

注意:<select>標籤中的resultMap與<resultMap>標籤中的id保持一致

        <!-- 一對多查詢 -->
	<resultMap type="cn.mybatis.xhchen.entity.Orders" id="OrdersAndOrderdetailResultMap" extends="OrdersCustomerResultMap">
		<!-- 繼承 OrdersCustomerResultMap-->
		<!-- 配置對映的訂單資訊 -->
		<!-- 配置對映的關聯使用者資訊 -->
		
		<!-- 關聯訂單明細資訊 
   			一個訂單關聯查詢出了多條訂單明細,要使用collection對映
   			collection:對關聯查詢到的多條記錄對映到集合中
    		property:將關聯查詢到的多條記錄對映到orders類的那個屬性
    		ofType:指定對映的集合屬性中pojo的型別
  		-->
  		<collection property="orderDetail" ofType="cn.mybatis.xhchen.entity.OrderDetail">
  			<!-- id:唯一標識
       			property:要將訂單明細的唯一標識對映到com.mybatis.entity.OrderDetail的那個屬性
    		-->
  			
  			<id column="id" property="id"/>
  			<result column="items_id" property="items_id"/>
  			<result column="items_num" property="items_num"/>
  			<result column="orders_id" property="orders_id"/>
  		
  		</collection>
	</resultMap>
	
	<!-- 查詢訂單關聯查詢使用者及訂單明細,使用resultMap實現  -->
	<select id="findOrdersAndOrderdetailResultMap" resultMap="OrdersAndOrderdetailResultMap">
		SELECT orders.*,
			customer.username,
			customer.sex,
			customer.address,
			orderdetail.id as orderdetail_id,
			orderdetail.items_id,
			orderdetail.items_num,
			orderdetail.orders_id
		FROM
			orders,
			customer,
			orderdetail
		WHERE 
			orders.user_id = customer.id AND orderdetail.orders_id = orders.id

	</select>

cn.mybatis.xhchen.mapper下編寫OrdersCustomMapper.java介面方法

// 一對多查詢訂單關聯查詢使用者及訂單明細,使用resultMap實現
public List<Orders> findOrdersAndOrderdetailResultMap() throws Exception;

編寫Junit Test Case測試類方法

        @Test
	/**
	 * 
	 * @Description: 一對多查詢訂單關聯查詢使用者及訂單明細,使用resultMap實現
	 * @param    
	 * @return void  
	 * @throws
	 * @author XHChen
	 * @date 2018年10月12日 下午5:17:32
	 */
	public void findOrdersAndOrderdetailResultMap() throws Exception {
		
		// 開啟sqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();

		// 動態代理
		OrdersCustomMapper ordersCustomMapper = sqlSession.getMapper(OrdersCustomMapper.class);

		List<Orders> list = ordersCustomMapper.findOrdersAndOrderdetailResultMap();
		
		// 遍歷
		for (Orders orders : list) {
			System.out.println(orders);
		}
		System.out.println(list.size());
		
		sqlSession.close();
		
	}

多對多查詢

使用 association將關聯查詢資訊對映到一個pojo物件中 和 collection將關聯查詢資訊對映到一個list集合中 完成一對多高階對映

專案用到的需求:查詢使用者以及使用者購買的商品資訊

對映思路

將使用者所有資訊對映到Customer中。

在Customer中新增訂單列表屬性private List<Orders> orderslist;,將建立的訂單對映到orderslist;

在Orders中新增訂單明細屬性private List<OrderDetail> orderDetail;,將建立的訂單明細對映到orderDetail;

在OrdersDetail中新增商品明細屬性private Items items;,將建立的商品資訊對映到items。

在/config/mapper下建立sql編寫檔案ordersMapper.xml 編寫sql語句

注意:<select>標籤中的resultMap與<resultMap>標籤中的id保持一致

        <!-- 多對多查詢 -->
	<resultMap type="cn.mybatis.xhchen.entity.Customer" id="CustomerAndOrderdetailResultMap">
		<!-- 使用者資訊 -->
		<id column="id" property="id" />
		<result column="username" property="username" />
		<result column="sex" property="sex" />
		<result column="address" property="address" />
		
		<!-- 訂單資訊 -->
		<collection property="orderslist" ofType="cn.mybatis.xhchen.entity.Orders">
			<id column="id" property="id" />
			<result column="user_id" property="user_id" />
			<result column="number" property="number" />
			<result column="createtime" property="createtime" />
			<result column="note" property="note" />
		
			<!-- 訂單明細信 -->
	  		<collection property="orderDetail" ofType="cn.mybatis.xhchen.entity.OrderDetail">
	  			<id column="id" property="id"/>
	  			<result column="items_id" property="items_id"/>
	  			<result column="items_num" property="items_num"/>
	  			<result column="orders_id" property="orders_id"/>
	  			
	  			<!-- 商品資訊 -->
	  			<association property="items" javaType="cn.mybatis.xhchen.entity.Items">
	  				<id column="id" property="id"/>
	  				<result column="items_name" property="items_name"/>
	  				<result column="items_detail" property="items_detail"/>
	  				<result column="items_price" property="items_price"/>
	  			</association>
	  		
	  		</collection>
  		</collection>
	</resultMap>
	
	<!-- 查詢使用者以及使用者購買的商品資訊 -->
	<select id="findCustomerAndOrderdetailResultMap" resultMap="CustomerAndOrderdetailResultMap">
		SELECT 
			orders.*,
		    customer.username,
		    customer.sex,
		    customer.address,
			orderdetail.id as orderdetail_id,
		    orderdetail.items_id,
		    orderdetail.items_num,
		    orderdetail.orders_id,
		    items.id as items_id,
		    items.items_name,
		    items.items_detail,
		    items.items_price	
	  	FROM
		    orders,
		    customer,
		    orderdetail,
		    items
	  	WHERE 
	  	    orders.user_id = customer.id AND orderdetail.orders_id = orders.id AND orderdetail.items_id = items.id
	
	</select>

在cn.mybatis.xhchen.mapper下編寫OrdersCustomMapper.java介面方法

// 多對多查詢使用者以及使用者購買的商品資訊
public List<Customer> findCustomerAndOrderdetailResultMap() throws Exception;

編寫Junit Test Case測試類方法

        @Test
	/**
	 * 
	 * @Description: 多對多查詢使用者以及使用者購買的商品資訊
	 * @param    
	 * @return void  
	 * @throws
	 * @author XHChen
	 * @date 2018年10月14日 上午10:52:34
	 */
	public void testfindCustomerAndOrderdetailResultMap() throws Exception {
		
		// 開啟sqlSession
		SqlSession sqlSession = sqlSessionFactory.openSession();
		
		// 載入動態代理
		OrdersCustomMapper ordersCustomMapper = sqlSession.getMapper(OrdersCustomMapper.class);
		
		// 查詢操作
		// 呼叫mapper方法
		List<Customer> list = ordersCustomMapper.findCustomerAndOrderdetailResultMap();
		
		// 遍歷結果
		for (Customer customer : list) {
			System.out.println(customer);
		}
		System.out.println(list.size());
		
		sqlSession.close();
	}