一:阐述
我们在日常操作的时候,很多时候会遇到多表联合查询,由于参照物的不通 ,会出现一对一、一对多的情况。比如说:账号信息和订单表,从订单表角度和账号信息是一对一的情况(一个订单只能是一个用户的情况),从用户的角度,就会出现一对多的情况(一个用户会有多个订单)。
二、一对一:
需要清楚:
现在我们创建2个表:
1 CREATE TABLE username( 2 id INT PRIMARY KEY AUTO_INCREMENT, 3 NAME VARCHAR(20), 4 sex VARCHAR(20) 5 ); 6 7 CREATE TABLE orders ( 8 id INT PRIMARY KEY AUTO_INCREMENT, 9 num VARCHAR(20), 10 user_id INT 11 );
创建订单表和用户表。插入一些值。
参照物是:订单
联合查询sql:
1 SELECT o.`id`AS oid ,o.`num` AS num ,o.`user_id` AS uid,u.* FROM orders AS o, username AS u WHERE o.user_id=u.id;
结果:
第一个方法:
首先映射类:
orders类:
1 package jd.com.ou; 2 3 public class orders { 4 private String num; 5 private Integer user_id; 6 7 public void setNum(String num) { 8 this.num = num; 9 } 10 11 public void setUser_id(Integer user_id) { 12 this.user_id = user_id; 13 } 14 15 public Integer getUser_id() { 16 return user_id; 17 } 18 19 public String getNum() { 20 return num; 21 } 22 }
user类:
1 package jd.com.ou; 2 3 public class user { 4 private String name; 5 private String sex; 6 7 public void setName(String name) { 8 this.name = name; 9 } 10 11 public void setSex(String sex) { 12 this.sex = sex; 13 } 14 15 public String getName() { 16 return name; 17 } 18 19 public String getSex() { 20 return sex; 21 } 22 }
注意:并不是为了联合查询就需要建立这2个表,而是这2个类是user表和ordes表的projo类。
然后我们定义返回数据的projo类:
1 package jd.com.ou; 2 3 public class customuo extends orders { 4 private String name; 5 private String sex; 6 7 public void setSex(String sex) { 8 this.sex = sex; 9 } 10 11 public void setName(String name) { 12 this.name = name; 13 } 14 15 public String getSex() { 16 return sex; 17 } 18 19 public String getName() { 20 return name; 21 } 22 23 @Override 24 public String toString() { 25 return this.name+this.sex+this.getNum(); 26 } 27 }
mapper配置文件:
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <mapper namespace="jd.com.ou.oumapper"> 6 <select id="findOrderAndUser" resultType="jd.com.ou.customuo" parameterType="jd.com.ou.customuo"> 7 SELECT o.`id`AS oid ,o.`num` AS num ,o.`user_id` AS uid,u.* FROM orders AS o, username AS u WHERE o.`user_id`=u.id; 8 </select> 9 </mapper>
注意在sql语句中,where关键字中,前面定义列的别名,在where的表达是中不能用列的别名。
mapper接口:
1 package jd.com.ou; 2 3 import java.util.List; 4 5 public interface oumapper { 6 List<customuo> findOrderAndUser(); 7 }
测试类:
1 package jd.com.ou; 2 3 import org.apache.ibatis.io.Resources; 4 import org.apache.ibatis.session.SqlSession; 5 import org.apache.ibatis.session.SqlSessionFactory; 6 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 7 import org.junit.jupiter.api.Test; 8 9 import java.io.IOException; 10 import java.io.InputStream; 11 12 import java.util.List; 13 14 public class testDemo { 15 16 @Test 17 public void testDemo() throws IOException { 18 String reource="SqlMapConfig.xml"; 19 InputStream inp= Resources.getResourceAsStream(reource); 20 SqlSessionFactory sqlSessionFactory= new SqlSessionFactoryBuilder().build(inp); 21 SqlSession sqlSession=sqlSessionFactory.openSession(); 22 oumapper oum=sqlSession.getMapper(oumapper.class); 23 List<customuo> list=oum.findOrderAndUser(); 24 System.out.println(list); 25 } 26 }
注意:
这里我们的定义接收返回值的customuo类中,我们并没有将user的字段设置成customuo的属性。为什么呢??
因为我们没有传入参数,也就是说,无法设置user类到customuo的属性中,这样,如果调用customuo的user属性会是对象的默认值:null。
那如果我们想使用user字段该怎么操作呢?
第二种方法:实际生产用的情况。
将orders类的字段和user对象的设置成新类custuo2。
1 package jd.com.ou; 2 3 public class custuo2 { 4 private String num; 5 private Integer user_id; 6 private user us; 7 private Integer id; 8 9 public void setId(Integer id) { 10 this.id = id; 11 } 12 13 public Integer getId() { 14 return id; 15 } 16 17 public void setUs(user us) { 18 this.us = us; 19 } 20 21 public user getUs() { 22 return us; 23 } 24 25 public void setNum(String num) { 26 this.num = num; 27 } 28 29 public void setUser_id(Integer user_id) { 30 this.user_id = user_id; 31 } 32 33 public Integer getUser_id() { 34 return user_id; 35 } 36 37 public String getNum() { 38 return num; 39 } 40 41 @Override 42 public String toString() { 43 return this.getNum()+" "+this.getId()+" "+this.getUser_id()+" "+this.getUs().toString(); 44 } 45 }
mapper配置文件,resultType的类型改为:resultMap该属性字段值是resultMap标签的id值。
mapper配置文件:
1 <select id="findOrderAndUserObj" resultMap="UserObj"> 2 SELECT o.`id`AS oid ,o.`num` AS num ,o.`user_id` AS uid,u.* FROM orders AS o, username AS u WHERE o.`user_id`=u.id; 3 </select> 4 <!-- 5 type:是我们resultMap类型的泛型值。 6 id:是别人调用该resultMap的唯一标识。 7 --> 8 <resultMap id="UserObj" type="jd.com.ou.custuo2" > 9 <!-- 10 id:是主键列 11 result:非主键列 12 property:是类的属性名称 13 javaType:是属性名称的类型。 14 column:是实际数据库列的名称. 15 --> 16 <id property="id" javaType="int" column="oid"/> 17 <result property="user_id" javaType="int" column="uid"/> 18 <result javaType="string" property="num" column="num"/> 19 <association property="us" javaType="jd.com.ou.user" > 20 <!-- 21 标签:association 是引用外部对象 我们写projo类的时候使用。 22 其中properites 是类中引用的属性的名称 23 javaType:引用对象的类型。 24 --> 25 <id javaType="int" property="id" column="id"/> 26 <result property="name" javaType="string" column="name"/> 27 <result property="sex" javaType="string" column="sex"/> 28 </association> 29 </resultMap>
三:一对多
一对多,那自定义 接收类中,对于一对多种的多的类型写成泛型的List对象。
1、需要注意的是在mapper文件中接收集合的是使用标签<collection>
2、需要注意的是collection标签的 需要设置属性ofType而不是javaType。该属性值是你自定义的接受类的定义的泛型的类型。
mapper文件:
1 <select id="findOrderAndUserObjlIST" resultMap="UseList" > 2 SELECT o.`id`AS oid ,o.`num` AS num ,o.`user_id` AS uid,u.* FROM orders AS o, username AS u WHERE o.`user_id`=u.id; 3 </select> 4 <resultMap id="UseList" type="jd.com.ou.ouList" > 5 <id property="id" column="id" javaType="int"/> 6 <result property="name" javaType="string" column="name" /> 7 <result property="sex" column="sex" javaType="string"/> 8 <collection property="ord" ofType="jd.com.ou.orders" > 9 <id property="id" column="oid"/> 10 <result property="num" column="num"/> 11 <result property="user_id" column="uid"/> 12 13 </collection> 14 </resultMap>
接口文件:
1 package jd.com.ou; 2 3 import java.util.List; 4 5 public interface oumapper { 6 List<customuo> findOrderAndUser(); 7 List<customuo> findOrderAndUserObj(); 8 List<ouList> findOrderAndUserObjlIST(); 9 }
自定义接收类:
1 package jd.com.ou; 2 3 import java.util.List; 4 5 public class ouList { 6 private Integer id; 7 private String name; 8 private String sex; 9 private List<orders> ord; 10 11 public void setOrd(List<orders> ord) { 12 this.ord = ord; 13 } 14 15 public List<orders> getOrd() { 16 return ord; 17 } 18 19 public void setId(Integer id) { 20 this.id = id; 21 } 22 23 public Integer getId() { 24 return id; 25 } 26 27 public void setName(String name) { 28 this.name = name; 29 } 30 31 public String getName() { 32 return name; 33 } 34 35 public void setSex(String sex) { 36 this.sex = sex; 37 } 38 39 public String getSex() { 40 return sex; 41 } 42 43 @Override 44 public String toString() { 45 return this.getSex()+" "+this.getId()+" "+this.getName()+" "+this.getOrd().toString(); 46 } 47 }
测试类:
1 @Test 2 public void testdemo2() throws IOException { 3 String resource="SqlMapConfig.xml"; 4 InputStream inp=Resources.getResourceAsStream(resource); 5 SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inp); 6 SqlSession sqlSession=sqlSessionFactory.openSession(); 7 oumapper oum=sqlSession.getMapper(oumapper.class); 8 List<ouList> list=oum.findOrderAndUserObjlIST(); 9 System.out.println(list); 10 }
注意:一对一的时候,我们使用的2种方法。
其中第一种方法需要注意的是:不设置projo类型的字段,否则获取不到值,这是因为自定义的projo引用,这时候需要通过set方法才能加载内存如果不设置的话,会使用其默认值。
第二种方法,通过标签<association>来实现projo类型的引用的。一对多也是。推荐第二种方法。