MyBatis-Plus不写任何resultMap和SQL执行一对一、一对多、多对多关联查询

2020/03/13 13:06
阅读数 2.8K

对于一对一,一对多的关联查询,Mybatis-Plus官方示例(mybatis-plus-sample-resultmap)在处理时,需要编写查询方法及配置resultMap,并且写SQL。

为了简化这种操作,可以自定义注解来简化。

 

注解工具源码及jar包地址:https://github.com/dreamyoung/mprelation.git

测试项目地址(GITHUB)  :https://github.com/dreamyoung/mprelation_demo.git

 

POM引用 :

<dependency>
     <groupId>com.github.dreamyoung</groupId>
     <artifactId>mprelation</artifactId>
     <version>0.0.2</version> 
</dependency>

 

 

注解工具使用公优缺点:

优点:

       无需再写SQL及XML配置文件

       无需在Service层及Mapper层写 getLinkById 、 selectLinkById   之类的方法

       Mybatis-Plus原来 ServiceImpl 内置的各种查询方法都自动关联查询,非内置方法可以调用autoMapper.mapperXXX方法进行自动关联

 

缺点:

       只能关联查询,对增删改级联操作没作用。

       无法做到 1个连接每次执行多条SQL,只能  多个连接每次执行1条。(即每个关联属性的查询都会消耗一个连接)

       最好搭配连接池一起使用,并且配置适当的延迟加载(通过@Lazy注解)

         通过配置事务管理,一个Service方法同个事务完成所有的自动关联操作,则关联查询可以做到正常:只需要1个连接,执行多条SQL进行关联。

 

 

注解使用:

 一对多(多对一) :

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.jar, 配置一个Spring:  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,实现自动关联。

       mapperEntityCollection(entity_list_or_set)          可以对一个实体类Set或List,实现自动关联。

       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://www.cnblogs.com/dreamyoung/p/12466656.html

展开阅读全文
打赏
1
1 收藏
分享
加载中
更多评论
打赏
0 评论
1 收藏
1
分享
返回顶部
顶部