目录
一、简介
1、使用嵌套查询:
2、使用多个 SQL 语句:
3、使用关联查询:
4、使用自定义映射查询:
二、业务场景
三、示例
1、一对一查询
2、一对多查询
一、简介
MyBatis 是一个优秀的持久层框架,它提供了强大的支持来执行数据库操作,包括多表查询。多表查询是指从多个数据库表中检索数据的过程,这在实际的应用中非常常见。MyBatis 提供了多种方法来执行多表查询,以下是一些常见的技术和方法:
1、使用嵌套查询:
这是最基本的多表查询方法,通过在 SQL 语句中嵌套子查询来联合多个表的数据。例如,你可以在 SELECT 语句中使用子查询来从一个表中获取数据,然后再将其用于主查询中。这种方法在某些简单情况下是有效的,但对于复杂的多表查询可能会变得冗长和难以维护。
2、使用多个 SQL 语句:
在 MyBatis 中,你可以编写多个独立的 SQL 语句,每个语句都从一个表中检索数据,然后在 Java 代码中将这些数据组合起来。这通常需要在 Java 代码中手动执行每个查询并进行数据处理,但对于一些复杂的多表查询情况可能更加灵活。
3、使用关联查询:
MyBatis 支持使用关联查询来执行多表查询,特别是在映射文件中配置了表之间的关联关系。通过在 Mapper XML 文件中配置 association 或 collection 来表示表之间的关联关系,MyBatis 可以自动根据关系从多个表中检索数据并构造结果对象。
4、使用自定义映射查询:
有时候,多表查询的结果可能不适合于一个实体类,这时你可以使用自定义映射查询来将结果映射到一个 Map 或者其他自定义的数据结构中,以适应查询的需要。
二、业务场景
模拟的业务场景为订单与用户的关系,可以是一对一、一对多。
比如,一个用户有多个订单,一个订单只有一个用户。
还有就是用户与角色的关系,多个用户拥有多个角色,一个角色可以被多个用户拥有,一个用户可以拥有多个角色。
三、示例
1、一对一查询
案例:查询所有订单信息,关联查询下单用户信息。 注意:因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询。如果从用户信息出发查询用户下的订单信息则为一对多查询,因为一个用户可以下多个订单。
一对一查询的需求:查询一个订单,与此同时查询出该订单所属的用户
数据库:
对应的SQL语句:
select o.id,o.ordername,o.ordercount,s.studentname,s.address from orders o,student s where o.student_id = s.id
用户表student
public class Student {
private int id;
private String studentName;
private String gender;
private String address;
private String email;
private String remark;
public Student() {
}
public Student( String studentName, String gender, String address, String email, String remark) {
this.studentName = studentName;
this.gender = gender;
this.address = address;
this.email = email;
this.remark = remark;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
}
}
订单表order
public class Order {
private int id;
private String ordername;
private int ordercount;
private Student student;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getOrdername() {
return ordername;
}
public void setOrdername(String ordername) {
this.ordername = ordername;
}
public int getOrdercount() {
return ordercount;
}
public void setOrdercount(int ordercount) {
this.ordercount = ordercount;
}
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
}
StudentMapper.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="com.xinhua.mapper.StudentMapper">
<!--查询出每个用户的信息和对应的所有订单-->
<resultMap id="studentOrder" type="Student">
<id column="id" property="id"></id>
<result column="studentName" property="studentName"></result>
<result column="gender" property="gender"></result>
<result column="address" property="address"></result>
<collection property="listOrder" ofType="com.xinhua.domain.Order">
<id column="order_id" property="id"></id>
<result column="ordername" property="ordername"></result>
<result column="ordercount" property="ordercount"></result>
</collection>
</resultMap>
<select id="findStudentOrderAll" resultMap="studentOrder">
SELECT s.id,s.studentname,s.gender,s.address,o.id order_id,o.ordername,o.ordercount FROM student s LEFT JOIN Orders o ON s.id=o.student_id
</select>
</mapper>
mapper接口类
public interface StudentMapper {
public List<Student> findStudentOrderAll();
}
测试类:
public class TestDemo {
SqlSessionFactory ssf = null;
@Before
public void creatFactory(){
InputStream input = null;
try {
input = Resources.getResourceAsStream("SqlMapConfig.xml");
} catch (IOException e) {
e.printStackTrace();
}
ssf = new SqlSessionFactoryBuilder().build(input);
}
@Test
public void testMapper10() {
SqlSession sqlSession = ssf.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List<Student> students = mapper.findStudentOrderAll();
for (Student student : students){
System.out.println(student.getId()+","+student.getStudentName()+","+student.getGender()+","+student.getAddress());
List<Order> listOrder = student.getListOrder();
for (Order order : listOrder){
System.out.println(" "+order.getOrdername()+","+order.getOrdercount());
}
}
}
2、一对多查询
用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户
一对多查询的需求:查询一个用户,与此同时查询出该用户具有的订单
主查询表:订单表
关联查询表:用户表、订单明细表、商品表
订单表
用户表
商品表
订单明细表
对应的SQL语句:
SELECT orders.id o_id, orders.ordername, student.studentname, student.gender, orderdetail.id od_id, orderdetail.items_count, orderdetail.items_all_price , items.id it_id, items.items_name, items.items_price FROM ORDERs,student,orderdetail,items WHERE orders.student_id = student.id AND orders.id = orderdetail.orders_id AND orderdetail.items_id = items.id
用户表
相比之前一对一,变化在student类多了一个List<Order> orderList
public class Student {
private int id;
private String studentName;
private String gender;
private String address;
private String email;
private String remark;
private List<Order> listOrder;
public Student() {
}
public Student( String studentName, String gender, String address, String email, String remark) {
this.studentName = studentName;
this.gender = gender;
this.address = address;
this.email = email;
this.remark = remark;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public List<Order> getListOrder() {
return listOrder;
}
public void setListOrder(List<Order> listOrder) {
this.listOrder = listOrder;
}
}
Order:
public class Order {
private int id;
private String ordername;
private int ordercount;
private Student student;
private List<OrderDetail> orderDetailList;
public List<OrderDetail> getOrderDetailList() {
return orderDetailList;
}
public void setOrderDetailList(List<OrderDetail> orderDetailList) {
this.orderDetailList = orderDetailList;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getOrdername() {
return ordername;
}
public void setOrdername(String ordername) {
this.ordername = ordername;
}
public int getOrdercount() {
return ordercount;
}
public void setOrdercount(int ordercount) {
this.ordercount = ordercount;
}
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
}
商品表items
private int id;
private String items_name;
private int items_price;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getItems_name() {
return items_name;
}
public void setItems_name(String items_name) {
this.items_name = items_name;
}
public int getItems_price() {
return items_price;
}
public void setItems_price(int items_price) {
this.items_price = items_price;
}
}
订单明细表
public class OrderDetail {
private int id;
private int items_count;
private int items_all_price;
private Order order;
private List<Items> listItems;
public List<Items> getListItems() {
return listItems;
}
public void setListItems(List<Items> listItems) {
this.listItems = listItems;
}
public Order getOrder() {
return order;
}
public void setOrder(Order order) {
this.order = order;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getItems_count() {
return items_count;
}
public void setItems_count(int items_count) {
this.items_count = items_count;
}
public int getItems_all_price() {
return items_all_price;
}
public void setItems_all_price(int items_all_price) {
this.items_all_price = items_all_price;
}
}
OrderMapper.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="com.xinhua.mapper.OrderMapper">
<resultMap id="orderStudentDetailItems" type="com.xinhua.domain.Order">
<id column="o_id" property="id"></id>
<result column="ordername" property="ordername"></result>
<association property="student" javaType="Student">
<result column="studentName" property="studentName"></result>
<result column="gender" property="gender"></result>
</association>
<!-- 一对多关联映射 -->
<collection property="orderDetailList" ofType="com.xinhua.domain.OrderDetail">
<id column="od_id" property="id"></id>
<result column="items_count" property="items_count"></result>
<result column="items_all_price" property="items_all_price"></result>
<collection property="listItems" ofType="com.xinhua.domain.Items">
<id column="it_id" property="id"></id>
<result column="items_name" property="items_name"></result>
<result column="items_price" property="items_price"></result>
</collection>
</collection>
</resultMap>
<select id="findOrderStudentDetailItems" resultMap="orderStudentDetailItems">
SELECT
orders.id o_id,
orders.ordername,
student.studentname,
student.gender,
orderdetail.id od_id,
orderdetail.items_count,
orderdetail.items_all_price ,
items.id it_id,
items.items_name,
items.items_price
FROM ORDERs,student,orderdetail,items
WHERE orders.student_id = student.id
AND orders.id = orderdetail.orders_id
AND orderdetail.items_id = items.id
</select>
</mapper>
mapper接口类
public interface OrderMapper {
public List<Order> findOrderStudentDetailItems();
}
测试类:
public class TestDemo {
SqlSessionFactory ssf = null;
@Before
public void creatFactory(){
InputStream input = null;
try {
input = Resources.getResourceAsStream("SqlMapConfig.xml");
} catch (IOException e) {
e.printStackTrace();
}
ssf = new SqlSessionFactoryBuilder().build(input);
}
@Test
public void testMapper11() {
SqlSession sqlSession = ssf.openSession();
OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
List<Order> orderList = mapper.findOrderStudentDetailItems();
for (Order order : orderList){
System.out.println(order.getId()+","+order.getOrdername()+","+order.getOrdercount()+","+order.getStudent().getStudentName());
List<OrderDetail> orderDetailList = order.getOrderDetailList();
for (OrderDetail orderDetail : orderDetailList){
System.out.println(" "+orderDetail.getId()+","+orderDetail.getItems_count()+","+orderDetail.getItems_all_price());
List<Items> list = orderDetail.getListItems();
for (Items listItems : list){
System.out.println(" "+listItems.getId()+","+listItems.getItems_name()+","+listItems.getItems_price());
}
}
}
}