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. ffmpeg:为视频添加静态水印

    在ffmpeg中,添加水印需要用overlay滤镜,这是一个复杂滤镜,因为它需要两个输入,默认第一个输入是主画面,第二输入为水印,先执行一个简单的看看. 下面有两个文件,一个是可爱的大雄兔,一个是可爱 ...

  2. JDBC概念理解

    ##JDBC: 概念:Java DataBase Connectivity  Java 数据库连接  Java语言操作数据库 JDBC本质:其实是官方(sun公司)定义的一套操作所有关系型数据库的规则 ...

  3. 微信小程序引入ECharts组件

    首先打开ECharts网页 https://echarts.apache.org/zh/tutorial.html#%E5%9C%A8%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8 ...

  4. 五分钟学会generator函数

    什么是generator函数? 常规函数只会返回一个单一值(或者不返回任何值). 而 Generator 可以按需一个接一个地返回("yield")多个值.它们可与 iterabl ...

  5. 微信小程序:添加全局的正在加载中图标效果

    在发送请求的时候,显示一个正在加载中的小图标.在加载下一页的时候也显示正在加载中.同时数据请求回来了,把加载中进行关闭. 开发----API-----界面 在哪里添加这两段代码会比较方便呢?一个项目有 ...

  6. Python函数注解

    目录 函数注解概述 实际应用 inspect模块 业务代码 总结 以下内容基于Python 3x 涉及的知识前提: 建议理解Python装饰器后学习此内容 函数注解概述 函数注解可以针对函数的参数.返 ...

  7. 大话Spark(6)-源码之SparkContext原理剖析

    SparkContext是整个spark程序通往集群的唯一通道,他是程序的起点,也是程序的终点. 我们的每一个spark个程序都需要先创建SparkContext,接着调用SparkContext的方 ...

  8. 剑指 Offer 57. 和为s的两个数字 + 二分法 + 双指针

    剑指 Offer 57. 和为s的两个数字 Offer_57 题目详情 使用二分法 package com.walegarrett.offer; /** * @Author WaleGarrett * ...

  9. STL中常用容器及操作 学习笔记1

    @[TOC](下面介绍STL中常见的容器及操作)## 不定长数组 vector> vetcor:其实就是一个数组或者说是容器 其操作不同于之前直接定义的数组 > 而且可以直接赋值也可以直接 ...

  10. Java 基础加强 02

    基础加强·反射 和 枚举 类的加载概述和加载时机 * A:类的加载概述 * 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载.连接.初始化来实现对这个类的初始化 * 加载 * 就是指 ...