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>
mybatis多表查询
一对一查询
示例:一个gameAccount(游戏账号)与player(玩家)为一对一关系
实现:
- 数据库中game_account(账号表)包含player(玩家表)的主键作为外键。
- 一的一方的主键作为一的一方的外键。
- 实体类中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(所有者)为多对一关系。
实现:
- 数据库中book(书籍表)包含own(所有者表)的主键作为外键。
- 把一的一方的主键作为多的一方的外键。
- 实体类中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的多表查询的主要内容,如果未能解决你的问题,请参考以下文章
SpringBoot集成Mybatis实现多表查询的两种方式(基于xml)