MyBatis-Plus不写任何resultMap和SQL执行一对一、一对多、多对多关联查询
对于一对一,一对多的关联查询,Mybatis-Plus官方示例(mybatis-plus-sample-resultmap)在处理时,需要编写查询方法及配置resultMap,并且写SQL。
为了简化这种操作,可以自定义注解来简化。注解工具源码及jar包地址:https://github.com/dreamyoung/mprelation
注解工具使用公优缺点:
优点:
无需再写SQL及XML配置文件
无需在Service层及Mapper层写 getLinkById 、 selectLinkById 之类的方法
Mybatis-Plus原来 ServiceImpl 内置的各种查询方法都自动关联查询。
缺点:
无法做到 1个连接每次执行多条SQL,只能 多个连接每次执行1条。(即每个关联属性的查询都会消耗一个连接)
最好搭配连接池一起使用,并且配置适当的延迟加载(通过@Lazy注解)
注解使用:
一对多(多对一) :
Company实体类中配置:
@Data
public class Company {
@TableId(value = "company_id")
private Long id;
private String name;
//一对多
@TableField(exist = false)
@OneToMany
@JoinColumn(name="company_id",referencedColumnName = "company_id")
private Set<Man> employees;
}
Man实体类中配置:
@Data
public class Man {
@TableId(value = "man_id")
private Long id;
private String name;
//多对一
@TableField("company_id")
private Long companyId;
@TableField(exist = false)
@ManyToOne
@JoinColumn(name = "company_id", referencedColumnName = "company_id")
private Company company;
}
一对多(多对一)表结构: company: (compnay_id, name) man: (man_id, name, company_id)
一对一:
Woman实体类配置:
@Data
public class Woman {
@TableId(value = "woman_id")
private Long id;
private String name;
//一对一
@TableField("lao_gong_id")
private Long laoGongId;
@TableField(exist = false)
@OneToOne
@JoinColumn(name = "lao_gong_id", referencedColumnName = "man_id")
private Man laoGong;
}
Man实体类配置:
@Data
public class Man {
@TableId(value = "man_id")
private Long id;
private String name;
//一对一
@TableField("lao_po_id")
private Long laoPoId;
@TableField(exist = false)
@OneToOne
@JoinColumn(name = "lao_po_id", referencedColumnName = "woman_id")
private Woman laoPo;
}
一对一表结构:(实际可以减少一方) woman: (woman_id, name, lao_gong_id) man: (man_id, name, lao_po_id)
多对多:
Course实体类配置:
@Data
public class Course {
@TableId(value = "course_id")
private Long id;
private String name;
//多对多
@TableField(exist = false)
@ManyToMany
@JoinTable(targetMapper = StudentCourseMapper.class)
@JoinColumn(name = "course_id", referencedColumnName = "course_id")
@InverseJoinColumn(name = "child_id", referencedColumnName = "student_id")
private List<Child> students;
}
Child实体类配置:
@Data
public class Child {
@TableId("child_id")
private Long id;
private String name;//多对多
@TableField(exist = false)
@ManyToMany
@JoinTable(targetMapper=StudentCourseMapper.class)
@JoinColumn(name = "child_id", referencedColumnName = "student_id")
@InverseJoinColumn(name = "course_id", referencedColumnName = "course_id")private List<Course> courses;
}
StudenCourse中间类(多对多必须要有):
@Data
public class StudentCourse {
//可以有也可以无此ID
private Long id;
@TableField("student_id")
private Long studentId;
@TableField("course_id")
private Long courseId;
}
多对多表结构:course: (course_id, name) child: (child_id, name) student_course:(id, student_id, course_id)
使用过程:
1. 加入 mprelation-1.0.jar,在Spring 配置 一个Bean: com.github.dreamyoung.mprelation.AutoMapper
@Configuration
public class AutoMapperConfig {
@Bean
public AutoMapper autoMapper(@Autowired(required=false) ApplicationContext applicationContext) {
return new AutoMapper(applicationContext, new String[] { "demo.entity" }); //配置ApplicationContext及实体类所在包
}
}
2. 在实体类中配置注解(注解的配置见上边注解部分)
3. 在Service层、Mapper层的使用,见下面:
以下是基于Mybatis-Plus官方示例修改而来的测试程序:
通过继承工具类重写过的IService / ServiceImpl 会自动执行关联映射, 无须再写gettLinkById之类的方法(可以使得各实现类没有任何方法):
mapper接口:
public interface ManMapper extends BaseMapper<Man> {}
service接口:
public interface IManService extends IService<Man> {} // IService为重写过的同名接口
Service实现:
@Service
public class ManServiceImpl extends ServiceImpl<ManMapper, Man> implements IManService {} // ServiceImpl为重写过的同名接口
调用:
public class ServiceTest {
@Autowired
ManService manService;
@Test
public void t_man_serviceImpl() {
Man man = manService.getById(1); // 原Mybatis-Plus的ServiceImpl的各种查询都可以自动关联
System.out.println(man);
}
}
输出:
Man(
id=1,
name=程序猿小明,
laoPoId=1,
laoPo=Woman(id=1, name=程序猿小明老婆, laoGongId=1, laoGong=null, waWa=null),
companyId=1,
company=Company(id=1, name=百度, employees=null),
waWa=[
Child(id=1,name=xxx1,lao_han_id=null, laoHan=null, lao_ma_id=null, laoMa=null, courses=null),
Child(id=2,name=xxxx2, lao_han_id=null, laoHan=null, lao_ma_id=null, laoMa=null, courses=null)
],
tels=[
Tel(id=1, tel=139xxxxxx, manId=1, laoHan=null),
Tel(id=4, tel=159xxxxxx, manId=1, laoHan=null),
Tel(id=2, tel=137xxxxxx, manId=1, laoHan=null)
]
)
如需需要对其查询到的关联属性对象的关联,可以使用AutoMapper对象的mapperEntity、mapperEntityList、mapperEntitySet、mapperEntityPage来操作:
比如想获取(填充)waWas 的关联,则:
List waWas=man.getWaWas(); autoMapper.mapperEntityList(waWas);
AutoMapper类中的几个常用方法说明:
mapperEntity(entity) 可以对一个实体类,实现自动关联。
mapperEntityList(entity_list) 可以对一个实体类List,实现自动关联。
mapperEntitySet(entity_set) 可以对一个实体类Set,实现自动关联。
mapperEntityPage(entity_page) 可以对一个实体类Page,实现自动关联。
AutoMapper在重写过的ServiceImpl类中已经自动注入可用(名为autoMapper),其它情况也可以手动注入:
public class MPRTest2 {
@Autowired
AutoMapper autoMapper;
@Resource
private ManMapper manMapper;
@Test
public void t_man() {
Man man = manMapper.selectById(1L);
autoMapper.mapperEntity(man);
System.out.println(man);
}
}
下载地址和源码地址:
https://github.com/dreamyoung/mprelation
原文:https://www.cnblogs.com/dreamyoung/p/12466656.html