1.Mybatis多表查询

1.1 一对一查询

1.1.1 一对一查询的模型MapperScannerConfigurer

用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户

一对一查询的需求:查询一个订单,与此同时查询出该订单所属的用户

1.1.2一对一查询的语句

对应的sql语句:select * from orders o,user u where o.uid=u.id;

查询的结果如下:

1.1.3 创建Order和User实体

public class Order {

    private int id;
private Date ordertime;
private double total; //代表当前订单从属于哪一个客户
private User user;
} public class User { private int id;
private String username;
private String password;
private Date birthday; }

1.1.4 创建OrderMapper接口

public interface OrderMapper {
List<Order> findAll();
}

1.1.5 配置OrderMapper.xml

主键ID比较的特殊,因此使用id column

其他的用result

<?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.itheima.mapper.OrderMapper"> <resultMap id="orderMap" type="com.itheima.domain.Order">
<!--手动指定字段与实体属性的映射关系
column: 数据表的字段名称
property:实体的属性名称
-->
<id column="oid" property="id"></id>
<result column="ordertime" property="ordertime"></result>
<result column="total" property="total"></result>
<result column="uid" property="user.id"></result>
<result column="username" property="user.username"></result>
<result column="password" property="user.password"></result>
<result column="birthday" property="user.birthday"></result>
</resultMap>
<select id="findAll" resultMap="orderMap">
SELECT *,o.id oid FROM orders o,USER u WHERE o.uid=u.id
</select>
</mapper>

换种封装方式,将user单独配置了

        <id column="oid" property="id"></id>
<result column="ordertime" property="ordertime"></result>
<result column="total" property="total"></result>
<!--<result column="uid" property="user.id"></result>
<result column="username" property="user.username"></result>
<result column="password" property="user.password"></result>
<result column="birthday" property="user.birthday"></result>--> <!--
property: 当前实体(order)中的属性名称(private User user)
javaType: 当前实体(order)中的属性的类型(User)
-->
<association property="user" javaType="user">
<id column="uid" property="id"></id>
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="birthday" property="birthday"></result>
</association>

1.1.6 测试结果

    @Test
public void test1() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession(); OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
List<Order> orderList = mapper.findAll();
for (Order order : orderList) {
System.out.println(order);
} sqlSession.close();
}

1.2 一对多查询

1.2.1 一对多查询的模型

用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户

一对多查询的需求:查询一个用户,与此同时查询出该用户具有的订单

1.2.2 一对多查询的语句

SELECT *,o.id oid FROM USER u,orders o WHERE u.id=o.uid

查询的结果如下:

1.2.3 修改User实体

public class Order {

    private int id;
private Date ordertime;
private double total; //代表当前订单从属于哪一个客户
private User user;
} public class User { private int id;
private String username;
private String password;
private Date birthday;
//代表当前用户具备哪些订单
private List<Order> orderList;
}

1.2.4 创建UserMapper接口

public interface UserMapper {
List<User> findAll();
}

1.2.5 配置UserMapper.xml

<mapper namespace="com.itheima.mapper.UserMapper">
<resultMap id="userMap" type="com.itheima.domain.User">
<id column="uid" property="id"></id>
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="birthday" property="birthday"></result>
<!--配置集合信息
property:集合名称
ofType:当前集合中的数据类型
-->
<collection property="orderList" ofType="com.itheima.domain.Order">
<!--封装order的数据-->
<id column="oid" property="id"></id>
<result column="ordertime" property="ordertime"></result>
<result column="total" property="total"></result>
</collection>
</resultMap>
<select id="findAll" resultMap="userMap">
SELECT *,o.id oid FROM USER u,orders o WHERE u.id=o.uid
</select>
</mapper>

1.2.6 测试结果

    @Test
public void test2() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = mapper.findAll();
for (User user : userList) {
System.out.println(user);
} sqlSession.close();
}

1.3 多对多查询

1.3.1 多对多查询的模型

用户表和角色表的关系为,一个用户有多个角色,一个角色被多个用户使用

多对多查询的需求:查询用户同时查询出该用户的所有角色

核心就是user_rolse的两个外键

1.3.2 多对多查询的语句

对应的sql语句:   SELECT * FROM USER u,sys_user_role ur,sys_role r WHERE u.id=ur.userId AND ur.roleId=r.id

查询的结果如下:

1.3.3 创建Role实体,修改User实体

package com.itheima.domain;

public class Role {

    private int id;
private String roleName;
private String roleDesc; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getRoleName() {
return roleName;
} public void setRoleName(String roleName) {
this.roleName = roleName;
} public String getRoleDesc() {
return roleDesc;
} public void setRoleDesc(String roleDesc) {
this.roleDesc = roleDesc;
} @Override
public String toString() {
return "Role{" +
"id=" + id +
", roleName='" + roleName + '\'' +
", roleDesc='" + roleDesc + '\'' +
'}';
}
}
public class User {
private int id;
private String username;
private String password;
private Date birthday;
//代表当前用户具备哪些订单
private List<Order> orderList;
//代表当前用户具备哪些角色
private List<Role> roleList;
} public class Role { private int id;
private String rolename; }

1.3.4 添加UserMapper接口方法

public List<User> findUserAndRoleAll();

1.3.5 配置UserMapper.xml

 <!--自定义别名-->
<typeAliases>
<typeAlias type="com.itheima.domain.User" alias="user"></typeAlias>
<typeAlias type="com.itheima.domain.Order" alias="order"></typeAlias>
<typeAlias type="com.itheima.domain.Role" alias="role"></typeAlias>
</typeAliases>
    <resultMap id="userRoleMap" type="user">
<!--user的信息-->
<id column="userId" property="id"></id>
<result column="username" property="username"></result>
<result column="password" property="password"></result>
<result column="birthday" property="birthday"></result>
<!--user内部的roleList信息-->
<collection property="roleList" ofType="role">
<id column="roleId" property="id"></id>
<result column="roleName" property="roleName"></result>
<result column="roleDesc" property="roleDesc"></result>
</collection>
</resultMap> <select id="findUserAndRoleAll" resultMap="userRoleMap">
SELECT * FROM USER u,sys_user_role ur,sys_role r WHERE u.id=ur.userId AND ur.roleId=r.id
</select>

1.3.6 测试结果

    @Test
public void test3() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userAndRoleAll = mapper.findUserAndRoleAll();
for (User user : userAndRoleAll) {
System.out.println(user);
} sqlSession.close();
}

1.4 知识小结

MyBatis多表配置方式:

一对一配置:使用<resultMap>做配置

一对多配置:使用<resultMap>+<collection>做配置

多对多配置:使用<resultMap>+<collection>做配置

2.Mybatis的注解开发

2.1 MyBatis的常用注解

这几年来注解开发越来越流行,Mybatis也可以使用注解开发方式,这样我们就可以减少编写Mapper

映射文件了。我们先围绕一些基本的CRUD来学习,再学习复杂映射多表操作。

@Insert:实现新增

@Update:实现更新

@Delete:实现删除

@Select:实现查询

@Result:实现结果集封装

@Results:可以与@Result 一起使用,封装多个结果集

@One:实现一对一结果集封装

@Many:实现一对多结果集封装

2.2 MyBatis的增删改查

我们完成简单的user表的增删改查的操作

public class MyBatisTest {

    private UserMapper mapper;

    @Before
public void before() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
mapper = sqlSession.getMapper(UserMapper.class);
} @Test
public void testSave(){
User user = new User();
user.setUsername("tom");
user.setPassword("abc");
mapper.save(user);
} @Test
public void testUpdate(){
User user = new User();
user.setId(18);
user.setUsername("lucy");
user.setPassword("123");
mapper.update(user);
} @Test
public void testDelete(){
mapper.delete(18);
} @Test
public void testFindById(){
User user = mapper.findById(2);
System.out.println(user);
} @Test
public void testFindAll(){
List<User> all = mapper.findAll();
for (User user : all) {
System.out.println(user);
}
} }

配置UserMapper的接口

package com.itheima.mapper;

import com.itheima.domain.User;
import org.apache.ibatis.annotations.*; import java.util.List; public interface UserMapper { @Insert("insert into user values(#{id},#{username},#{password},#{birthday})")
public void save(User user); @Update("update user set username=#{username},password=#{password} where id=#{id}")
public void update(User user); @Delete("delete from user where id=#{id}")
public void delete(int id); @Select("select * from user where id=#{id}")
public User findById(int id); @Select("select * from user")
public List<User> findAll(); @Select("select * from user")
@Results({
@Result(id=true ,column = "id",property = "id"),
@Result(column = "username",property = "username"),
@Result(column = "password",property = "password"),
@Result(
property = "orderList",
column = "id",
javaType = List.class,
many = @Many(select = "com.itheima.mapper.OrderMapper.findByUid")
)
})
public List<User> findUserAndOrderAll(); @Select("SELECT * FROM USER")
@Results({
@Result(id = true,column = "id",property = "id"),
@Result(column = "username",property = "username"),
@Result(column = "password",property = "password"),
@Result(
property = "roleList",
column = "id",
javaType = List.class,
many = @Many(select = "com.itheima.mapper.RoleMapper.findByUid")
)
})
public List<User> findUserAndRoleAll(); }

修改MyBatis的核心配置文件,我们使用了注解替代的映射文件,所以我们只需要加载使用了注解的Mapper接口即可,或者指定扫描包含映射关系的接口所在的包也可以

    <!--加载映射关系-->
<mappers>
<!--指定接口所在的包-->
<package name="com.itheima.mapper"></package>
</mappers>

2.3 MyBatis的注解实现复杂映射开发

实现复杂关系映射之前我们可以在映射文件中通过配置<resultMap>来实现,使用注解开发后,我们可以使用@Results注解,@Result注解,@One注解,@Many注解组合完成复杂关系的配置

2.4 一对一查询

2.4.1 一对一查询的模型

用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户

一对一查询的需求:查询一个订单,与此同时查询出该订单所属的用户

2.4.2 一对一查询的语句

对应的sql语句:

select * from orders;

select * from user where id=查询出订单的uid;

2.4.3 创建Order和User实体

public class Order {

    private int id;
private Date ordertime;
private double total; //代表当前订单从属于哪一个客户
private User user;
} public class User { private int id;
private String username;
private String password;
private Date birthday; }

2.4.4 创建OrderMapper接口

public interface OrderMapper {
List<Order> findAll();
}

2.4.5 使用注解配置Mapper

    @Select("select *,o.id oid from orders o,user u where o.uid=u.id")
@Results({
@Result(column = "oid",property = "id"),
@Result(column = "ordertime",property = "ordertime"),
@Result(column = "total",property = "total"),
@Result(column = "uid",property = "user.id"),
@Result(column = "username",property = "user.username"),
@Result(column = "password",property = "user.password")
})
public List<Order> findAll();

对应的sql语句:

select * from orders;

select * from user where id=查询出订单的uid;
    @Select("select * from orders")
@Results({
@Result(column = "id",property = "id"),
@Result(column = "ordertime",property = "ordertime"),
@Result(column = "total",property = "total"),
@Result(
property = "user", //要封装的属性名称
column = "uid", //根据那个字段去查询user表的数据
javaType = User.class, //要封装的实体类型
//select属性 代表查询那个接口的方法获得数据
one = @One(select = "com.itheima.mapper.UserMapper.findById")
)
})
public List<Order> findAll();
public interface UserMapper {

    @Select("select * from user where id=#{id}")
User findById(int id); }

通过查询结果中的uid再进行查询,执行查询语句

2.4.6 测试结果

package com.itheima.test;

import com.itheima.domain.Order;
import com.itheima.domain.User;
import com.itheima.mapper.OrderMapper;
import com.itheima.mapper.UserMapper;
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.Before;
import org.junit.Test; import java.io.IOException;
import java.io.InputStream;
import java.util.List; public class MyBatisTest2 { private OrderMapper mapper; @Before
public void before() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
mapper = sqlSession.getMapper(OrderMapper.class);
} @Test
public void testSave(){
List<Order> all = mapper.findAll();
for (Order order : all) {
System.out.println(order);
}
} }

2.5 一对多查询

2.5.1 一对多查询的模型

用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户

一对多查询的需求:查询一个用户,与此同时查询出该用户具有的订单

select * from user;

select * from orders where uid=查询出用户的id;

2.5.3 修改User实体

public class Order {

    private int id;
private Date ordertime;
private double total; //代表当前订单从属于哪一个客户
private User user;
} public class User { private int id;
private String username;
private String password;
private Date birthday;
//代表当前用户具备哪些订单
private List<Order> orderList;
}

2.5.4 创建UserMapper接口

    public List<User> findUserAndOrderAll();

2.5.5 使用注解配置Mapper

public interface UserMapper {
@Select("select * from user")
@Results({
@Result(id=true ,column = "id",property = "id"),//主键
@Result(column = "username",property = "username"),
@Result(column = "password",property = "password"),
@Result(
property = "orderList",
column = "id",
javaType = List.class,
many = @Many(select = "com.itheima.mapper.OrderMapper.findByUid")
)
})
public List<User> findUserAndOrderAll();
}
public interface OrderMapper {
@Select("select * from orders where uid=#{uid}")
List<Order> findByUid(int uid); }

2.5.6 测试结果

public class MyBatisTest3 {

    private UserMapper mapper;

    @Before
public void before() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
mapper = sqlSession.getMapper(UserMapper.class);
} @Test
public void testSave(){
List<User> userAndOrderAll = mapper.findUserAndOrderAll();
for (User user : userAndOrderAll) {
System.out.println(user);
}
} }

2.6 多对多查询

2.6.1 多对多查询的模型

用户表和角色表的关系为,一个用户有多个角色,一个角色被多个用户使用

多对多查询的需求:查询用户同时查询出该用户的所有角色

2.6.2 多对多查询的语句

2.6.3 创建Role实体,修改User实体

public class User {
private int id;
private String username;
private String password;
private Date birthday; //代表当前用户具备哪些角色
private List<Role> roleList;
} public class Role { private int id;
private String rolename; }

2.6.4 添加UserMapper接口方法

    public List<User> findUserAndRoleAll();

2.6.5 使用注解配置Mapper

    @Select("SELECT * FROM USER")
@Results({
@Result(id = true,column = "id",property = "id"),
@Result(column = "username",property = "username"),
@Result(column = "password",property = "password"),
@Result(
property = "roleList",
column = "id",
javaType = List.class,
many = @Many(select = "com.itheima.mapper.RoleMapper.findByUid")
)
})
public List<User> findUserAndRoleAll();
public interface RoleMapper {

    @Select("SELECT * FROM sys_user_role ur,sys_role r WHERE ur.roleId=r.id AND ur.userId=#{uid}")
public List<Role> findByUid(int uid); }

2.6.6 测试结果

public class MyBatisTest4 {

    private UserMapper mapper;

    @Before
public void before() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
mapper = sqlSession.getMapper(UserMapper.class);
} @Test
public void testSave(){
List<User> userAndRoleAll = mapper.findUserAndRoleAll();
for (User user : userAndRoleAll) {
System.out.println(user);
}
} }

Mybatis的多表操作的更多相关文章

  1. 阶段3 1.Mybatis_09.Mybatis的多表操作_2 完成account表的建立及实现单表查询

    mybatis中的多表查询:         示例:用户和账户             一个用户可以有多个账户             一个账户只能属于一个用户(多个账户也可以属于同一个用户)    ...

  2. 阶段3 1.Mybatis_09.Mybatis的多表操作_1 mybatis表之间关系分析

    4.mybatis中的多表查询     表之间的关系有几种:         一对多         多对一         一对一         多对多     举例:         用户和订单 ...

  3. 阶段3 1.Mybatis_09.Mybatis的多表操作_8 mybatis多对多操作-查询角色获取角色下所属用户信息

    一个角色对应多个用户 生成getter和setter 查看两个表的数据 中间表定义了谁有角色,谁没有角色 根据中间表的关系,最终查询出来的列表的数据样子.这需要两个左外链接才能实现功能. 第一个左外链 ...

  4. 阶段3 1.Mybatis_09.Mybatis的多表操作_7 mybatis多对多准备角色表的实体类和映射配置

    创建Role表和user_role表 DROP TABLE IF EXISTS `role`; CREATE TABLE `role` ( `ID` int(11) NOT NULL COMMENT ...

  5. 阶段3 1.Mybatis_09.Mybatis的多表操作_6 分析mybatis多对多的步骤并搭建环境

    示例:用户和角色             一个用户可以有多个角色             一个角色可以赋予多个用户         步骤:             1.建立两张表:用户表,角色表    ...

  6. 阶段3 1.Mybatis_09.Mybatis的多表操作_3 完成account的一对一操作-通过写account的子类方式查询

    先把多表查询的sql语句写出来 想要显示的字段 创建一个AccountUser类 继承Account.这样它就会从父类上继承一些信息 这里只需要定义username和address就可以了 .然后生成 ...

  7. 阶段3 1.Mybatis_09.Mybatis的多表操作_9 mybatis多对多操作-查询用户获取用户所包含的角色信息

    sql语句以user作为主表 用户的全部信息,以为用户下的角色的.并不是所有的用户都有角色,有角色的就带角色.没角色的就为null 首先修改实体类 定义List<Role> 生成gette ...

  8. 阶段3 1.Mybatis_09.Mybatis的多表操作_5 完成user的一对多查询操作

    定义List<Account> accounts,生成getter和setter 复制AccountTest类改名UserTest类 修改测试类 还没封装所以Account的list都是n ...

  9. 阶段3 1.Mybatis_09.Mybatis的多表操作_4 完成account一对一操作-建立实体类关系的方式

    定义user的实体.然后生成getter和setter 定义一个可以封装Account和User的Map type这里虽然是account类型 这一段只能保证account的数据完成.并不能保证use ...

随机推荐

  1. 【目标检测】用Fast R-CNN训练自己的数据集超详细全过程

    目录: 一.环境准备 二.训练步骤 三.测试过程 四.计算mAP 寒假在家下载了Fast R-CNN的源码进行学习,于是使用自己的数据集对这个算法进行实验,下面介绍训练的全过程. 一.环境准备 我这里 ...

  2. DBA 的效率加速器——CloudQuery v1.3.2 上线!

    嘿,兄弟,我们好久不见,你在哪里 嘿,朋友,如果真的是你,请打声招呼 我说好久不见,你去哪里 你却对我说,我去江湖 我去看 CloudQuery v1.3.2,看看新增了哪些好用的小功能! 一.自动/ ...

  3. vue_webpack

    1.生成项目工程描述文件 npm init 2.安装webpack开发依赖 (本地安装):npm install -D 3.(webpack4.0版本以上安装webpack cli) npm inst ...

  4. 移动端时间回显iphone出现的问题

    new Date(item.startTime.replace(/-/g, '/') dateFormat('hh:mm', new Date(item.startTime.replace(/-/g, ...

  5. 最实用JS 留着学习

    1.A标签删除 function input(){    var b = window.confirm("确认要删除本条信息!");    if(b==true){     ret ...

  6. js中this指向的问题与联系

    前言 JavaScript 中最大的一个安全问题,也是最令人困惑的一个问题,就是在某些情况下this的值是如何确定的.有js基础的同学面对这个问题基本可以想到:this的指向和函数调用的方式相关.这当 ...

  7. 微信小程序:快速生成less文件类嵌套的结构

    全部选中标签结构,按住ctrl+shift+p,选中插件Generate CSS tree(提前安装CSS Tree),先删除undefined,将img替换成image,删除标签名view. 完整的 ...

  8. Docker-compose编排微服务顺序启动

    一.概述 docker-compose可以方便组合多个 docker 容器服务, 但是, 当容器服务之间存在依赖关系时, docker-compose 并不能保证服务的启动顺序.docker-comp ...

  9. JS动态获取select中被选中的option的值,并在控制台输出

    生活城市: <select id="province"> <option>河南省</option> <option>黑龙江省< ...

  10. kubernetes生产实践之redis-cluster

    方案一 自定义yaml文件安装redis cluster 背景 在Kubernetes中部署Redis集群面临挑战,因为每个Redis实例都依赖于一个配置文件,该文件可以跟踪其他集群实例及其角色.为此 ...