mybatis-基于xml的多表查询

Posted 拾亿~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mybatis-基于xml的多表查询相关的知识,希望对你有一定的参考价值。

mybatis动态SQL

简化SQL

Sql 中可将重复的 sql 提取出来,使用时用include 引用即可,最终达到 sql 重用的目的。

<!--    抽取重复片段-->
<sql id="selectAll" >
  select * from user 
</sql>
<!--使用重复片段-->
<select id="findUserAll" resultType="user">
--         select * from user
  <include refid="selectAll"></include>
</select>

标签:抽取重复SQL片段。id属性:指定重复片段的名称。

标签:引用抽取的重复片段。refix属性:该属性值为标签id属性值。

mybatis多表查询

一对一查询

示例:一个gameAccount(游戏账号)与player(玩家)为一对一关系

实现:

  1. 数据库中game_account(账号表)包含player(玩家表)的主键作为外键。
    • 一的一方的主键作为一的一方的外键。
  2. 实体类中GameAccount(账号实体类)包含Player(玩家实体类)的引用。
    • 主表(直接查询的表)包含从表(关联查询的表)实体类的引用。

需求:查询账号,并且关联查询用户。

玩家表:

create table player(
	pid int primary key auto_increment,
  pname varchar(20),
  psex varchar(20)
);

账号表:

create table game_account(
	gid int primary key auto_increment,
  gusername varchar(20),
  gpassword varchar(20),
  gpid int,
  foreign key (gpid) references player(pid)
);

玩家实体类:

package com.mybatis_xml.pojo;
import java.io.Serializable;
public class Player implements Serializable {
  private Integer pid;
  private String pname;
  private String psex;
  //getter,setter,toString
}

账号实体类:

package com.mybatis_xml.pojo;
import java.io.Serializable;
public class GameAccount implements Serializable {
    private Integer gid;
    private String gusername;
    private String gpassword;
    private Integer gpid;//player表的主键
    //一对一关系:主表(直接查询的表)包含从表(关联查询的表)实体类的引用
    private Player player;
    //getter,setter,toString
}

IGameAccountMapper接口:

package com.mybatis_xml.mapper;
import com.mybatis_xml.pojo.GameAccount;
import java.util.List;

public interface IGameAccountMapper {
    //账号和玩家为一对一关系;查询账号,关联查询玩家
    List<GameAccount> findAll();
}

IGameAccountMapper.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.mybatis_xml.mapper.IGameAccountMapper">
<!-- resultMap标签用于指定数据库表与实体的一一映射关系
    id属性:给定一个唯一标识,是给select标签resultMap属性引用的。
    type属性:接口对应的实体类的全限定类名或者配置了别名后的别名
-->
    <resultMap id="gameAccountMap" type="gameAccount">
<!--id标签用于指定主键对应
    property属性:用于指定实体类属性名称
    column属性:用于指定数据库列名
-->
        <id property="gid" column="gid"></id>
<!--result标签指定非主键对应-->
        <result column="gusername" property="gusername"></result>
        <result column="gpassword" property="gpassword"></result>
        <result column="gpid" property="gpid"></result>
<!--association标签配置GameAccount对象中player对象引用的映射关系:一般为一对一配置
    property属性:用于指定被引用实体类属性名称
    javaType属性:用于指定被引用实体的Java类全限定类名
-->
        <association property="player" javaType="player">
            <id property="pid" column="pid"></id>
            <result property="pname" column="pname"></result>
            <result property="psex" column="psex"></result>
        </association>
    </resultMap>
<!--
SELECT
  p.*,g.gid,g.gpid,g.gpassword,g.gusername
FROM
  game_account g,
  player p
WHERE
  g.gpid = p.pid
-->
<!--
SELECT 查询的字段
FROM 表 表别名
-->
    <select id="findAll" resultMap="gameAccountMap">
        SELECT
            p.*,g.gid,g.gpid,g.gpassword,g.gusername
        FROM
            game_account g,
            player p
        WHERE
            g.gpid = p.pid
    </select>
</mapper>

OneToOne.class测试类:

import com.mybatis_xml.mapper.IGameAccountMapper;
import com.mybatis_xml.pojo.GameAccount;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class OneToOne {
    private InputStream is;
    private SqlSession session;
    private SqlSessionFactoryBuilder sqlSessionFactoryBuilder;
    private SqlSessionFactory factory;
    private IGameAccountMapper gameAccountMapper;

    @Before
    public void init() throws IOException {
        String resource = "mybatis-config.xml";
        // 读取mybatis配置文件
        is = Resources.getResourceAsStream(resource);
        // 创建构造者对象
        sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        // 创建工厂对象
        factory = sqlSessionFactoryBuilder.build(is);
        // 创建SqlSession对象
        session = factory.openSession();
        // 创建IUserMapper对象
        gameAccountMapper = session.getMapper(IGameAccountMapper.class);
    }
    @After
    public void destory() throws IOException {
        session.close();
        is.close();
    }

    //测试查询所有
    @Test
    public void testFindAll() throws IOException {
        List<GameAccount> pgs = gameAccountMapper.findAll();
        System.out.println(pgs);
    }
}

多对一查询

示例:一个Book(书籍)与Own(所有者)为多对一关系。

实现:

  1. 数据库中book(书籍表)包含own(所有者表)的主键作为外键。
    • 把一的一方的主键作为多的一方的外键。
  2. 实体类中Own(所有者实体类)包含Book(书籍实体类)的集合引用。
    • 主表(直接查询的表)实体类包含从表(关联查询的表)实体类集合的引用。

需求:查寻所有者,并且关联查询书籍。

所有者表:

create table own(
	oid int primary key auto_increment,
	oname varchar(20)
);

书籍表:

create table book(
 bid int primary key auto_increment,
 bname varchar(20),
 boid int,
 foreign key(boid) references own(oid)
);

书籍实体类:

package com.mybatis_xml.pojo;
import java.io.Serializable;
public class Book implements Serializable {
    private Integer bid;
    private String bname;
    private Integer boid;
  //getter,setter,toString省略
}

所有者实体类:

package com.mybatis_xml.pojo;
import java.io.Serializable;
import java.util.List;
public class Own implements Serializable {
    private Integer oid;
    private String oname;
    //多对一:主表包含从表的集合引用
    private List<Book> books;
  //getter,setter,toString省略
}

IOwnMapper接口:

package com.mybatis_xml.mapper;
import com.mybatis_xml.pojo.Own;
import java.util.List;
public interface IOwnMapper {
  //所有者与书籍为一对多关系:查询所有者,关联查询书籍
    List<Own> findAll();
}

IOwnMapper.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.mybatis_xml.mapper.IOwnMapper">
    <resultMap id="ownMap" type="own">
        <id column="oid" property="oid"></id>
        <result column="oname" property="oname"></result>
<!--collection标签配置own对象中Book集合的映射关系:一般为一对多配置
    property属性:指定集合变量名称
    ofType属性:指定集合元素类型,全限定类名
-->
        <collection property="books" ofType="book">
            <id property="bid" column="bid"></id>
            <result property="bname" column="bname"></result>
            <result property="boid" column="boid"></result>
        </collection>
    </resultMap>

    <select id="findAll" resultMap="ownMap">
        select
               o.*,b.bid,b.boid,b.bname
        from own o
            left outer
                join book b
                    on b.boid = o.oid;
    </select>
</mapper>

ManyToOne.class测试类:

import com.mybatis_xml.mapper.IOwnMapper;
import com.mybatis_xml.pojo.Own;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class ManyToOne {

    private InputStream is;
    private SqlSession session;
    private SqlSessionFactoryBuilder sqlSessionFactoryBuilder;
    private SqlSessionFactory factory;
    private IOwnMapper ownMapper;

    @Before
    public void init() throws IOException {
        String resource = "mybatis-config.xml";
        // 读取mybatis配置文件
        is = Resources.getResourceAsStream(resource);
        // 创建构造者对象
        sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        // 创建工厂对象
        factory = sqlSessionFactoryBuilder.build(is);
        // 创建SqlSession对象
        session = factory.openSession();
        // 创建IUserMapper对象
        ownMapper = session.getMapper(IOwnMapper.class);
    }
    @After
    public void destory() throws IOException {
        session.close();
        is.close();
    }

    //测试查询所有
    @Test
    public void testFindAll() throws IOException {
        List<Own> pgs = ownMapper.findAll();
        System.out.println(pgs);
    }
}

多对多查询

示例:一个Student(学生)对应多个(Teacher)老师,一个 、Teacher(老师)对应多个Student(学生),所以学生和老师是多对多关系。

实现:

  • 数据库中student(学生表)的主键,teacher(老师表)的主键,作为s_t(学生_老师表)的外键。
    • 抽取两个主键,作为新的表的外键
  • 实体类中Student(学生实体类)引用Teacher(老师实体类)的集合,Teacher(老师实体类)引用Student(学生实体类)的集合。
    • 主从表各包含对对方实体集合的引用

student表:

create table student(
 sid int primary key auto_increment,
 sname varchar(20)
);

teacher表:

create table teacher(
	tid int primary key auto_increment,
	tname varchar(20)
);

中间表:

-- 注意:st_sid需要添加括号
create table st(
	st_sid int,
	st_tid int,
	foreign key (st_sid) references student(sid),
	foreign key (st_tid) references teacher(tid)
);

Teacher实体类:

package com.mybatis_xml.pojo;
import java.io.Serializable;
import java.util.List;

public class Teacher implements Serializable {
    private Integer tid;
    private String tname;
    //多对多:主表和从表各包含对方集合的引用
    private List<Student> students;
    //setter,getter,toString省略
}

Student实体类:

package com.mybatis_xml.pojo;
import java.io.Serializable;
import java.util.List;

public class Student implements Serializable {
    private Integer sid;
    private String sname;
    //多对多:主表和从表各包含对方集合的引用
    private List<Teacher> teachers;
    //setter,getter,toString省略
}

IStudentMapper接口:

package com.mybatis_xml.mapper;
import com.mybatis_xml.pojo.Student;
import java.util.List;
public interface IStudentMapper {
    //多对多:查询学生,关联查询老师
    List<Student> findAll();
}

ITeacherMappper接口:

package com.mybatis_xml.mapper;
import com.mybatis_xml.pojo.Teacher;
import java.util.List;
public interface ITeacherMapper {
    //多对多:查询老师,关联查询学生
    List<Teacher> findAll();
}

IStudentMapper.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.mybatis_xml.mapper.IStudentMapper">
    <resultMap id="studentMap" type="student">
        <id property="sid" column="sid"></id>
        <result property="sname" column="sname"></result>
        <collection property="teachers" ofType="teacher">
            <id property="tid" column="tid"></id>
            <result property="tname" column="tname"></result>
        </collection>
    </resultMap>

    <select id="findAll" resultMap="studentMap">
        select s.*,t.*
        from student s
        left outer join st on s.sid=st.st_sid
        left outer join teacher t on t.tid=st.st_tid
    </select>
</mapper>

ITeacherMapper.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.mybatis_xml.mapper.ITeacherMapper">
    <resultMap id="teacherMap" type="teacher">
        <id property="tid" column="tid"></id>
        <result property="tname" column="tname"></result>
        <collection property="students" ofType="student">
            <id property="sid" column="sid"></id>
            <result property="sname" column="sname"></result>
        </collection>
    </resultMap>

    <select id="findAll" resultMap="teacherMap">
        select t.*,s.*
        from student s
                 left outer join st on s.sid=st.st_sid
                 left outer join teacher t on t.tid=st.st_tid
    </select>
</mapper>

ManyToMany.class测试类:

import com.mybatis_xml.mapper.IOwnMapper;
import com.mybatis_xml.mapper.IStudentMapper;
import com.mybatis_xml.mapper.ITeacherMapper;
import com.mybatis_xml.pojo.Student;
import com.mybatis_xml.pojo.Teacher;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class ManyToMany {
    private InputStream is;
    private SqlSession session;
    private SqlSessionFactoryBuilder sqlSessionFactoryBuilder;
    private SqlSessionFactory factory;
    private IStudentMapper studentMapper;
    private ITeacherMapper teacherMapper;

    @Before
    public void init() throws IOException {
        String resource = "mybatis-config.xml";
        // 读取mybatis配置文件
        is = Resources.getResourceAsStream(resource);
        // 创建构造者对象
        sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        // 创建工厂对象
        factory = sqlSessionFactoryBuilder.build(is);
        // 创建SqlSession对象
        session = factory.openSession();
        // 创建IUserMapper对象
        studentMapper = session.getMapper(IStudentMapper.class);
        teacherMapper = session.getMapper(ITeacherMapper.class);
    }
    @After
    public void destory() throws IOException {
        session.close();
        is.close();
    }

    @Test
    public void testFindAllStudent(){
        List<Student> students = studentMapper.findAll();
        System.out.println(students);
    }

    @Test
    public void testFindAllTeacher(){
        List<Teacher> teachers = teacherMapper.findAll();
        System.out.println(teachers);
    }
}

以上是关于mybatis-基于xml的多表查询的主要内容,如果未能解决你的问题,请参考以下文章

MyBatis

11-表之间关系

SpringBoot集成Mybatis实现多表查询的两种方式(基于xml)

什么?mybatis-plus的多表查询,你还在写sql语句?!CRUD2多表联查的三种方式

Mybatis 的多表操作

MyBatis的多表联合查询