14、MyBatis的多表操作

1.MyBatis的多表操作

1.1 一对一查询
  1. 一对一查询的模型

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

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

  2. 一对一查询的语句

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

    查询的结果如下:

  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;
    }
  4. 创建OrderMapper接口

    public interface OrderMapper {
    List<Order> findAll();
    }
  5. 配置OrderMapper.xml

    <mapper namespace="com.itheima.mapper.OrderMapper">
    <resultMap id="orderMap" type="com.itheima.domain.Order">
    <!--
    property: 当前实体(order)中的属性名称(private User user)
    javaType: 当前实体(order)中的属性的类型(User)
    -->
    <result 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 * from orders o,user u where o.uid=u.id
    </select>
    </mapper>

    其中<resultMap>还可以配置如下:

    <resultMap id="orderMap" type="com.itheima.domain.Order">
    <result property="id" column="id"></result>
    <result property="ordertime" column="ordertime"></result>
    <result property="total" column="total"></result>
    <!--
    property: 当前实体(order)中的属性名称(private User user)
    javaType: 当前实体(order)中的属性的类型(User)
    -->
    <association property="user" javaType="com.itheima.domain.User">
    <result column="uid" property="id"></result>
    <result column="username" property="username"></result>
    <result column="password" property="password"></result>
    <result column="birthday" property="birthday"></result>
    </association>
    </resultMap>
  6. 测试结果

    OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
    List<Order> all = mapper.findAll();
    for(Order order : all){
    System.out.println(order);
    }

1.2 一对多查询
  1. 一对多查询的模型

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

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

  2. 一对多查询的语句

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

    查询的结果如下:

  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;
    }
  4. 创建UserMapper接口

    public interface UserMapper {
    List<User> findAll();
    }
  5. 配置UserMapper.xml

    <mapper namespace="com.itheima.mapper.UserMapper">
    <resultMap id="userMap" type="com.itheima.domain.User">
    <!—手动指定字段与实体属性的映射关系-->
    <result column="id" property="id"></result>
    <result column="username" property="username"></result>
    <result column="password" property="password"></result>
    <result column="birthday" property="birthday"></result>
    <collection property="orderList" ofType="com.itheima.domain.Order">
    <result column="oid" property="id"></result>
    <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 left join orders o on u.id=o.uid
    </select>
    </mapper>
  6. 测试结果

    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    List<User> all = mapper.findAll();
    for(User user : all){
    System.out.println(user.getUsername());
    List<Order> orderList = user.getOrderList();
    for(Order order : orderList){
    System.out.println(order);
    }
    System.out.println("----------------------------------");
    }

1.3 多对多查询
  1. 多对多查询的模型

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

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

  2. 多对多查询的语句

    对应的sql语句:select u.*,r.*,r.id rid from user u left join user_role ur on u.id=ur.user_id

    inner join role r on ur.role_id=r.id;

    查询的结果如下:

  3. 创建Role实体,修改User实体

    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;
    }
  4. 添加UserMapper接口方法

    List<User> findAllUserAndRole();
  5. 配置UserMapper.xml

    <resultMap id="userRoleMap" type="com.itheima.domain.User">
    <result column="id" property="id"></result>
    <result column="username" property="username"></result>
    <result column="password" property="password"></result>
    <result column="birthday" property="birthday"></result>
    <collection property="roleList" ofType="com.itheima.domain.Role">
    <result column="rid" property="id"></result>
    <result column="rolename" property="rolename"></result>
    </collection>
    </resultMap>
    <select id="findAllUserAndRole" resultMap="userRoleMap">
    select u.*,r.*,r.id rid from user u left join user_role ur on u.id=ur.user_id
    inner join role r on ur.role_id=r.id
    </select>
  6. 测试结果

    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    List<User> all = mapper.findAllUserAndRole();
    for(User user : all){
    System.out.println(user.getUsername());
    List<Role> roleList = user.getRoleList();
    for(Role role : roleList){
    System.out.println(role);
    }
    System.out.println("----------------------------------");
    }

1.4 小结

MyBatis多表配置方式:

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

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

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


15、MyBatis注解开发

1.MyBatis的注解开发

1.1 MyBatis的常用注解

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

映射文件了。

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

  • @Insert:实现新增

  • @Update:实现更新

  • @Delete:实现删除

  • @Select:实现查询

  • @Result:实现结果集封装

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

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

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

1.2 MyBatis的增删改查

简单的对user表的增删改查工作:

private UserMapper userMapper;
@Before
public void before() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
userMapper = sqlSession.getMapper(UserMapper.class);
}
@Test
public void testAdd() {
User user = new User();
user.setUsername("测试数据");
user.setPassword("123");
user.setBirthday(new Date());
userMapper.add(user);
}
@Test
public void testUpdate() throws IOException {
User user = new User();
user.setId(16);
user.setUsername("测试数据修改");
user.setPassword("abc");
user.setBirthday(new Date());
userMapper.update(user);
}
@Test
public void testDelete() throws IOException {
userMapper.delete(16);
}
@Test
public void testFindById() throws IOException {
User user = userMapper.findById(1);
System.out.println(user);
}
@Test
public void testFindAll() throws IOException {
List<User> all = userMapper.findAll();
for(User user : all){
System.out.println(user);
}
}

修改MyBatis的核心配置文件,我们使用了注解替代的映射文件,所以我们只需要加载使用了注解的Mapper接口即可

<mappers>
<!--扫描使用注解的类-->
<mapper class="com.itheima.mapper.UserMapper"></mapper>
</mappers>

或者指定扫描包含映射关系的接口所在的包也可以

<mappers>
<!--扫描使用注解的类所在的包-->
<package name="com.itheima.mapper"></package>
</mappers>
1.3 MyBatis的注解实现复杂映射开发

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


1.4 一对一查询
  1. 一对一查询的模型

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

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

  2. 一对一查询的语句

    对应的sql语句:

    select * from orders;

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

    查询的结果如下:

  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;
    }
  4. 创建OrderMapper接口

    public interface OrderMapper {
    List<Order> findAll();
    }
  5. 使用注解配置Mapper

  6. 测试结果

    @Test
    public void testSelectOrderAndUser() {
    List<Order> all = orderMapper.findAll();
    for(Order order : all){
    System.out.println(order);
    }
    }

1.5 一对多查询
  1. 一对多查询的模型

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

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

  2. 一对多查询的语句

    对应的sql语句:

    select * from user;

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

    查询的结果如下:

  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;
    }
  4. 创建UserMapper接口

    List<User> findAllUserAndOrder();
  5. 使用注解配置Mapper

  6. 测试结果

    List<User> all = userMapper.findAllUserAndOrder();
    for(User user : all){
    System.out.println(user.getUsername());
    List<Order> orderList = user.getOrderList();
    for(Order order : orderList){
    System.out.println(order);
    }
    System.out.println("-----------------------------");
    }
  7. 测试结果

1.6 多对多查询
  1. 多对多查询的模型

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

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

  2. 多对多查询的语句

    对应的sql语句:

    select * from user;

    select * from role r,user_role ur where r.id=ur.role_id and ur.user_id=用户的id

    查询的结果如下:

  3. 创建Role实体,修改User实体

    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;
    }
  4. 添加UserMapper接口方法

    List<User> findAllUserAndRole();
  5. 使用注解配置Mapper

  6. 测试结果

    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    List<User> all = mapper.findAllUserAndRole();
    for(User user : all){
    System.out.println(user.getUsername());
    List<Role> roleList = user.getRoleList();
    for(Role role : roleList){
    System.out.println(role);
    }
    System.out.println("----------------------------------");
    }

SSM自学笔记(七)的更多相关文章

  1. vue 自学笔记(七) 组件细节问题

    前情提要: 这里盘点一下,组件细节的问题 现在我们观察一些用框架开发的网页BiliBili.掘金,会发现很多部分都十分相似或者一模一样,我们甚至可以将其拆分归类.而事实上,页面的确是被一个个组件构成的 ...

  2. SSM自学笔记(六)

    11.MyBatis的Dao层实现方式 1.MyBatis的Dao层实现 1.1 传统开发方式 编写UserDao接口 public interface UserDao { List<User& ...

  3. SSM自学笔记(五)

    10.MyBatis入门操作 1.MyBatis的简介 1.1 原始jdbc操作(查询数据) 1.2 原始jdbc操作(插入数据) ##### 1.3 **原始**jdbc操作的分析 原始jdbc开发 ...

  4. SSM自学笔记(四)

    8.面向切面编程AOP 1.Spring 的 AOP 简介 1.1 什么是 AOP AOP 为 Aspect Oriented Programming 的缩写,意思为面向切面编程,是通过预编译方式和运 ...

  5. SSM自学笔记(三)

    5.Spring JdbcTemplate 1.Spring JdbcTemplate基本使用 1.1 JdbcTemplate概述 它是spring框架中提供的一个对象,是对原始繁琐的Jdbc AP ...

  6. SSM自学笔记(二)

    3.SpringMVC入门 1.Spring与Web环境集成 1.1 ApplicationContext应用上下文获取方式 应用上下文对象是通过new ClasspathXmlApplication ...

  7. SSM自学笔记(一)

    本文内容 Ioc和DI Spring快速入门 Spring配置文件 Spring IoC和DI注解开发 Spring配置数据源 Spring注解开发 Spring整合Junit IoC 和 DI 1. ...

  8. JavaScript高级程序设计之自学笔记(一)————Array类型

    以下为自学笔记. 一.Array类型 创建数组的基本方式有两种: 1.1第一种是使用Array构造函数(可省略new操作符). 1.2第二种是使用数组字面量表示法. 二.数组的访问 2.1访问方法 在 ...

  9. 《Linux内核设计与实现》课本第四章自学笔记——20135203齐岳

    <Linux内核设计与实现>课本第四章自学笔记 进程调度 By20135203齐岳 4.1 多任务 多任务操作系统就是能同时并发的交互执行多个进程的操作系统.多任务操作系统使多个进程处于堵 ...

随机推荐

  1. OpenFlow协议分析

    OpenFlow协议分析实验手册 启动虚拟机mininet 和 控制器 ODL 启动wireshark,在控制器的ens32 网卡抓包 使用mininet创建简单拓扑,并连接控制器,指定交换机为ovs ...

  2. python使用笔记11--时间模块

    1.时间模块常用方法 1 import time,datetime 2 #格式化好的时间2020-05-16 18:30:52 3 #时间戳1589616753 从unix元年(计算机发明的时间)到现 ...

  3. IP地址与子网化分

    IP地址与子网掩码 一.IP地址的组成 二.IP地址的分类                            1)A.B.C三类地址的组成                            2 ...

  4. C语言:FILE p和FILE *p

    FILE p和FILE *p大概可以这么理解:1 . 前一个p指文件型变量,后一个p指文件地址型变量.2 . 前一个p的内存地址已定,后一个p内存地址未定. 前一个是声明类对象,后一个是声明一个可指向 ...

  5. LeetCode解题记录(双指针专题)

    1. 算法解释 双指针主要用于遍历数组,两个指针指向不同的元素,从而协同完成任务.也可以延伸到多个数组的多个指针. 若两个指针指向同一数组,遍历方向相同且不会相交,则也称为滑动窗口(两个指针包围的区域 ...

  6. LeetCode 895. Maximum Frequency Stack

    题目链接:https://leetcode.com/problems/maximum-frequency-stack/ 题意:实现一种数据结构FreqStack,FreqStack需要实现两个功能: ...

  7. Requests方法 -- session方法

    import requests#禁用安全请求警告from requests.packages.urllib3.exceptions import InsecureRequestWarningreque ...

  8. PAT甲级:1152 Google Recruitment (20分)

    PAT甲级:1152 Google Recruitment (20分) 题干 In July 2004, Google posted on a giant billboard along Highwa ...

  9. 【洛谷P1507 NASA的食物计划】动态规划

    分析 二维费用背包模板 AC代码 #include <bits/stdc++.h> using namespace std; const int Maxn=505; int a[Maxn] ...

  10. 【codeforces1058】Vasya and Golden Ticket 枚举+暴力+模拟

    #点击传送 题目描述 Recently Vasya found a golden ticket - a sequence which consists of nn digits a1a2-ana1a2 ...