Mybatis关联查询一对一和一对多的实现_4. mybatis 实现一对一查询和一对多关联查询分别有儿种方式,的?(8分)_擦肩而过的博客-程序员秘密

技术标签: MyBatis  

出处http://blog.csdn.net/evankaka

  本文主要讲了使用Mybatis实现关联查询,分为一对一和一对多两种情况,最后并对ResultMap进行一个简要说明。

本文工程免费下载

一、创建表、分析

下面是两表,一个是顾客表,一个是车票表。一个顾客可以对应多张车票,但是一张车票只能对应一个顾客

 t_customer:顾客表,一个顾客可以对应多张车票

t_ticket:车票表,一张车票只能对应一个顾客

1、创建数据表及插入初始数据

创建数据表

[sql]  view plain   copy
  在CODE上查看代码片 派生到我的代码片
  1. use test;  
  2. DROP TABLE IF EXISTS t_customer;  
  3. CREATE TABLE t_customer(  
  4. customerId INT PRIMARY KEY AUTO_INCREMENT,  
  5. customerName VARCHAR(20) NOT NULL,  
  6. customerTel INT NOT NULL  
  7. )ENGINE=InnoDB DEFAULT CHARSET=utf8;  
  8.   
  9. DROP TABLE IF EXISTS t_ticket;  
  10. CREATE TABLE t_ticket(  
  11. ticketId INT PRIMARY KEY  AUTO_INCREMENT,  
  12. ticketAddress VARCHAR(50) NOT NULL,  
  13. ticketPrice INT NOT NULL,  
  14. ticketCId INT NOT NULL  
  15. )ENGINE=InnoDB DEFAULT CHARSET=utf8;  

插入数据:

[java]  view plain   copy
  在CODE上查看代码片 派生到我的代码片
  1. use test;  
  2.   
  3. insert into t_customer values(1,'小王',1888327654);  
  4. insert into t_customer values(2,'天天',3456546354);  
  5. insert into t_customer values(3,'阿大',123345566);  
  6.   
  7. insert into  t_ticket values(1,'武汉到重庆',100,1);  
  8. insert into  t_ticket values(2,'北京到上海',200,1);  
  9. insert into  t_ticket values(3,'深圳到广州',50,1);  

传统的联合查询的方法

[sql]  view plain   copy
  在CODE上查看代码片 派生到我的代码片
  1. select c.*,t.* from t_customer c  JOIN t_ticket t ON (c.customerId=t.ticketCId) where c.customerName ='小王';  

结果如下:


二、工程创建

1、新建java工程,导入需要的包,最后整个工程目录 如下:


2、创建表对应的类:

Customer.java:

[java]  view plain   copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.mucfc.model;  
  2. import java.util.List;  
  3. /** 
  4.  *顾客信息类 
  5.  *@author linbingwen 
  6.  *@2015年5月13日8:30:12 
  7.  */  
  8. public class Customer {  
  9.     private Integer customerId;  
  10.     private String customerName;  
  11.     private Integer customerTel;  
  12.     private List<Ticket> tickets;//使用一个List来表示车票  
  13.   
  14.     public List<Ticket> getTickets() {  
  15.         return tickets;  
  16.     }  
  17.   
  18.     public void setTickets(List<Ticket> tickets) {  
  19.         this.tickets = tickets;  
  20.     }  
  21.   
  22.     public Integer getCustomerId() {  
  23.         return customerId;  
  24.     }  
  25.   
  26.     public void setCustomerId(Integer customerId) {  
  27.         this.customerId = customerId;  
  28.     }  
  29.   
  30.     public String getCustomerName() {  
  31.         return customerName;  
  32.     }  
  33.   
  34.     public void setCustomerName(String customerName) {  
  35.         this.customerName = customerName;  
  36.     }  
  37.   
  38.     public Integer getCustomerTel() {  
  39.         return customerTel;  
  40.     }  
  41.   
  42.     public void setCustomerTel(Integer customerTel) {  
  43.         this.customerTel = customerTel;  
  44.     }  
  45.   
  46.     @Override  
  47.     public String toString() {  
  48.         return "Customer [customerId=" + customerId + ", customerName="  
  49.                 + customerName + ", customerTel=" + customerTel+"]";  
  50.     }  
  51.   
  52.   
  53.   
  54. }  

Ticket.java:

[java]  view plain   copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.mucfc.model;  
  2. /** 
  3.  *车票信息类 
  4.  *@author linbingwen 
  5.  *@2015年5月13日8:30:12 
  6.  */  
  7. public class Ticket {  
  8.     private Integer ticketId;  
  9.     private String ticketAddress;  
  10.     private Integer ticketPrice;  
  11.     private Integer ticketCId;  
  12.     private Customer customer;//使用一个customer来表示顾客  
  13.   
  14.     public Customer getCustomer() {  
  15.         return customer;  
  16.     }  
  17.   
  18.     public void setCustomer(Customer customer) {  
  19.         this.customer = customer;  
  20.     }  
  21.   
  22.     public Integer getTicketId() {  
  23.         return ticketId;  
  24.     }  
  25.   
  26.     public void setTicketId(Integer ticketId) {  
  27.         this.ticketId = ticketId;  
  28.     }  
  29.   
  30.     public String getTicketAddress() {  
  31.         return ticketAddress;  
  32.     }  
  33.   
  34.     public void setTicketAddress(String ticketAddress) {  
  35.         this.ticketAddress = ticketAddress;  
  36.     }  
  37.   
  38.     public Integer getTicketPrice() {  
  39.         return ticketPrice;  
  40.     }  
  41.   
  42.     public void setTicketPrice(Integer ticketPrice) {  
  43.         this.ticketPrice = ticketPrice;  
  44.     }  
  45.   
  46.     public Integer getTicketCId() {  
  47.         return ticketCId;  
  48.     }  
  49.   
  50.     public void setTicketCId(Integer ticketCId) {  
  51.         this.ticketCId = ticketCId;  
  52.     }  
  53.   
  54.     @Override  
  55.     public String toString() {  
  56.         return "Ticket [ticketId=" + ticketId + ", ticketAddress="  
  57.                 + ticketAddress + ", ticketPrice=" + ticketPrice  
  58.                 + ", ticketCId=" + ticketCId + "]";  
  59.     }  
  60.   
  61.   
  62. }  
注意Customer.java:中有个list,list来存放车票,Ticket.java中有一个 customer。

3、定义sql映射文件

(1)首先是一对多关联:

MyBatis中使用collection标签来解决一对一的关联查询,collection标签可用的属性如下:

  • property:指的是集合属性的值
  • ofType:指的是集合中元素的类型
  • column:所对应的外键字段名称
  • select:使用另一个查询封装的结果

[html]  view plain   copy
  在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  
  3. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
  4. <mapper namespace="com.mucfc.model.CustomerMapper">  
  5.  <!-- 定义数据库字段与实体对象的映射关系 -->  
  6.     <resultMap type="Customer" id="customerBean">  
  7.         <id column="customerId" property="customerId"/>  
  8.         <result column="customerName" property="customerName"/>  
  9.         <result column="customerTel" property="customerTel"/>       
  10.         <!-- 一对多的关系 -->  
  11.         <!-- property: 指的是集合属性的值, ofType:指的是集合中元素的类型 -->  
  12.         <collection property="tickets" ofType="Ticket">  
  13.             <id column="ticketId" property="ticketId"/>  
  14.             <result column="ticketAddress" property="ticketAddress"/>  
  15.             <result column="ticketPrice" property="ticketPrice"/>  
  16.             <result column="ticketCId" property="ticketCId"/>  
  17.         </collection>  
  18.     </resultMap>    
  19.       
  20.     <!-- 根据id查询Person, 关联将Orders查询出来 -->  
  21.     <select id="selectCustomerByName" parameterType="string" resultMap="customerBean">  
  22.         select c.*,t.* from t_customer c,t_ticket t  where  c.customerId=t.ticketCId and c.customerName =#{customerName};  
  23.     </select>  
  24.       
  25.  </mapper>  

(2)接着是一对一关联:

MyBatis中使用association标签来解决一对一的关联查询,association标签可用的属性如下:

  • property:对象属性的名称
  • javaType:对象属性的类型
  • column:所对应的外键字段名称
  • select:使用另一个查询封装的结果

[html]  view plain   copy
  在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  
  3. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
  4. <mapper namespace="com.mucfc.model.TicketMapper">  
  5.     <!-- 定义数据库字段与实体对象的映射关系  -->  
  6.     <resultMap type="Ticket" id="ticketBean">  
  7.         <id column="ticketId" property="ticketId" />  
  8.         <result column="ticketAddress" property="ticketAddress" />  
  9.         <result column="ticketPrice" property="ticketPrice" />  
  10.         <result column="ticketCId" property="ticketCId" />  
  11.         <!-- 一对一的关系 -->  
  12.         <!-- property: 指的是属性的值, javaType:指的是元素的类型 -->  
  13.         <association property="customer" javaType="Customer">  
  14.             <id column="customerId" property="customerId" />  
  15.             <result column="customerName" property="customerName" />  
  16.             <result column="customerTel" property="customerTel" />  
  17.         </association>  
  18.     </resultMap>  
  19.     <!-- 根据id查询ticket, 关联将Customer查询出来 -->  
  20.     <select id="selectTicketById" parameterType="int" resultMap="ticketBean">  
  21.         select c.*,t.* from t_customer c,t_ticket t where  
  22.         c.customerId=t.ticketCId and t.ticketId =#{ticketId}  
  23.     </select>  
  24. </mapper>  

4、总配置文件

[html]  view plain   copy
  在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <!DOCTYPE configuration  
  3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"  
  4. "http://mybatis.org/dtd/mybatis-3-config.dtd">  
  5. <!-- 这是根标签  -->  
  6. <configuration>  
  7.     <!-- 设置别名  -->  
  8.     <typeAliases>  
  9.         <typeAlias alias="Customer" type="com.mucfc.model.Customer"/>  
  10.         <typeAlias alias="Ticket" type="com.mucfc.model.Ticket" />  
  11.     </typeAliases>  
  12.       
  13.     <!-- 配置数据源相关的信息  -->  
  14.     <environments default="development">  
  15.         <environment id="development">  
  16.             <transactionManager type="JDBC" />  
  17.             <dataSource type="POOLED">  
  18.             <property name="driver" value="com.mysql.jdbc.Driver"/>  
  19.              <property name="url" value="jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8"/>   
  20.             <property name="username" value="root"/>   
  21.             <property name="password" value="christmas258@"/>    
  22.             </dataSource>  
  23.         </environment>  
  24.     </environments>  
  25.       
  26.     <!-- 列出映射文件 -->  
  27.     <mappers>  
  28.         <mapper resource="com/mucfc/model/CustomerMapper.xml" />  
  29.         <mapper resource="com/mucfc/model/TicketMapper.xml" />   
  30.     </mappers>  
  31. </configuration>  

5、测试

[java]  view plain   copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.mucfc.test;  
  2.   
  3. import java.io.Reader;  
  4. import java.util.List;  
  5.   
  6. import org.apache.ibatis.io.Resources;  
  7. import org.apache.ibatis.session.SqlSession;  
  8. import org.apache.ibatis.session.SqlSessionFactory;  
  9. import org.apache.ibatis.session.SqlSessionFactoryBuilder;  
  10.   
  11. import com.mucfc.model.Customer;  
  12. import com.mucfc.model.Ticket;  
  13.   
  14. public class Test {  
  15.     private static SqlSessionFactory sqlSessionFactory;  
  16.     private static Reader reader;  
  17.     static {  
  18.         try {  
  19.             reader = Resources.getResourceAsReader("mybatis-config.xml");  
  20.             sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);  
  21.         } catch (Exception e) {  
  22.             e.printStackTrace();  
  23.         }  
  24.     }  
  25.   
  26.     /* 
  27.      * 一对一关联查询 
  28.      */  
  29.     public static void selectTicketById(int id) {  
  30.         SqlSession session = null;  
  31.         try {  
  32.             session = sqlSessionFactory.openSession();  
  33.             Ticket ticket = (Ticket) session.selectOne(  
  34.                     "com.mucfc.model.TicketMapper.selectTicketById", id);  
  35.             if (ticket == null)  
  36.                 System.out.println("null");  
  37.             else {  
  38.                 System.out.println(ticket);  
  39.                 System.out.println(ticket.getCustomer());  
  40.             }  
  41.         } finally {  
  42.             session.close();  
  43.         }  
  44.     }  
  45.   
  46.     /* 
  47.      * 一对多关联查询 
  48.      */  
  49.     public static void selectCustomerByName(String string) {  
  50.         SqlSession session = null;  
  51.         try {  
  52.             session = sqlSessionFactory.openSession();  
  53.             Customer customer = (Customer) session  
  54.                     .selectOne(  
  55.                             "com.mucfc.model.CustomerMapper.selectCustomerByName",  
  56.                             string);  
  57.             if (customer == null)  
  58.                 System.out.println("null");  
  59.             else {  
  60.                 System.out.println(customer);  
  61.                 List<Ticket> tickets = customer.getTickets();  
  62.                 for (Ticket ticket : tickets) {  
  63.                     System.out.println(ticket);  
  64.                 }  
  65.             }  
  66.         } finally {  
  67.             session.close();  
  68.         }  
  69.     }  
  70.   
  71.     public static void main(String[] args) {  
  72.         System.out.println("==============一对一查询,根据车票来查顾客===============");  
  73.         selectTicketById(1);  
  74.         System.out.println("==============多对一查询,根据顾客来查车票===============");  
  75.         selectCustomerByName("小王");  
  76.   
  77.     }  
  78.   
  79. }  

结果:


结果显示,查询正确。

三、ResultMap标签                        

           MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType是直接表示返回类型的,而resultMap则是对外部ResultMap的引用,但是resultType跟resultMap不能同时存在。在MyBatis进行查询映射的时候,其实查询出来的每一个属性都是放在一个对应的Map里面的,其中键是属性名,值则是其对应的值。当提供的返回类型属性是resultType的时候,MyBatis会将Map里面的键值对取出赋给resultType所指定的对象对应的属性。所以其实MyBatis的每一个查询映射的返回类型都是ResultMap,只是当我们提供的返回类型属性是resultType的时候,MyBatis对自动的给我们把对应的值赋给resultType所指定对象的属性,而当我们提供的返回类型是resultMap的时候,因为Map不能很好表示领域模型,我们就需要自己再进一步的把它转化为对应的对象,这常常在复杂查询中很有作用。

当Java接口与XML文件在一个相对路径下时,可以不在myBatis配置文件的mappers中声明:

[html]  view plain   copy
  在CODE上查看代码片 派生到我的代码片
  1. <!-- 列出映射文件 -->  
  2. <mappers>  
  3.     <mapper resource="com/mucfc/model/CustomerMapper.xml" />  
  4.     <mapper resource="com/mucfc/model/TicketMapper.xml" />   
  5. </mappers>  

SQL 映射XML 文件一些初级的元素:

[sql]  view plain   copy
  在CODE上查看代码片 派生到我的代码片
  1. 1. cache – 配置给定模式的缓存  
  2. 2. cache-ref – 从别的模式中引用一个缓存  
  3. 3. resultMap – 这是最复杂而却强大的一个元素了,它描述如何从结果集中加载对象  
  4. 4. sql – 一个可以被其他语句复用的SQL 块  
  5. 5. insert – 映射INSERT 语句  
  6. 6. update – 映射UPDATE 语句  
  7. 7. delete – 映射DELEETE 语句  
  8. 8. select - 映射SELECT语句  


resultMap 是MyBatis 中最重要最强大的元素了。你可以让你比使用JDBC 调用结果集省掉90%的代码,也可以让你做许多JDBC 不支持的事。现实上,要写一个等同类似于交互的映射这样的复杂语句,可能要上千行的代码。ResultMaps 的目的,就是这样简单的语句而不需要多余的结果映射,更多复杂的语句,除了只要一些绝对必须的语句描述关系以外,再也不需要其它的。
resultMap属性:type为java实体类;id为此resultMap的标识。
resultMap可以设置的映射:

[sql]  view plain   copy
  在CODE上查看代码片 派生到我的代码片
  1. 1. constructor – 用来将结果反射给一个实例化好的类的构造器  
  2. a) idArg – ID 参数;将结果集标记为ID,以方便全局调用  
  3. b) arg –反射到构造器的通常结果  
  4. 2. id – ID 结果,将结果集标记为ID,以方便全局调用  
  5. 3. result – 反射到JavaBean 属性的普通结果  
  6. 4. association – 复杂类型的结合;多个结果合成的类型  
  7. a) nested result mappings – 几resultMap 自身嵌套关联,也可以引用到一个其它上  
  8. 5. collection –复杂类型集合a collection of complex types  
  9. 6. nested result mappings – resultMap 的集合,也可以引用到一个其它上  
  10. 7. discriminator – 使用一个结果值以决定使用哪个resultMap  
  11. a) case – 基本一些值的结果映射的case 情形  
  12. i. nested result mappings –一个case 情形本身就是一个结果映射,因此也可以包括一些相同的元素,也可以引用一个外部resultMap。  
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zwj1030711290/article/details/53365362

智能推荐

国外物联网平台(1):亚马逊AWS IoT_aotun7642的博客-程序员秘密

国外物联网平台(1)——亚马逊AWS IoT马智平台定位AWS IoT是一款托管的云平台,使互联设备可以轻松安全地与云应用程序及其他设备交互。AWS IoT可支持数十亿台设备和数万亿条消息,并且可以对这些消息进行处理并将其安全可靠地路由至 AWS 终端节点和其他设备。应用程序可以随时跟踪所有设备并与其通信,即使这些设备未处于连接状态也不例外。使用AWS ...

Android记录25-WebView实现离线缓存阅读_webview 实现_IT_xiao小巫的博客-程序员秘密

Android记录25-WebView实现离线缓存阅读前言本篇博客要实现的是一个离线下载和离线阅读的功能,这是很多阅读类app都常见的一个功能,典型的应用就是网易新闻。什么是离线下载?其实这个概念是比较模糊,是离线之后下载呢,还是下载之后离线,但稍微有点脑子的人都知道没有网络之后怎么下载呢?所以离线下载这个功能是”在有网络的情况下,把资源下载到本地“,离线阅读就是”在没有网络或者网络不好的时候,阅读

关于Typora官网进不去的状况_奔跑的小贝壳的博客-程序员秘密

请大家试试:Typora-Mirror 发行版 - Gitee.com

Objective—C中的排序及Compare陷阱_weixin_33794672的博客-程序员秘密

campare陷阱NSString有多个compare相关方法:- (NSComparisonResult)compare:(NSString *)string;- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask;- (NSComparisonResu...

在线创建ios正式打包的p12私钥证书和证书profile文件_生成p12证书_handsome0916的博客-程序员秘密

ios开发的正式打包,需要p12私钥证书和证书profile文件。这两个文件卡住了很多想要了解ios开发的同学们。官方提供的方法是需要使用mac电脑,先创建csr文件,再去苹果开发者中心生成cer证书,然后再将cer证书导入mac系统,再从mac系统导出p12,整个过程不仅需要mac电脑,而且不熟悉操作的人还容易出错,非常麻烦。

知乎大神YaqiLYU关于tracking方向的2013-2016趋势总览!!!强烈推荐!!!_mini猿要成长QAQ的博客-程序员秘密

真真实实的学习tracking也有半年了,tracking的主流趋势年年改变,每年都有新的突破。从CT、IVT到struck,到TLD、到CF,再到火热的CNN也应用到了tracking领域。作为初入领域的学习者,需要在打好机器学习各种算法的基础上,了解每年顶级会议以及期刊中tracking的发展方向,尽力把握前沿动态。下面是对知乎大神YaqiLYU的年年总结的转载,对于把握从2013年到20

随便推点

java-字符串数组转化为int数组_java字符串数组转化为整数型数组_U12Euphoria的博客-程序员秘密

public class MyDemo { public static void main(String[] args) { String s = "91 27 46 38 50"; //获取字符串中的每一个数字. String[] strArr = s.split(" "); //创建一个int类型的数组. int [] numberArr = new int[strArr.length]; //把

DPDK系列之七:OVS-DPDK的在CentOS安装和测试_ovs dpdk安装centos_cloudvtech的博客-程序员秘密

一、前言根据文章《DPDK系列之六:qemu-kvm网络后端的加速技术》,OVS-DPDK可以给虚拟机的部署密度和虚拟机网络性能的提升带来帮助。本文将介绍如何编译和安装DPDK以及如何使用DPDK提升网络性能:OS:CentOS 7.4.1708OVS:2.8.1DPDK:17.08.1转载自https://blog.csdn.net/cloudvtech二、操作系统和DPDK的安装2.1 系统配...

bzoj4519: [Cqoi2016]不同的最小割【最小割树】_图中至多有n-1种最小割_Neo__Z的博客-程序员秘密

题目大意:求一张无向图中两两点之间不同的最小割的种数,n&amp;lt;=850,m&amp;lt;=8500;解题思路:即是要构造最小割树,统计不同边权的数量。 有一个结论:任意两点之间的最小割,不同的只有n-1个(然而不会证明……) 构造最小割树方法如下(分治+最小割): 1.集合中随便找两个点,求这两点的最小割 2.用求出的最小割更新s,t两个集合之间点的最小割(或者可以直接建边,那么最...

java 生日日期类型编程_Java日期时间API系列34-----Jdk8中java.time包中的新的日期时间API类应用,使用Period一行代码计算生日。..._王锦添的博客-程序员秘密

通过Java日期时间API系列9-----Jdk8中java.time包中的新的日期时间API类的Period和Duration的区别中得知,Period可以比较2个日期相差的年月日。年龄计算是2个日期相差的年的值,具体还要根据月日微调,如果小于生日年龄减1。下面使用Period可以非常方便的计算年龄。1.使用Period一行代码计算生日核心代码就是一行代码:Period.between(birt...

mybatis入门--mapper代理方式开发_weixin_30908103的博客-程序员秘密

不使用代理开发 之前,我们说了如何搭建mybatis框架以及我们使用mybatis进行简单的增删改查.现在,我们一起来构建一个dao层的完整代码.并用@test来模拟service层对dao层进行一下调用. 其实构建很简单,跟我们之前的差不多.如果不是为了演示其中的弊端,我甚至都懒得再写这些东西了.我们这次用UserDao为大家演示....

推荐文章

热门文章

相关标签