第五章.MyBatis高階對映
阿新 • • 發佈:2018-11-11
5.1 新建資料庫準備
CREATE TABLE `finacial_products` ( `product_id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(32) NOT NULL COMMENT '理財產品名稱', `price` float(10,1) NOT NULL COMMENT '理財產品定價', `detail` text COMMENT '理財產品描述', `pic` varchar(64) DEFAULT NULL COMMENT '理財產品圖片', `invasttime`datetime NOT NULL COMMENT '理財產品收益日期', PRIMARY KEY (`product_id`) ) ;
CREATE TABLE `customer` ( `cus_id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(32) NOT NULL COMMENT '使用者名稱稱', `acno` varchar(32) DEFAULT NULL COMMENT '卡號', `gender` varchar(4) DEFAULT NULL COMMENT '性別', `phone`varchar(256) DEFAULT NULL COMMENT '電話', PRIMARY KEY (`cus_id`) );
CREATE TABLE `batch` ( `batch_id` int(11) NOT NULL AUTO_INCREMENT, `cus_id` int(11) NOT NULL COMMENT '建立批次使用者id', `number` varchar(32) NOT NULL COMMENT '批次編碼', `createtime` datetime NOT NULL COMMENT '建立批次時間', `note`varchar(100) DEFAULT NULL COMMENT '備註', PRIMARY KEY (`batch_id`), KEY `FK_batch_1` (`cus_id`), CONSTRAINT `FK_batch_id` FOREIGN KEY (`cus_id`) REFERENCES `customer` (`cus_id`) ON DELETE NO ACTION ON UPDATE NO ACTION );
CREATE TABLE `batchdetail` ( `id` int(11) NOT NULL AUTO_INCREMENT, `batch_id` int(11) NOT NULL COMMENT '批次id', `product_id` int(11) NOT NULL COMMENT '理財產品id', `product_num` int(11) DEFAULT NULL COMMENT '理財產品購買數量', PRIMARY KEY (`id`), KEY `FK_batchdetail_1` (`batch_id`), KEY `FK_batchdetail_2` (`product_id`), CONSTRAINT `FK_batchdetai_1` FOREIGN KEY (`batch_id`) REFERENCES `batch` (`batch_id`) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT `FK_batchdetai_2` FOREIGN KEY (`product_id`) REFERENCES `finacial_products` (`product_id`) ON DELETE NO ACTION ON UPDATE NO ACTION );
5.2 一對一查詢
新建類在包 cn.com.mybatis.po
Batch.java
getter/setter方法
public class Batch { private int batch_id; private int cus_id; private String number; private Date createtime; private String note;
.....
}
BatchCustomer.java
public class BatchCustomer extends Batch{ private String username; private String acno; ...
}
一對一查詢
使用resultType實現
UserMapper.xml
<select id="findBatchCustomer" resultType="cn.com.mybatis.po.BatchCustomer"> SELECT BATCH.*, CUSTOMER.username, CUSTOMER.acno FROM BATCH, CUSTOMER WHERE BATCH.cus_id = CUSTOMER.cus_id </select>
MyBatisTest.java
@Test public void testBatchCustomer() throws Exception{ SqlSession sqlSession = dataConn.getSqlSession(); //呼叫userMapper的方法 List<BatchCustomer> bcList=sqlSession.selectList("test.findBatchCustomer"); if(bcList!=null){ BatchCustomer batchCustomer = null; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); for (int i = 0; i < bcList.size(); i++) { batchCustomer = bcList.get(i); System.out.println("卡號為"+batchCustomer.getAcno()+"的名為" +batchCustomer.getUsername()+"的客戶:\n於" +sdf.format(batchCustomer.getCreatetime())+"採購了批次號為" +batchCustomer.getNumber()+"的一批理財產品"); } } sqlSession.close(); }
執行的結果:
DEBUG [main] - Setting autocommit to false on JDBC Connection [[email protected]] DEBUG [main] - ==> Preparing: SELECT BATCH.*, CUSTOMER.username, CUSTOMER.acno FROM BATCH, CUSTOMER WHERE BATCH.cus_id = CUSTOMER.cus_id DEBUG [main] - ==> Parameters: DEBUG [main] - <== Total: 1 卡號為622848的名為Mr的客戶: 於2018-10-04 16:47:41採購了批次號為牛奶的一批理財產品 DEBUG [main] - Resetting autocommit to true on JDBC Connection [[email protected]] DEBUG [main] - Closing JDBC Connection [[email protected]]
資料庫的內容
customer表:
batch表:
使用resultMap實現
新建兩個類
Customer.java
public class Customer implements Serializable{ private int cus_id; private String username; private String acno; private String gender; private String phone; private List<Batch> batchList;
...
}
BatchItem.java
import java.util.Date; import java.util.List; public class BatchItem { private int batch_id; private int cus_id; private String number; private Date createtime; private String note; private Customer customer;
...
}
UserMapper.xml
<resultMap type="cn.com.mybatis.po.BatchItem" id="BatchInfoMap"> <id column="batch_id" property="batch_id"/> <result column="cus_id" property="cus_id"/> <result column="number" property="number"/> <result column="createtime" property="createtime" javaType="java.util.Date"/> <result column="note" property="note"/> <association property="customer" javaType="cn.com.mybatis.po.Customer"> <id column="cus_id" property="cus_id"/> <result column="username" property="username"/> <result column="acno" property="acno"/> <result column="gender" property="gender"/> <result column="phone" property="phone"/> </association> </resultMap> <select id="findBatchCustomerToMap" resultMap="BatchInfoMap"> SELECT BATCH.*, CUSTOMER.username, CUSTOMER.acno FROM BATCH, CUSTOMER WHERE BATCH.cus_id = CUSTOMER.cus_id </select>
MyBatisTest.java
@Test public void testBatchCustomerToMap() throws Exception{ SqlSession sqlSession=dataConn.getSqlSession(); //呼叫userMapper的方法 List<BatchItem> bcList=sqlSession.selectList("findBatchCustomerToMap"); if(bcList!=null){ BatchItem batchItem = null; Customer customer = null; SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); for (int i = 0; i < bcList.size(); i++) { batchItem = bcList.get(i);//取出批次物件 customer = batchItem.getCustomer();//取出該批次的使用者資訊 System.out.println("卡號為"+customer.getAcno()+"的名為" +customer.getUsername()+"的客戶:\n於" +sdf.format(batchItem.getCreatetime())+"採購了批次號為" +batchItem.getNumber()+"的一批理財產品"); } } sqlSession.close(); }
控制檯結果:
DEBUG [main] - Setting autocommit to false on JDBC Connection [[email protected]] DEBUG [main] - ==> Preparing: SELECT BATCH.*, CUSTOMER.username, CUSTOMER.acno FROM BATCH, CUSTOMER WHERE BATCH.cus_id = CUSTOMER.cus_id DEBUG [main] - ==> Parameters: DEBUG [main] - <== Total: 1 卡號為622848的名為Mr的客戶: 於2018-10-04 16:47:41採購了批次號為牛奶的一批理財產品 DEBUG [main] - Resetting autocommit to true on JDBC Connection [[email protected]]
一對多查詢
首先對資料路進行補充:
batch表:
batchdetail表:
customer表:
finacial_products表:
在資料庫中測試指令:
SELECT BATCH.*, CUSTOMER.username, CUSTOMER.acno, BATCHDETAIL.product_id, BATCHDETAIL.product_num FROM BATCH, CUSTOMER, BATCHDETAIL WHERE BATCH.cus_id = CUSTOMER.cus_id AND BATCHDETAIL.batch_id=BATCH.batch_id;
得到:
Batch.java
新增一句程式碼:
public class Batch { private int batch_id; private int cus_id; private String number; private Date createtime; private String note; private List<BatchDetail> batchDetials;
...
}
BatchDetail.java
public class BatchDetail { private int id; private int batch_id; private int product_id; private int product_num;
...
}
BatchItem.java
新增
//批次包含的理財產品訂購資訊 private List<BatchDetail> batchDetails;
BatchDatas.java
public class BatchDatas { private int batch_id; private int cus_id; private String number; private Date createtime; private String note; private Customer customer; private List<BatchDetail> batchDetails;
...
}
UserMapper.xml
<resultMap type="cn.com.mybatis.po.BatchItem" id="BatchAndBatchDetailResultMap" extends="BatchInfoMap"> <collection property="batchDetails" ofType="cn.com.mybatis.po.BatchDetail"> <!-- id:訂單明細的唯一標識 --> <id column="id" property="id"/> <result column="batch_id" property="batch_id"/> <result column="product_id" property="product_id"/> <result column="product_num" property="product_num"/> </collection> </resultMap> <select id="findBatchAndBatchDetail" resultMap="BatchAndBatchDetailResultMap"> SELECT BATCH.*, CUSTOMER.username, CUSTOMER.acno, BATCHDETAIL.product_id, BATCHDETAIL.product_num FROM BATCH, CUSTOMER, BATCHDETAIL WHERE BATCH.cus_id = CUSTOMER.cus_id AND BATCHDETAIL.batch_id=BATCH.batch_id </select>
MyBatisTest.java
@Test public void testfindBatchAndBatchDetail() throws Exception{ SqlSession sqlSession=dataConn.getSqlSession(); //呼叫userMapper的方法 BatchItem batchItem=sqlSession.selectOne("findBatchAndBatchDetail"); if(batchItem!=null){ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Customer customer = batchItem.getCustomer();//取出該批次的使用者資訊 //取出該批次訂購的理財產品資訊 List<BatchDetail> batchDetails = batchItem.getBatchDetails(); System.out.println("卡號為"+customer.getAcno()+"的名為" +customer.getUsername()+"的客戶:\n於" +sdf.format(batchItem.getCreatetime())+"採購了批次號為" +batchItem.getNumber()+"的一批理財產品,詳情如下:"); BatchDetail batchDetail = null; if(batchDetails!=null){ for (int i = 0; i < batchDetails.size(); i++) { batchDetail = batchDetails.get(i); System.out.println("id為"+batchDetail.getProduct_id() +"的理財產品"+batchDetail.getProduct_num()+"份"); } } } sqlSession.close(); }
測試結果:
DEBUG [main] - ==> Preparing: SELECT BATCH.*, CUSTOMER.username, CUSTOMER.acno, BATCHDETAIL.product_id,
BATCHDETAIL.product_num FROM BATCH, CUSTOMER, BATCHDETAIL WHERE BATCH.cus_id = CUSTOMER.cus_id AND
BATCHDETAIL.batch_id=BATCH.batch_id DEBUG [main] - ==> Parameters: DEBUG [main] - <== Total: 2 卡號為622848的名為Mr的客戶: 於2018-10-04 16:47:41採購了批次號為牛奶的一批理財產品,詳情如下: id為1的理財產品100份 id為2的理財產品50份 DEBUG [main] - Resetting autocommit to true on JDBC Connection [[email protected]]
多對多的查詢
Customer.java
public class Customer implements Serializable{ private int cus_id; private String username; private String acno; private String gender; private String phone; private List<Batch> batchList;
...
}
Batch.java
public class Batch { private int batch_id; private int cus_id; private String number; private Date createtime; private String note; private List<BatchDetail> batchDetials;
...
}
BatchDetail.java
public class BatchDetail { private int id; private int batch_id; private int product_id; private int product_num; private FinacialProduct finacialProduct;
...
}
FinacialProduct.java
public class FinacialProduct { private int id; private String name; private double price; private String detail; private String imgpath; private Date invattime;
...
}
UserMapper.xml
<resultMap type="cn.com.mybatis.po.Customer" id="UserAndProductsResultMap"> <!-- 客戶資訊 --> <result column="username" property="username"/> <result column="acno" property="acno"/> <!--批次訂單資訊,一個客戶對應多個訂單--> <collection property="batchList" ofType="cn.com.mybatis.po.Batch"> <id column="batch_id" property="batch_id"/> <result column="cus_id" property="cus_id"/> <result column="number" property="number"/> <result column="createtime" property="createtime" javaType="java.util.Date"/> <result column="note" property="note"/> <collection property="batchDetials" ofType="cn.com.mybatis.po.BatchDetail"> <!-- id:訂單明細的唯一標識 --> <id column="id" property="id"/> <result column="batch_id" property="batch_id"/> <result column="product_id" property="product_id"/> <result column="product_num" property="product_num"/> <association property="finacialProduct" javaType="cn.com.mybatis.po.FinacialProduct"> <id column="product_id" property="id"/> <result column="name" property="name"/> <result column="price" property="price"/> <result column="detail" property="detail"/> </association> </collection> </collection> </resultMap> <select id="findUserAndProducts" resultMap="UserAndProductsResultMap"> SELECT BATCH.*, CUSTOMER.username, CUSTOMER.acno, BATCHDETAIL.product_id, BATCHDETAIL.product_num, FINACIAL_PRODUCTS.name, FINACIAL_PRODUCTS.detail, FINACIAL_PRODUCTS.price FROM BATCH, CUSTOMER, BATCHDETAIL, FINACIAL_PRODUCTS WHERE BATCH.cus_id = CUSTOMER.cus_id AND BATCHDETAIL.batch_id=BATCH.batch_id AND FINACIAL_PRODUCTS.product_id=BATCHDETAIL.product_id; </select>
MybatisTest.java
@Test public void testfindCustomerAndProducts() throws Exception{ SqlSession sqlSession=dataConn.getSqlSession(); //呼叫userMapper的方法,獲取所有使用者資訊(以及從屬批次資訊) List<Customer> customerList=sqlSession.selectList("findUserAndProducts"); if(customerList!=null){ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Customer customer = null; for (int i = 0; i < customerList.size(); i++) { customer = customerList.get(i); //1.獲取使用者基本資訊 System.out.println("卡號為"+customer.getAcno()+"的名為" +customer.getUsername()+"的客戶:"); //2.獲取使用者下的所有批次訂單資訊 List<Batch> batchList=customer.getBatchList(); Batch batch = null; for (int j = 0; j < batchList.size(); j++) { batch = batchList.get(j); System.out.println("於" +sdf.format(batch.getCreatetime())+"採購了批次號為" +batch.getNumber()+"的一批理財產品,詳情如下:"); //3.獲取一個批次的明細 List<BatchDetail> batchDetails = batch.getBatchDetials(); BatchDetail batchDetail = null; FinacialProduct finacialProduct = null; for (int k = 0; k < batchDetails.size(); k++) { batchDetail = batchDetails.get(k); System.out.println("id為"+batchDetail.getProduct_id() +"的理財產品"+batchDetail.getProduct_num()+"份。"); //4.獲取每個批次明細中的理財產品詳細資訊 finacialProduct = batchDetail.getFinacialProduct(); System.out.println("該理財產品的詳細資訊為:\n" +"產品名稱:"+finacialProduct.getName() +"|產品價格:"+finacialProduct.getPrice() +"|產品簡介:"+finacialProduct.getDetail()); } } System.out.println("**************************************"); } } sqlSession.close(); }
實測結果:
DEBUG [main] - Setting autocommit to false on JDBC Connection [[email protected]] DEBUG [main] - ==> Preparing: SELECT BATCH.*, CUSTOMER.username, CUSTOMER.acno, BATCHDETAIL.product_id,
BATCHDETAIL.product_num, FINACIAL_PRODUCTS.name, FINACIAL_PRODUCTS.detail, FINACIAL_PRODUCTS.price FROM BATCH,
CUSTOMER, BATCHDETAIL, FINACIAL_PRODUCTS WHERE BATCH.cus_id = CUSTOMER.cus_id AND BATCHDETAIL.batch_id=
BATCH.batch_id AND FINACIAL_PRODUCTS.product_id=BATCHDETAIL.product_id; DEBUG [main] - ==> Parameters: DEBUG [main] - <== Total: 2 卡號為622848的名為Mr的客戶: 於2018-10-04 16:47:41採購了批次號為牛奶的一批理財產品,詳情如下: id為1的理財產品100份。 該理財產品的詳細資訊為: 產品名稱:花生|產品價格:12.0|產品簡介:酒鬼花生 id為2的理財產品50份。 該理財產品的詳細資訊為: 產品名稱:方便麵|產品價格:2.0|產品簡介:康師傅 **************************************
延遲載入
sqlMapConfig.xml
新增程式碼:
<settings> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/> </settings>
UserMapper.xml
<!-- 延遲載入的resultMap --> <resultMap id="BatchUserLazyLoadingResultMap" type="cn.com.mybatis.po.BatchItem"> <!-- 對訂單資訊進行對映配置 --> <id column="batch_id" property="batch_id"/> <result column="cus_id" property="cus_id"/> <result column="number" property="number"/> <result column="createtime" property="createtime" javaType="java.util.Date"/> <result column="note" property="note"/> <!-- 實現延遲載入使用者資訊 --> <association property="customer" javaType="cn.com.mybatis.po.Customer" select="findCustomerById" column="cus_id"> </association> </resultMap> <select id="findBatchUserLazyLoading" resultMap="BatchUserLazyLoadingResultMap"> SELECT * FROM BATCH </select> <select id="findCustomerById" parameterType="int" resultType="cn.com.mybatis.po.Customer"> SELECT * FROM CUSTOMER WHERE cus_id=#{id} </select>
MyBatisTest.java
@Test public void testFindBatchCustomerLazyLoading() throws Exception{ SqlSession sqlSession=dataConn.getSqlSession(); //呼叫userMapper的方法,獲取所有訂單資訊(未載入關聯的使用者資訊) List<BatchItem> batchItemList=sqlSession.selectList("findBatchUserLazyLoading"); BatchItem batchItem = null; Customer customer = null; for (int i = 0; i < batchItemList.size(); i++) { batchItem = batchItemList.get(i); System.out.println("訂單編號:"+batchItem.getNumber()); //執行getCustomer時才會去查詢使用者資訊,這裡實現了延遲載入 customer=batchItem.getCustomer(); System.out.println("訂購使用者姓名:"+customer.getUsername()); } sqlSession.close(); }
結果:
DEBUG [main] - Setting autocommit to false on JDBC Connection [[email protected]] DEBUG [main] - ==> Preparing: SELECT * FROM BATCH DEBUG [main] - ==> Parameters: DEBUG [main] - <== Total: 2 訂單編號:牛奶 DEBUG [main] - ==> Preparing: SELECT * FROM CUSTOMER WHERE cus_id=? DEBUG [main] - ==> Parameters: 1(Integer) DEBUG [main] - <== Total: 1 訂購使用者姓名:Mr 訂單編號:方便麵 訂購使用者姓名:Mr DEBUG [main] - Resetting autocommit to true on JDBC Connection [[email protected]] DEBUG [main] - Closing JDBC Connection [[email protected]] DEBUG [main] - Returned connection 2048425748 to pool.
Mappwe動態代理
建立新的mapper檔案
CustomerMapper.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="cn.com.mybatis.mapper.CustomerMapper"> <!-- 查詢使用者 --> <select id="findCustomerById" parameterType="int" resultType="cn.com.mybatis.po.Customer"> SELECT * FROM CUSTOMER WHERE cus_id=#{cus_id} </select> <!-- 新增使用者 --> <insert id="insertCustomer" parameterType="cn.com.mybatis.po.Customer"> INSERT INTO CUSTOMER(username,acno,gender,phone) value(#{username},#{acno},#{gender},#{phone}) </insert> <!-- 刪除使用者 --> <delete id="deleteCustomer" parameterType="java.lang.Integer"> DELETE FROM CUSTOMER WHERE cus_id=#{cus_id} </delete> <!-- 修改使用者 --> <update id="updateCustomerAcNo" parameterType="cn.com.mybatis.po.Customer" > UPDATE CUSTOMER SET acno = #{acno} WHERE cus_id=#{cus_id} </update> </mapper>
注意:引入檔案除非使用的是package方法
SqlMapConfig.xml
<mappers>
<mapper resource="sqlmap/UserMapper.xml"/>
<mapper resource="sqlmap/CustomerMapper.xml"/>
</mappers>
新建包以及介面
CustomerMapper.java
public interface CustomerMapper { //根據Id查詢使用者資訊 public Customer findCustomerById(int id) throws Exception; //新增使用者資訊 public void insertCustomer(Customer customer) throws Exception; //刪除使用者資訊 public void deleteCustomer(int id) throws Exception; //修改使用者資訊 public void updateCustomerAcNo(Customer customer) throws Exception; }
MyBatisTest.java
//動態代理 @Test public void testFindCustomerOnMapper() throws Exception{ SqlSession sqlSession=dataConn.getSqlSession(); //獲取Mapper代理 CustomerMapper customerMapper=sqlSession.getMapper(CustomerMapper.class); //執行Mapper代理物件的查詢方法 Customer customer=customerMapper.findCustomerById(1); System.out.println("使用者姓名:"+customer.getUsername()+"|" +"卡號:"+customer.getAcno()); sqlSession.close(); }
結果:
DEBUG [main] - Created connection 331510866. DEBUG [main] - Setting autocommit to false on JDBC Connection [[email protected]] DEBUG [main] - ==> Preparing: SELECT * FROM CUSTOMER WHERE cus_id=? DEBUG [main] - ==> Parameters: 1(Integer) DEBUG [main] - <== Total: 1 使用者姓名:Mr|卡號:622848 DEBUG [main] - Resetting autocommit to true on JDBC Connection [[email protected]] DEBUG [main] - Closing JDBC Connection [[email protected]] DEBUG [main] - Returned connection 331510866 to pool.