Mybatis 关联查询

多表查询是在企业中必不可少的,无论多么简单的项目里都会出现多表查询操作。因为只要是关系型数据库,在设计表时都需要按照范式进行设计,为了减少数据冗余,都会拆成多个表。当需要表中数据时,在进行联合查询。

在MySQL学习时,知道表之间关系分为:一对一、一对多、多对多。这三种关系又细分为单向和双向。如果学习的是Hibernate框架,必须要严格区分开表之间的关系,然后才能使用Hibernate框架。但是在MyBatis框架中只有两种情况:当前表对应另外表是一行数据还是多行数据。转换到实体类上:当前实体类包含其他实体类一个对象还是多个对象。再转换到MyBatis的映射文件上:在标签里面使用还是标签就可以。

所以:在学习MyBatis多表查询时其实就是在学习标签和标签。其中如果一个实体类关联另一个实体类的一个对象使用。如果一个实体类关联另一个实体类的List集合对象,需要使用

所以分析的思路是:先分析需求->分析数据库设计对应关系->创建实体类->根据实体类关联属性类型决定使用哪个标签。

Mybatis 关联查询_第1张图片

这两个标签根据编写的SQL,分为N+1查询和联合查询两种方式。两种方式优缺点:

  • N+1方式:

优点:SQL简单。支持延迟加载。

缺点:多做N次查询。

  • 联合查询方式:

优点:一次查询。

缺点:SQL相对复杂。不支持延迟加载。

MyBatis多表查询时一定需要使用标签,因为标签和标签是的子标签。所以数据库设计时列名和实体类的属性名是否相同无所谓了,下面在设计数据库时按照数据库设计的命名规范进行设计。

案例:

  1. 数据库准备 tb_dept部门表 tb_customer客户表 tb_address地址表

create table tb_dept(
    dep_id int(11) primary key auto_increment COMMENT '部门主键',
    dep_name  varchar(32) COMMENT '部门名称',
    dept_addr varchar(255) COMMENT '部门地址'
);

insert into tb_dept value(DEFAULT,'教学部','无忧工业园');
insert into tb_dept value(DEFAULT,'行政部','无忧工业园');
insert into tb_dept value(DEFAULT,'财务部','无忧工业园');

create table tb_customer(
    id int(11) PRIMARY key auto_increment,
    name varchar(32) COMMENT '姓名',
    username varchar(32) COMMENT '登录名',
    password varchar(32) COMMENT '登录密码'
);

create table tb_address(
    id int(11) PRIMARY key auto_increment,
    province varchar(32) COMMENT '省',
    city varchar(32) COMMENT '市',
    address varchar(255) COMMENT '具体地址',
    customer_id int(11) REFERENCES tb_customer(id)
);

insert into tb_customer values (DEFAULT,'张三','zhangsan','123');
insert into tb_customer values (DEFAULT,'李四','李四','123');
insert into tb_customer values (DEFAULT,'王五','wangwu','123');

insert into tb_address values(DEFAULT,"广东","广州市","越秀区",1)
insert into tb_address values(DEFAULT,"广东","广州市","越秀区",1)
insert into tb_address values(DEFAULT,"广东","广州市","天河区",2)
insert into tb_address values(DEFAULT,"广东","广州市","天河区",2)
insert into tb_address values(DEFAULT,"广东","广州市","白云区",3)
insert into tb_address values(DEFAULT,"广东","广州市","白云区",3)
  1. Address实体类 没有在文档里面粘贴getter/setter和toString(),太占地方 需要读者自己编写(要加空构造器)

import java.io.Serializable;
import java.util.Objects;

public class Address implements Serializable {
    private Integer id;
    private String province;
    private String city;
    private String address;

    private Customer customer;
}
  1. Customer实体类 没有在文档里面粘贴getter/setter和toString(),太占地方 需要读者自己编写(要加空构造器)

import java.io.Serializable;
import java.util.List;
import java.util.Objects;

public class Customer implements Serializable {
    private Integer id;
    private String name;
    private String username;
    private String password;

    private List
addressList;     }

案例实现功能:

  1. 查询全部地址,同时查询地址对应的客户数据

当存在调用和被调用关系时,按照正常编程习惯,都是先编写被调用方。

N+1次实现 当查询Customer表中N调数据时,需要编写1条查询全部的SQL,和N条根据外键列值作为另一张表主键查询条件的N条SQL语句。

被调用方 客户

创建接口com.bjsxt.mapper.CustomerMapper

package com.xu.mapper;

import com.xu.pojo.Customer;

import java.util.List;

/**
 * 客户访问接口
 */
public interface CustomerMapper {
    Customer selectAllById();
}

在包com.xu.mappers下创建CustomerMapper.xml文件





    

创建接口com.bjsxt.mapper.AddressMapper

import com.xu.pojo.Address;

import java.util.List;

/**
 * 地址数据访问接口
 */
public interface AddressMapper {
    List
selectAll(); }

在包com.xu.mapper下创建.AddressMapper.xml文件




    
    
        
        
        
        
        
        
        
    
    

一次实现

接口com.bjsxt.mapper.AddressMapper 添加方法

   List
selectAll2();

AddressMapper.xml配置





    

    
        
        
        
        
        
        
            
            
            
            
        
    
    

    

    
  
  1. 查询全部客户,同时查询客户对应的地址集合

一次查询实现

CustomerMapper接口添加方法

 List selectAll2();

配置CustomerMapper.xml




    
    
        
        
        
        
        
        
            
            
            
            
        
    

    

你可能感兴趣的:(mybatis,mybatis,java,mysql)