spring boot 2使用Mybatis多表关联查询
模拟业务关系:
一个用户user有对应的一个公司company,每个用户有多个账户account。
spring boot 2的环境搭建见上文:spring boot 2整合mybatis
一、mysql创表和模拟数据sql
CREATE TABLE IF NOT EXISTS `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`company_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE IF NOT EXISTS `company` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(200) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE IF NOT EXISTS `account` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(200) NOT NULL,
`user_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO
`user`
VALUES
(1, 'aa', 1),
(2, 'bb', 2); INSERT INTO
`company`
VALUES
(1, 'xx公司'),
(2, 'yy公司'); INSERT INTO
`account`
VALUES
(1, '中行', 1),
(2, '工行', 1),
(3, '中行', 2);
二、创建实体
public class User {
private Integer id;
private String name;
private Company company;
private List<Account> accounts;
//getter/setter 这里省略...
} public class Company {
private Integer id;
private String companyName;
//getter/setter 这里省略...
} public class Account {
private Integer id;
private String accountName;
//getter/setter 这里省略... }
三、开发Mapper
方法一:使用注解
1、AccountMapper.java
package com.example.demo.mapper; import java.util.List; import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select; import com.example.demo.entity.Account; public interface AccountMapper {
/*
* 根据用户id查询账户信息
*/
@Select("SELECT * FROM `account` WHERE user_id = #{userId}")
@Results({
@Result(property = "accountName", column = "name")
})
List<Account> getAccountByUserId(Long userId);
}
2、CompanyMapper.java
package com.example.demo.mapper; import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select; import com.example.demo.entity.Company; public interface CompanyMapper {
/*
* 根据公司id查询公司信息
*/
@Select("SELECT * FROM company WHERE id = #{id}")
@Results({
@Result(property = "companyName", column = "name")
})
Company getCompanyById(Long id);
}
3、UserMapper.java
package com.example.demo.mapper; import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Many; import com.example.demo.entity.User; public interface UserMapper { /*
* 一对一查询
* property:查询结果赋值给此实体属性
* column:对应数据库的表字段,做为下面@One(select方法的查询参数
* one:一对一的查询
* @One(select = 方法全路径) :调用的方法
*/
@Select("SELECT * FROM user WHERE id = #{id}")
@Results({
@Result(property = "company", column = "company_id", one = @One(select = "com.example.demo.mapper.CompanyMapper.getCompanyById"))
})
User getUserWithCompany(Long id); /*
* 一对多查询
* property:查询结果赋值给此实体属性
* column:对应数据库的表字段,可做为下面@One(select方法)的查询参数
* many:一对多的查询
* @Many(select = 方法全路径) :调用的方法
*/
@Select("SELECT * FROM user WHERE id = #{id}")
@Results({
@Result(property = "id", column = "id"),//加此行,否则id值为空
@Result(property = "accounts", column = "id", many = @Many(select = "com.example.demo.mapper.AccountMapper.getAccountByUserId"))
})
User getUserWithAccount(Long id); /*
* 同时用一对一、一对多查询
*/
@Select("SELECT * FROM user")
@Results({
@Result(property = "id", column = "id"),
@Result(property = "company", column = "company_id", one = @One(select = "com.example.demo.mapper.CompanyMapper.getCompanyById")),
@Result(property = "accounts", column = "id", many = @Many(select = "com.example.demo.mapper.AccountMapper.getAccountByUserId"))
})
List<User> getAll();
}
方法二:使用XML
参考上文spring boot 2整合mybatis配置application.properties和mybatis-config.xml等后,
以上面的getAll()方法为例,UserMapper.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.example.demo.mapper.UserMapper" >
<resultMap id="UserMap" type="com.example.demo.entity.User">
<id column="id" jdbcType="INTEGER" property="id" />
<result property="name" column="name" jdbcType="VARCHAR" />
<!--封装映射company表数据,user表与company表1对1关系,配置1对1的映射
association:用于配置1对1的映射
属性property:company对象在user对象中的属性名
属性javaType:company属性的java对象 类型
属性column:user表中的外键引用company表
-->
<association property="company" javaType="com.example.demo.entity.Company" column="company_id">
<id property="id" column="companyid"></id>
<result property="companyName" column="companyname"></result>
</association>
<!--配置1对多关系映射
property:在user里面的List<Account>的属性名
ofType:当前account表的java类型
column:外键
-->
<collection property="accounts" ofType="com.example.demo.entity.Account" column="user_id">
<id property="id" column="accountid"></id>
<result property="accountName" column="accountname"></result>
</collection>
</resultMap> <select id="getAll" resultMap="UserMap" >
SELECT
u.id,u.name,c.id companyid, c.name companyname, a.id accountid,a.name accountname
FROM user u
LEFT JOIN company c on u.company_id=c.id
LEFT JOIN account a on u.id=a.user_id
</select> </mapper>
四、控制层
package com.example.demo.web; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper; @RestController
public class UserController {
@Autowired
private UserMapper userMapper; //请求例子:http://localhost:9001/getUserWithCompany/1
/*请求结果:{"id":1,"name":"aa","company":{"id":1,"companyName":"xx公司"},"accounts":null}*/
@RequestMapping("/getUserWithCompany/{id}")
public User getUserWithCompany(@PathVariable("id") Long id) {
User user = userMapper.getUserWithCompany(id);
return user;
} //请求例子:http://localhost:9001/getUserWithAccount/1
/*请求结果:{"id":1,"name":"aa","company":null,"accounts":[{"id":1,"accountName":"中行"},{"id":2,"accountName":"工行"}]}*/
@RequestMapping("/getUserWithAccount/{id}")
public User getUserWithAccount(@PathVariable("id") Long id) {
User user = userMapper.getUserWithAccount(id);
return user;
} //请求例子:http://localhost:9001/getUserWithAccount/1
/*请求结果:[{"id":1,"name":"aa","company":{"id":1,"companyName":"xx公司"},"accounts":[{"id":1,"accountName":"中行"},
{"id":2,"accountName":"工行"}]},{"id":2,"name":"bb","company":{"id":2,"companyName":"yy公司"},"accounts":[{"id":3,"accountName":"中行"}]}]*/
@RequestMapping("/getUsers")
public List<User> getUsers() {
List<User> users=userMapper.getAll();
return users;
}
}
spring boot 2使用Mybatis多表关联查询的更多相关文章
- 三、mybatis多表关联查询和分布查询
前言 mybatis多表关联查询和懒查询,这篇文章通过一对一和一对多的实例来展示多表查询.不过需要掌握数据输出的这方面的知识.之前整理过了mybatis入门案例和mybatis数据输出,多表查询是在前 ...
- JAVA入门[9]-mybatis多表关联查询
概要 本节要实现的是多表关联查询的简单demo.场景是根据id查询某商品分类信息,并展示该分类下的商品列表. 一.Mysql测试数据 新建表Category(商品分类)和Product(商品),并插入 ...
- mybatis多表关联查询之resultMap单个对象
resultMap的n+1方式实现多表查询(多对一) 实体类 创建班级类(Clazz)和学生类(Student),并在Student中添加一个Clazz类型的属性,用于表示学生的班级信息. mappe ...
- MyBatis 多表关联查询
多表关联查询 一对多 单条SQL实现. //根据部门编号查询出部门和部门成员姓名public dept selectAll() thorws Excatipon; //接口的抽象方法 下面是对应接口的 ...
- Mybatis多表关联查询字段值覆盖问题
一.错误展示 1.首先向大家展示多表关联查询的返回结果集 <resultMap id="specialdayAndWorktimeMap type="com.hierway. ...
- 5.mybatis一对一表关联查询
方式一:嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集,封装联表查询的数据(去除重复的数据) SELECT * FROM class c,teacher t WHERE c.tid = t.t ...
- 三、Mybatis多表关联查询应用
一对一查询 实现语句:select * from neworder o, user u where o.uid = u.id 实体Order: 接口: 配置: 测试: 一对多查询 实现语句:selec ...
- Spring Boot入门系列(十七)整合Mybatis,创建自定义mapper 实现多表关联查询!
之前讲了Springboot整合Mybatis,介绍了如何自动生成pojo实体类.mapper类和对应的mapper.xml 文件,并实现最基本的增删改查功能.mybatis 插件自动生成的mappe ...
- Spring Boot:实现MyBatis动态创建表
综合概述 在有些应用场景中,我们会有需要动态创建和操作表的需求.比如因为单表数据存储量太大而采取分表存储的情况,又或者是按日期生成日志表存储系统日志等等.这个时候就需要我们动态的生成和操作数据库表了. ...
随机推荐
- Java中equals,hashcode,==的区别
== :比较java栈局部变量表中变量的地址或值是否相等. equals : 比较变量的地址在java堆中引用对象是否为同一个对象. hashcode : 通过对象在JVM内存中的存储地址通过特定算 ...
- webpack入门操作教程
1. webpack介绍 在传统的项目中,一个html文件可能会加载多个js.css文件,如果多人协同开发的话,就会出现全局变量被污染.文件直接的依赖问题 而webpack打包工具,会先分析入口文件的 ...
- 问题记录 --Error parsing column 1 (Function_Num=10 - String)”
当C#查询数据库出现Error parsing column ## 的时候,首先去看看数据库里面该字段是什么类型,然后在看看你在创建model 的时候是什么类型,如果model的类型和数据库字段类型不 ...
- 编程填空:第i位替换
编程填空:第i位替换 OpenJudge 总时间限制:1000ms 内存限制:1024kB 描述:写出函数中缺失的部分,使得函数返回值为一个整数,该整数的第i位和m的第i位相同,其他位和n相同. 请使 ...
- 爬取豆瓣电影排行top250
功能描述V1.0: 爬取豆瓣电影排行top250 功能分析: 使用的库 1.time 2.json 3.requests 4.BuautifulSoup 5.RequestException 上机实验 ...
- TextField widgets require a Material widget ancestor
TextField widget需要被包裹在Scaffold widget中,否则会报错
- 安利一个vps,7美元/年。
黑色星期五.给大家安利一个vps,7美元/年.配置如下:2 个虚拟化 CPU 2 GB (2048 MB) 专属内存 50 GB RAID-10 受保护硬盘存储 3000 GB (3TB) 月流量 1 ...
- Roomblock: a Platform for Learning ROS Navigation With Roomba, Raspberry Pi and RPLIDAR(转)
What is this? "Roomblock" is a robot platform consists of a Roomba, a Raspberry Pi 2, a ...
- 使用StringEscapeUtils转义、反转义字符串
使用commmons-lang.jar中的字符串转义工具类org.apache.commons.lang.StringEscapeUtils转义.反转义字符串,支持CSV.HTML.JAVA.Java ...
- Atom读写MarkDown插件选择,以及墙内安装markdown-preview-enhanced,及markdown和mermaid使用教程
1.Atom自带markdown-preview 功能太少,需要大量拓展. 2.markdown-preview-plus 功能还不错,但是其中的滚动条插件markdown-scroll-sync和最 ...