mybatis高階對映
mybatis動態代理實現高階對映,主要整合了mybatis和mysql間的複雜查詢方法。在本專案中主要在使用者,訂單,訂單明細,商品明細間進行關聯查詢操作來理解高階對映。
以下一對一查詢,一對多查詢,多對多查詢三種查詢方法主要以resultType(和resultMap(對結果有特殊的對映要求)兩種封裝方法完成。如果對結果沒有特殊的對映要求建議使用resultType,但resultMap 可以實現延遲載入, resultType 無法實現延遲載入。
工程結構搭建
- 在工程src下建立一個總包cn.mybatis.xhchen
- 在總包下建立兩個包,cn.mybatis.xhchen.entity實體類包和cn.mybatis.xhchen.mapper介面mapper包
- 工程下建立config檔案集與src同級
- 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封裝,為了更好的瞭解和區別兩種方法,在一對一查詢中用了兩種封裝方法進行查詢 。
專案用到的需求:查詢訂單資訊,關聯查詢使用者資訊
- 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();
}