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. vim程序编辑器---常用操作整理

    vim程序编辑器---常用操作整理 移动光标方法 o 在光标行的下一行,进入编辑模式 $ 移动到光标这行,最末尾的地方 G(大写) 移动到文件最末行 :set  nu 文件显示行数 :set  non ...

  2. muggle_ocr 下载安装

    pip install -i https://pypi.tuna.tsinghua.edu.cn/simple muggle_ocr

  3. Vue使用PrintJs自定义打印表格模板

    这俩天客户提了个需求,需要打印俩个自定义的表格模板,一开始想到的是打印Json表格,但是发现表格样式不符合要求,后来想着打印html,自己生成html模板然后打印,基本可以满足客户的需求,废话不多说, ...

  4. C++11运算符重载详解与向量类重载实例(<<,>>,+,-,*等)

    1. C++运算符重载介绍 C ++ 中预定义的运算符的操作对象只能是基本数据类型.但实际上,对于许多用户自定义类型(例如类),也需要类似的运算操作.这时就必须在C ++ 中重新定义这些运算符,赋予已 ...

  5. 「NOIP2017」宝藏

    「NOIP2017」宝藏 题解 博客阅读效果更佳 又到了一年一度NOIPCSP-S 赛前复习做真题的时间 于是就遇上了这道题 首先观察数据范围 \(1 \le n \le 12\) ,那么极大可能性是 ...

  6. 基于JSP的学生考勤管理系统(MySQL版)

    介绍:基于JSP的学生考勤管理系统(MySQL版)1.包含源程序,数据库脚本.代码和数据库脚本都有详细注释.2.课题设计仅供参考学习使用,可以在此基础上进行扩展完善.开发环境:Eclipse ,MyS ...

  7. erase

    erase详细解释及原理 我们先定义一个字符串string string.erase(iterator) iterator表示要删除元素的迭代器. string.erase(it_begin,it_e ...

  8. 使用Visual Studio进行文件差异比较

    启动VS自带的文件差异比较工具,进行代码文本比较,省去安装第三方工具的麻烦. 一.启动VS命令窗口. 依次点击菜单[视图]>>[其它窗口]>>[命令窗口],如下图所示,启动命令 ...

  9. 利用C++11可变模板,封装调用dll导出函数

    起因 开发中经常需要动态调用一些导出函数,试着利用C++11特性封装一下 尝试 常规使用 typedef int WINAPI (*TMessageBoxA)(HWND hWnd,LPCSTR lpT ...

  10. HCNA Routing&Switching之OSPF缺省路由发布

    前文我们了解了OSPF的度量值,以及基础配置命令的总结,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15069632.html:今天我们来聊一聊在ospf里动 ...