SpringBoot使用Mybatis注解进行一对多和多对多查询

GitHub的完整示例项目地址kingboy-springboot-data

一、模拟的业务查询

系统中的用户user都有唯一对应的地址信息address,每个用户可以有多量车car,类似如下结构

|-- user
|-- address
|-- carList
|-- car1
|-- car2

  

二、对应的实体类如下

/省略setter/getter

public class Address {
private Long id;
private String province;
private String city;
} public class Car {
private Long id;
private String color;
private String name;
//用户id
private Long userId;
} public class User {
private Long id;
//地址信息,和用户是一对一的关系
private Address address;
//地址id
private Long addressId;
//用户拥有的车,和用户是一对多的关系
private List<Car> cars;
}

三、对应的建表语句和模拟数据如下

CREATE TABLE IF NOT EXISTS `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`nick_name` varchar(50) DEFAULT NULL,
`address_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE IF NOT EXISTS `address` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`province` varchar(50) DEFAULT NULL,
`city` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE IF NOT EXISTS `car` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`color` varchar(50) DEFAULT NULL,
`name` varchar(50) DEFAULT NULL,
`user_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO
`user`
VALUES
('1', 'baby', '1'),
('2', 'kingboy', '2'),
('3', 'boy', '3'),
('4', 'kingbaby', '4'); INSERT INTO
`address`
VALUES
('1', '北京', '北京'),
('2', '天津', '天津'),
('3', '安徽', '宿州'),
('4', '广东', '广州'); INSERT INTO
`car`
VALUES
('1', 'green', '路虎', '1'),
('2', 'white', '奔驰', '2'),
('3', 'blue', '玛莎拉蒂', '4'),
('4', 'yellow', '兰博基尼', '4');

四、@One一对一映射

以获取用户的唯一地址为例,首先我们定义一个根据地址id查询地址的查询方法

public interface AddressRepository {
/**
* 根据地址id查询地址
*/
@Select("SELECT * FROM `address` WHERE id = #{id}")
Address findAddressById(Long id);
}

然后我们定义一个根据用户id查询用户的方法

public interface UserRepository {
@Select("SELECT * FROM `user` where id = #{id}")
User findUserWithAddress(Long id);
}

这个时候我们查询出来的user对象中的address属性是空的,和address并没有任何关联。 
那么我们要把user中的addressId传递给AddressRepository的查询地址的方法, 
然后把查询出的地址对象address赋值给user的address属性,那么我们怎么做呢?

public interface UserRepository {
@Select("SELECT * FROM `user` where id = #{id}")
@Results({
@Result(property = "address", column = "address_id",
one = @One(select = "com.kingboy.repository.address.AddressRepository.findAddressById"))
})
User findUserWithAddress(Long id);
}

我们要使用@Resutl注解对返回的结果进行配置, 
- property = “address”, 表示要将返回的查询结果赋值给user的address属性 
- column = “address_id” 是指将user表中的address_id作为com.kingboy.repository.address.AddressRepository.findAddressById的查询参数 
- one 表示这是一个一对一的查询 
- @One(select = “方法全路径) 表示我们调用的方法

五、@Many一对多查询

以获取用户拥有的所有车car为例,首先我们定义一个根据用户id查询车的查询方法

public interface CarRepository {
/**
* 根据用户id查询所有的车
*/
@Select("SELECT * FROM `car` WHERE user_id = #{userId}")
List<Car> findCarByUserId(Long userId);
}

  然后我们定义一个根据用户id查询用户的方法

public interface UserRepository {
@Select("SELECT * FROM `user` where id = #{id}")
User findUserWithAddress(Long id);
}

这个时候我们查询出来的user对象中的List属性是空的,和car的查询方法并没有任何关联。 
那么我们要把user中的用户id传递给CarRepository的查询车的方法, 
然后把查询出的集合对象List赋值给user的cars属性,那么我们怎么做呢?

public interface UserRepository {
/**
* 查询带有车信息的用户===============演示一对多(关于多对多其实就是两个一对多组成)
*/
@Select("SELECT * FROM `user` WHERE id = #{id}")
@Results({
@Result(property = "cars", column = "id",
many = @Many(select = "com.kingboy.repository.car.CarRepository.findCarByUserId"))
})
User getUserWithCar(Long id);
}
我们要使用@Resutl注解对返回的结果进行配置,
- property = “cars”, 表示要将返回的查询结果赋值给user的cars属性
- column = “id” 是指将user表中的用户主键id作为com.kingboy.repository.address.CarRepository.findCarByUserId的查询参数
- many 表示这是一个一对多的查询
- @Many(select = “方法全路径) 表示我们调用的方法, 方法参数userId就是上面column指定的列值

六、@One @Many的总结

首先我们统一下概念:查询Address或Car的方法,接下来统称为User的附属查询。

共同点: 
- 无论是一对一还是一对多,都是通过附属查询来实现的,我们需要定义这个附属查询方法。 
- 在主查询方法中通过@One、@Many指定附属查询方法的全路径。 
- 都通过column来传递参数给附属方法。

不同点: 
- 一对一,那么附属方法返回的是一个单独的对象 
- 一对多,那么附属方法返回的是一个对象集合

SpringBoot使用Mybatis注解进行一对多和多对多查询(2)的更多相关文章

  1. mybatis+oracle实现一对多,多对一查询

    首先创建表 学生表 create table stu(       id number(11) primary key,       name varchar2(255),       age num ...

  2. Mybatis一对一、一对多、多对多查询。+MYSQL

    场景:使用三张数据表:student学生表.teacher教师表.position职位表 一个学生可以有多为老师.一位老师可以有多个学生.但是一个老师只能有一个职位:教授.副教授.讲师:但是一个职位可 ...

  3. SpringBoot整合Mybatis注解版---update出现org.apache.ibatis.binding.BindingException: Parameter 'XXX' not found. Available parameters are [arg1, arg0, param1, param2]

    SpringBoot整合Mybatis注解版---update时出现的问题 问题描述: 1.sql建表语句 DROP TABLE IF EXISTS `department`; CREATE TABL ...

  4. springboot整合mybatis(注解)

    springboot整合mybatis(注解) 1.pom.xml: <?xml version="1.0" encoding="UTF-8"?> ...

  5. mybatis(一、原理,一对多,多对一查询)

    MyBatis框架及原理分析 MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架,其主要就完成2件事情: 封装JDBC操作 利用反射打通Java类与SQL语句之间的相互转换 ...

  6. springboot之mybatis注解形式

    springboot整合mybatis对数据库进行访问,本实例采用注解的方式,如下: pom.xml文件 <parent> <groupId>org.springframewo ...

  7. SpringBoot使用Mybatis注解开发教程-分页-动态sql

    代码示例可以参考个人GitHub项目kingboy-springboot-data 一.环境配置 1.引入mybatis依赖 compile( //SpringMVC 'org.springframe ...

  8. Springboot整合Mybatis实现级联一对多CRUD操作

    在关系型数据库中,随处可见表之间的连接,对级联的表进行增删改查也是程序员必备的基础技能.关于Spring Boot整合Mybatis在之前已经详细写过,不熟悉的可以回顾Spring Boot整合Myb ...

  9. Mybatis 一对一、一对多、多对多

    一对一返回resultType <!-- 查询订单关联查询用户信息 resultType --> <select id="findOrderCustom" res ...

随机推荐

  1. POST 和 PUT 方法区别

        Http定义了与 服务器的交互方法,其中除了一般我们用的最多的GET,POST 其实还有PUT和DELETE 根据RFC2616标准(现行的HTTP/1.1)其实还有OPTIONS,GET,H ...

  2. 在websocket中怎么样注入service类

    最近项目中用到了websocket,遇到很多问题,其中一个是@ServerEndpoint修饰的类无法注入其他的bean,注入的对象都是null,在网上找了好多资料,无意中发现一个朋友的答案给了思路. ...

  3. 血族第四季/全集The Strain迅雷下载

    当第四季开始时,故事时间已经过去九个月.世界陷入黑暗,斯特里高伊吸血鬼控制了一切.第三季结尾的爆炸引发了一场全球核灾难,核冬天的到来令地表变得暗无天日,斯特里高伊获得解放.它们大白天也能出来活动,帮助 ...

  4. Java中CAS详解

    在JDK 5之前Java语言是靠synchronized关键字保证同步的,这会导致有锁 锁机制存在以下问题: (1)在多线程竞争下,加锁.释放锁会导致比较多的上下文切换和调度延时,引起性能问题. (2 ...

  5. Identifier:GUID (全局唯一标识符)

    ylbtech-Miscellaneos-Identifier:GUID (全局唯一标识符) A,返回顶部 1, 全局唯一标识符(GUID,Globally Unique Identifier)是一种 ...

  6. C++11 std::unique_lock与std::lock_guard区别及多线程应用实例

    C++多线程编程中通常会对共享的数据进行写保护,以防止多线程在对共享数据成员进行读写时造成资源争抢导致程序出现未定义的行为.通常的做法是在修改共享数据成员的时候进行加锁--mutex.在使用锁的时候通 ...

  7. Vue.js vs React vs Angular 深度对比[转]

    这个页面无疑是最难编写的,但我们认为它也是非常重要的.或许你曾遇到了一些问题并且已经用其他的框架解决了.你来这里的目的是看看 Vue 是否有更好的解决方案.这也是我们在此想要回答的. 客观来说,作为核 ...

  8. SharePoint 2013 开启访问请求 链接丢失

    关于SharePoint 2013 开启访问请求的做法其实很简单,比如http://www.cnblogs.com/jianyus/archive/2014/06/21/3799386.html 这篇 ...

  9. 为什么你作为一个.NET的程序员工资那么低?(转)

    最近看到很多抱怨贴,也许有一定的道理,但是你想过没,为什么大部分.NET程序员工资相对低?我个人是这么看的: 大批半罐子水的程序员,永远被局限在.NET的原始的小圈圈里.前端不会(你放弃了一项很重要的 ...

  10. FileProvider N 7.0 升级 安装APK 选择文件 拍照 临时权限 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...