超详细-Springboot使用Mybatis注解进行一对一一对多和多对多查询

超详细-Springboot使用Mybatis注解进行一对一一对多和多对多查询

一、模拟的业务查询

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

|-- user

|-- address

|-- carList

​ |-- car1

​ |-- car2

二、对应的实体类如下

@Data

public class AddressPO {

private Long id;

/**

* 省份

*/

private String province;

/**

* 城市

*/

private String city;

/**

* 街道

*/

private String street;

}

@Data

public class CarPO {

private Long id;

/**

* 颜色

*/

private String color;

/**

* 品牌

*/

private String name;

private Long userId;

}

@Data

public class UserPO extends AbstractPO {

private Long id;

private String username;

private String password;

private Integer age;

private GenderEnum gender;

/**

* 地址信息,和用户是一对一的关系

*/

private AddressPO address;

/**

* 地址id

*/

private Long addressId;

/**

* 用户拥有的车,和用户是一对多的关系

*/

private List cars;

}

————————————————

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

CREATE TABLE IF NOT EXISTS user

(

id int(11) NOT NULL AUTO_INCREMENT COMMENT ‘主键’,

username varchar(20) NOT NULL UNIQUE COMMENT ‘用户名’,

password varchar(50) NOT NULL COMMENT ‘密码’,

age int(2) NOT NULL COMMENT ‘年龄’,

gender varchar(10) NOT NULL COMMENT ‘性别’,

address_id int(11) DEFAULT NULL COMMENT ‘地址’,

creater varchar(20) DEFAULT NULL COMMENT ‘创建人’,

modifier varchar(20) DEFAULT NULL COMMENT ‘更新人’,

create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ‘创建时间’,

modify_time datetime NOT NUll DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ‘修改时间’,

PRIMARY KEY (id),

KEY index_gender (gender) USING BTREE COMMENT ‘性别’

) ENGINE = InnoDB

DEFAULT CHARSET = utf8mb4

COLLATE = utf8mb4_bin;

CREATE TABLE IF NOT EXISTS address

(

id int(11) NOT NULL AUTO_INCREMENT,

province varchar(50) DEFAULT NULL,

city varchar(50) DEFAULT NULL,

street varchar(50) DEFAULT NULL,

PRIMARY KEY (id)

) ENGINE = InnoDB

DEFAULT CHARSET = utf8mb4

COLLATE = utf8mb4_bin;

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 = utf8mb4

COLLATE = utf8mb4_bin;

INSERT INTO user(username, password, age, gender, address_id)

VALUES (‘KimZing’, ‘123456’, ‘25’, ‘MAN’, 1), (‘kim’, ‘123456’, ‘25’, ‘MAN’, 2);

INSERT INTO address

VALUES (‘1’, ‘北京’, ‘北京’, ‘王府井’),

​ (‘2’, ‘天津’, ‘天津’, ‘周良’),

​ (‘3’, ‘安徽’, ‘宿州’, ‘涌桥’),

​ (‘4’, ‘广东’, ‘广州’, ‘顺德’);

INSERT INTO

car

VALUES

(‘1’, ‘green’, ‘路虎’, ‘1’),

(‘2’, ‘white’, ‘奔驰’, ‘2’),

(‘3’, ‘blue’, ‘玛莎拉蒂’, ‘1’),

(‘4’, ‘yellow’, ‘兰博基尼’, ‘2’);

四、@One一对一映射

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

@Mapper

public interface AddressRepository {

/**

* 根据地址id查询地址

*/

@Select(“SELECT * FROM address WHERE id = #{id}”)

AddressPO findAddressById(Long id);

}

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

@Mapper

public interface MySqlUserRepository {

@Select(“SELECT * FROM user WHERE id = #{id}”)

UserPO find(Long id);

}

这个时候我们查询出来的user对象中的address属性是空的,和address并没有任何关联。

那么我们要把user中的addressId传递给AddressRepository的查询地址的方法,

然后把查询出的地址对象address赋值给user的address属性,那么我们怎么做呢?

@Mapper

public interface MySqlUserRepository {

@Select(“SELECT * FROM user WHERE id = #{id}”)

@Results({

​ @Result(property = “address”, column = “address_id”,

​ one = @One(select = “com.kimzing.data.repository.AddressRepository.findAddressById”))

})

UserPO find(Long id);

}

我们要使用@Resutl注解对返回的结果进行配置,

property = “address”, 表示要将返回的查询结果赋值给user的address属性

column = “address_id” 是指将user表中的address_id作为com.kimzing.data.repository.AddressRepository.findAddressById的查询参数

one 表示这是一个一对一的查询

@One(select = "方法全路径) 表示我们调用的方法

五、@Many一对多查询

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

@Mapper

public interface CarRepository {

/**

* 根据用户id查询所有的车

*/

@Select(“SELECT * FROM car WHERE user_id = #{userId}”)

List findCarsByUserId(Long userId);

}

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

@Mapper

public interface MySqlUserRepository {

@Select(“SELECT * FROM user WHERE id = #{id}”)

UserPO find(Long id);

}

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

package com.kimzing.data.repository.impl;

import com.kimzing.data.domain.po.UserPO;

import org.apache.ibatis.annotations.*;

import java.util.List;

/**

* 数据存储.

* @author KimZing - kimzing@163.com

* @since 2020/1/31 13:12

*/

@Mapper

public interface MySqlUserRepository {

@Select(“SELECT * FROM user WHERE id = #{id}”)

@Results({

​ @Result(property = “address”, column = “address_id”,

​ one = @One(select = “com.kimzing.data.repository.AddressRepository.findAddressById”)),

​ @Result(property = “cars”, column = “id”,

​ many = @Many(select = “com.kimzing.data.repository.CarRepository.findCarsByUserId”))

}),

// 对userId进行赋值

@Result(property = “id”, column = “id”)

UserPO find(Long id);

}

我们要使用@Resutl注解对返回的结果进行配置,

property = “cars”, 表示要将返回的查询结果赋值给user的cars属性

column = “id” 是指将user表中的用户主键id作为com.kimzing.data.repository.CarRepository.findCarsByUserId的查询参数

many 表示这是一个一对多的查询

@Many(select = "方法全路径) 表示我们调用的方法, 方法参数userId就是上面column指定的列值

六、@One @Many的总结

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

共同点:

无论是一对一还是一对多,都是通过附属查询来实现的,我们需要定义这个附属查询方法。

在主查询方法中通过@One、@Many指定附属查询方法的全路径。

都通过column来传递参数给附属方法。

不同点:

一对一,那么附属方法返回的是一个单独的对象

一对多,那么附属方法返回的是一个对象集合

mybatis的高级映射 (resultmap标签,column属性传多个参数,select子查询自身)

public interface UsersMapper {

//

// @Results(value={

// @Result(id=true,column=“id”,property=“id”),

// @Result(column=“username”,property=“username”),

// @Result(column=“password”,property=“password”),

// @Result(property=“menu”,many=@Many(select=“cn.cong.mapper.MenuMapper.selByPid”),column="{uid=id,pid=pid}")

// })

​ //如果需要传递多个参数 column="{“key”=列名,“key”=列名}" key自定义

​ //另一个查询中获取传递过来的参数 #{key}

​ //另一个查询public void select(Map<String,Object> map);

​ //@Select(“select *,0 pid from users where username=#{username} and password=#{password}”)

​ Users selByUsers(Users users);

}

public interface MenuMapper {

// @Results(value={

// @Result(id=true,property=“id”,column=“id”),

// @Result(property=“name”,column=“name”),

// @Result(property=“pid”,column=“pid”),

// @Result(property=“children”,many=@Many(select=“selByPid”),column="{uid=uid,pid=id}"),

// })

// @Select(“select *,#{uid} uid from menu where id in (select mid from user_menu where uid=#{uid}) and pid=#{pid}”)

​ List

selByPid(Map<String,Object> map);

}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值