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


    对于一对一,一对多,多对一,多对多的关联查询,Mybatis-Plus 在处理时,需要编写关联查询方法及配置resultMap,并且书写SQL。

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

    Mybatis-Plus-Relation  ( mprelation ) : mybatis-plus 一对一、一对多、多对一、多对多的自动关联查询,注解方式。

     交流QQ群: 1085077558

    mprelation源码地址  :

         github:     https://github.com/dreamyoung/mprelation.git   

         gitee:        https://gitee.com/dreamyoung/mprelation.git

    mprelation_demo 地址  :

        github:      https://github.com/dreamyoung/mprelation_demo.git 

        gitee:        https://gitee.com/dreamyoung/mprelation_demo.git

    POM引用 :

    <dependency>
         <groupId>com.github.dreamyoung</groupId>
         <artifactId>mprelation</artifactId>
         <version>0.0.3.2-RELEASE</version> 
    </dependency>

    注解工具使用优缺点:

    优点:

           使用简单,通过在实体类上添加@OneToOne / @OneToMany@ManyToOne@ManyToMany  等注解即可。

           注解命名参考了Hibernate命名,如果使用过Hibernate则即刻可上手。

           1对1、1对多、多对1、多对多映射时,可以不再写SQL及XML配置文件,免去配置冗长的<resultMap>的麻烦。

           Service层及Mapper层不需要再添加 getLinkById 、 selectLinkById   之类的方法来关联映射

           重写过的ServiceImpl各种内置的查询方法都自动关联查询,非内置方法可以调用autoMapper相关方法进行自动或手动关联

           所有执行采用非join方式查询,同时解决关联处理的1+n问题

    缺点:

           目前只针对SqlSession/Mappe形式有效(ActiveRecord形式暂未涉及修改,也没有测试)

           非事务下, 1个连接(1个SqlSession)只执行一条SQL,而自动获取每个关联属性的sql都会创建1~2个SqlSession(并执行1~2条SQL)。如果需要使用非内置方法(即除ServiceImpl外的方法),必须配置只读事务来减少SqlSession创建。

           如果有多个延迟加载的关联属性,类上可注解@AutoLazy(false)或没有标注该注解(默认),之后通过initialize方法在事务范围内的一个SqlSession中同时加载需要的多个延迟加载的属性。

    使用注意点:

           非ServiceImpl内置的业务查询,配置事务管理,减少SqlSession的创建。

           实体上可用注解@AutoLazy(true/false)来标注是否自动触发延迟加载,该注解只针对需要延迟的属性。

                   ★  true或无值的话,则获取延迟的关联属性时自动关联。但每一个延迟属性的获取都消耗一个SqlSession。适合于只有一个延迟属性的情况。

                   ★  false或者不标注该注解的话,需要手动通过initialize()方法对延迟的关联属性进行获取,否则不会自动关联获取,此时关联为空。适合于有多个延迟属性的情况。

           如果可以,不使用延迟加载(延迟加载的使用是在SqlSession关闭后执行的,需要重新创建SqlSession)。

           如果确实需要延迟加载,可使用ServiceImpl   AutoMapper 相关的initialize方法一次性加载所有需要的被延迟的属性(只需要创建额外的一个SqlSession,毕竟SqlSession之前已经关闭)

    注解使用:

     一对多(多对一) :

    Company实体类中配置:

    @Data
    public class Company {
        @TableId(value = "company_id")
        private Long id;
        private String name;
        
        //一对多
        @TableField(exist = false)
        @OneToMany //一对多默认为延迟加载,即@Lazy/@Lazy(true)/或此时不标注
        @JoinColumn(name="company_id",referencedColumnName = "company_id")//@TableId与一方相关属性中@TableField名称保持一致时@JoinColumn可省略
        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 //多对一默认为立即加载,即@Lazy(false)或此时不标注 @JoinColumn(name = "company_id", referencedColumnName = "company_id") //相关的@TableField与多方的@TableId名称一致时@JoinColumn可省略 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 //一对一默认为立即加载,即@Lazy(false)或此时不标注 @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 //多对多默认为延迟加载,即@Lazy(true)或此时不标注
        @JoinTable(targetMapper = StudentCourseMapper.class) //第三方命名为StudentCourseMapper或CourseStudentMapper时@JoinTable注解一般可省略
        @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中间类(多对多必须要有,如果命名为StudentCourse或CourseStudent,则上边的@JoinTable可省略):

    @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)

    mprelation 关联查询,使用过程:   

    1.   POM中引入mprelation:

    <dependency>
         <groupId>com.github.dreamyoung</groupId>
         <artifactId>mprelation</artifactId>
         <version>0.0.3.2-RELEASE</version> 
    </dependency>

    配置 AutoMapper (只要是扫描被注解的实体类)

    @Configuration
    public class AutoMapperConfig {
        @Bean
        public AutoMapper autoMapper() {
            return new AutoMapper(new String[] { "demo.entity","demo.bean" }); //配置实体类所在目录(可多个,暂时不支持通过符*号配置)
        }
    }

     

    2.   在实体类中配置注解(更多的注解配置见上边注解部分,这里只列出其中一个)

    @Data
    @AutoLazy  //不需要手动触发加载延迟属性,当延迟属性被调用时自动创建Session进行获取。可见如果有多个延迟属性需要被使用时,会造成多次创建Session,此时可以标注为AutoLazy(false)或不标注,然后采用initialze方法手动一次性加载需要的属性
    public class Man { 
        @TableId(value = "man_id")
        private Long id;
        private String name;
    
        private Long laoPoId;
    @TableField(exist
    = false) @OneToOne @JoinColumn(name = "lao_po_id", referencedColumnName = "woman_id") private Woman laoPo;
    @TableField(
    "company_id") private Long companyId; @TableField(exist = false) @ManyToOne @JoinColumn(name = "company_id", referencedColumnName = "company_id")
    private Company company;
    @TableField(exist
    = false) @OneToMany @JoinColumn(name = "man_id", referencedColumnName = "lao_han_id")
    @Lazy(false)
    private List<Child> waWa;
    
        @TableField(exist = false)
        @OneToMany
        @JoinColumn(name = "man_id", referencedColumnName = "man_id")
        @Lazy(false)
        private Set<Tel> tels;
    
    }

    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,实现自动关联。

           mapper(entity_entityListOrSet_entityPage)         统一上边的各种方法,直接对实体类,列表,分页都可以实现自动关联。


           initialize(entity/entityList/entitySet/entityPage,    OneOrMoreLazyPropertyName ...)                   

           可以对一个实体类/实体类List/实体类Set/实体类Page,在事务范围内,手动立即触发其各个被@Lazy(true)标注的关联属性。

          该方法在重写过的ServiceImpl内也存在(供Controller层调用来加载延迟关联的属性)。

           

    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);
        }
    
    }

      

     最新版本POM:

    <dependency>
         <groupId>com.github.dreamyoung</groupId>
         <artifactId>mprelation</artifactId>
         <version>0.0.3.2-RELEASE</version> 
    </dependency>

     

    github:   https://github.com/dreamyoung/mprelation

     
  • 相关阅读:
    java核心学习笔记(三) java集合框架
    java核心学习笔记(二) 学习环境与学习的方法以及java几个包的作用
    java核心学习笔记(一) javaJDK目录阐述
    版本控制工具git的配置
    linux系统管理员之自动化检测工具 nagios及其插件配置
    运维工程师需要的技能
    在线求中位数(优先队列实现) POJ3784
    并查集 poj1308
    stack HDU1022
    hash数组 POJ1840
  • 原文地址:https://www.cnblogs.com/dreamyoung/p/12466656.html
Copyright © 2020-2023  润新知