MyBatis注解开发---实现自定义映射关系和关联查询

Posted 会洗碗的CV工程师

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis注解开发---实现自定义映射关系和关联查询相关的知识,希望对你有一定的参考价值。

目录

一、使用注解实现自定义映射关系

1. 编写注解方法

2. 编写测试方法

3. 查看运行结果

二、使用注解实现一对一关联查询

1. 编写注解方法

2. 编写测试方法

3. 查看运行结果

三、使用注解实现一对多关联查询

1. 编写注解方法

2. 编写测试方法

3. 查看运行结果

四、注解文件和映射文件开发对比


一、使用注解实现自定义映射关系

        当POJO属性名与数据库列名不一致时,需要自定义实体类和结果集的映射关系,在MyBatis注解开发中,使用 @Results 定义并使用自定义映射,使用 @ResultMap 使用自定义映射,用法如下:

        前戏:为了体验这个效果,我们可以修改一下User实体类代码,如下

package com.example.pojo;

import java.io.Serializable;

public class User implements Serializable 
    private int id;
    private String username1;
    private String sex1;
    private String address1;

    public User(String programmer, String man, String shangHai) 
        this.username1 = programmer;
        this.sex1 = man;
        this.address1 = shangHai;
    

    public User(int i, String programmer_1, String woman, String shenzhen) 
        this.id = i;
        this.username1 = programmer_1;
        this.sex1 = woman;
        this.address1 = shenzhen;
    

    public User() 

    
 
    public int getId() 
        return id;
    

    public void setId(int id) 
        this.id = id;
    

    public String getUsername1() 
        return username1;
    

    public void setUsername1(String username1) 
        this.username1 = username1;
    

    public String getSex1() 
        return sex1;
    

    public void setSex1(String sex1) 
        this.sex1 = sex1;
    

    public String getAddress1() 
        return address1;
    

    public void setAddress1(String address1) 
        this.address1 = address1;
    

    @Override
    public String toString() 
        return "User[ " +
                "id=" + id +
                ", username1='" + username1 + '\\'' +
                ", sex1='" + sex1 + '\\'' +
                ", address1='" + address1 + '\\'' +
                " ]";
    

1. 编写注解方法

    // 查询所有用户
    @Results(id="userDiyMapper",value = 
            @Result(id = true,property = "id",column = "id"),
            @Result(property = "username1",column = "username"),
            @Result(property = "sex1",column = "sex"),
            @Result(property = "address1",column = "address")
    )
    @Select("select * from user")
    List<User> findAll1();

    // 根据id查询
    @ResultMap("userDiyMapper")
    @Select("select * from user where id = #id")
    User findById(int id);

注意啊:这里property对应的是实体类属性名,column对应的就是数据库表的列名 

2. 编写测试方法

    @Test
    public void testFindAll1()
        List<User> all = userMapper.findAll1();
        all.forEach(System.out::println);
        System.out.println("---------------------");
        System.out.println(userMapper.findById(5));
    

        看看能否查询出所有用户和id为5的用户,并且留意对应的属性名 

3. 查看运行结果

        OK,看来都是符合我们的预期的。 

二、使用注解实现一对一关联查询

        在MyBatis的注解开发中对于多表查询只支持分解查询,不支持连接查询。

        这里我们采用学生表和班级表做对比,所以我们先新建Student实体类和Classes实体类

Classes实体类 

package com.example.pojo;

import java.util.List;

public class Classes 
    private int cid;
    private String className;
    private List<Student> studentList;

    public int getCid() 
        return cid;
    

    public void setCid(int cid) 
        this.cid = cid;
    

    public String getClassName() 
        return className;
    

    public void setClassName(String className) 
        this.className = className;
    

    public List<Student> getStudentList() 
        return studentList;
    

    public void setStudentList(List<Student> studentList) 
        this.studentList = studentList;
    

    @Override
    public String toString() 
        return "Classes[ " +
                "cid=" + cid +
                ", className='" + className + '\\'' +
                ", studentList=" + studentList + 
                " ]";
    

Student实体类

package com.example.pojo;

public class Student 
    private int sid;
    private String name;
    private int age;
    private String sex;
    private Classes classes;

    public int getSid() 
        return sid;
    

    public void setSid(int sid) 
        this.sid = sid;
    

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

    public int getAge() 
        return age;
    

    public void setAge(int age) 
        this.age = age;
    

    public String getSex() 
        return sex;
    

    public void setSex(String sex) 
        this.sex = sex;
    

    public Classes getClasses() 
        return classes;
    

    public void setClasses(Classes classes) 
        this.classes = classes;
    

    @Override
    public String toString() 
        return "Student[ " +
                "sid=" + sid +
                ", name='" + name + '\\'' +
                ", age=" + age +
                ", sex='" + sex + '\\'' +
                ", classes=" + classes +
                " ]";
    

1. 编写注解方法

StudentMapper添加查询所有用户

package com.example.mapper;

import com.example.pojo.Student;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.mapping.FetchType;

import java.util.List;

public interface StudentMapper 
    @Select("select * from student")
    // 自定义映射关系
    @Results(id = "studentMapper",value = 
            @Result(id = true,property = "sid",column = "sid"),
            @Result(property = "name",column = "name"),
            @Result(property = "age",column = "age"),
            @Result(property = "sex",column = "sex"),
            /**
             * property:属性名
             * column:调用从表方法时传入的参数列
             * one:表示该属性是一个对象
             * select:调用的是从表方法
             * fetchType:加载方式
             */
            @Result(property = "classes",column = "classId",
                one = @One(select = "com.example.mapper.ClassesMapper.findByCid",
                        fetchType = FetchType.EAGER)
                )
    )
    List<Student> findAll();

ClassesMapper添加根据id查询班级

package com.example.mapper;

import com.example.pojo.Classes;
import org.apache.ibatis.annotations.Many;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.mapping.FetchType;

import java.util.List;

public interface ClassesMapper 
    // 根据id查询班级
    @Select("select * from classes where cid = #cid")
    Classes findByCid(Integer id);

2. 编写测试方法

// 测试一对一查询
    @Test
    public void testFindAllStudent()
        StudentMapper studentMapper = session.getMapper(StudentMapper.class);
        List<Student> all = studentMapper.findAll();
        all.forEach(System.out::println);
    

        看看能否查询出学生对应的班级,如果可以则查询成功 

3. 查看运行结果

        OK,看图我们是已经成功查询出每个学生对应的班级的 

三、使用注解实现一对多关联查询

        在这里我们主要实现查询所有班级的时候把对应的学生列表也查询出来。

1. 编写注解方法

StudentMapper添加根据班级id查询学生

// 根据班级Id查询学生
    @Select("select * from student where ClassId = #classId")
    List<Student> findByClassId(int classId);

Classes添加查询所有班级

// 查询所有班级
    @Select("select * from classes")
    @Results(id = "classMapper",value = 
            @Result(id = true,property = "cid",column = "cid"),
            @Result(property = "className",column = "className"),
            // many:表示该属性是一个集合
            @Result(property = "studentList",column = "cid",
            many = @Many(select = "com.example.mapper.StudentMapper.findByClassId",
                        fetchType = FetchType.LAZY))
    )
    List<Classes> findAll();

2. 编写测试方法

// 测试一对多查询
    @Test
    public void findAllClasses()
        ClassesMapper classesMapper = session.getMapper(ClassesMapper.class);
        List<Classes> all = classesMapper.findAll();
        all.forEach(System.out::println);
    

        观察能否查询出班级对应的学生列表

3. 查看运行结果

OK,确实也是可以查询出来了的。 

四、注解文件和映射文件开发对比

注解开发更快,映射文件更方便。

MyBatis中更推荐使用映射文件开发,SpringSpringBoot更推荐注解方式。具体使用要视项目情况而定。它们的优点对比如下:

映射文件:

  • 代码与Sql语句是解耦的,修改时只需修改配置文件,无需修改源码。
  • Sql语句集中,利于快速了解和维护项目。
  • 级联查询支持连接查询和分解查询两种方式,注解开发只支持分解查询。

注解:

  • 配置简单,开发效率高。
  • 类型安全,在编译期即可进行校验,不用等到运行时才发现错误。

我个人也是比较喜欢映射文件开发,主要更喜欢方便维护和了解。

MyBatis注解开发之多对多查询

文章目录

0. MyBatis的注解实现复杂映射开发

实现复杂关系映射之前我们可以在映射文件中通过配置来实现,使用注解开发后,我们可以使用@Results注解,@Result注解,@One注解,@Many注解组合完成复杂关系的配置


1. 多对多查询

1.1 多对多查询的模型

多对多查询的需求:查询学生以及所对应的课程信息

1.2 多对多查询的语句

对应的sql语句:

SELECT DISTINCT s.id,s.name,s.age FROM student s,stu_cr sc WHERE sc.sid=s.id

SELECT c.id,c.name FROM stu_cr sc,course c WHERE sc.cid=c.id AND sc.sid=#id

1.3 添加CourseMapper 接口方法

public interface CourseMapper 
    //根据学生id查询所选课程
    @Select("SELECT c.id,c.name FROM stu_cr sc,course c WHERE sc.cid=c.id AND sc.sid=#id")
    public abstract List<Course> selectBySid(Integer id);


1.4 使用注解配置Mapper

public interface StudentMapper 
    //查询全部
    @Select("SELECT DISTINCT s.id,s.name,s.age FROM student s,stu_cr sc WHERE sc.sid=s.id")
    @Results(
            @Result(column = "id",property = "id"),
            @Result(column = "name",property = "name"),
            @Result(column = "age",property = "age"),
            @Result(
                    property = "courses",   // 被包含对象的变量名
                    javaType = List.class,  // 被包含对象的实际数据类型
                    column = "id",          // 根据查询出student表的id来作为关联条件,去查询中间表和课程表
                    /*
                        many、@Many 一对多查询的固定写法
                        select属性:指定调用哪个接口中的哪个查询方法
                     */
                    many = @Many(select = "com.yyl.many_to_many.CourseMapper.selectBySid")
            )
    )
    public abstract List<Student> selectAll();


1.5 测试类

public class Test01 
    @Test
    public void selectAll() throws Exception
        //1.加载核心配置文件
        InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");

        //2.获取SqlSession工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);

        //3.通过工厂对象获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession(true);

        //4.获取StudentMapper接口的实现类对象
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);

        //5.调用实现类对象中的方法,接收结果
        List<Student> list = mapper.selectAll();

        //6.处理结果
        for (Student student : list) 
            System.out.println(student.getId() + "," + student.getName() + "," + student.getAge());
            List<Course> courses = student.getCourses();
            for (Course cours : courses) 
                System.out.println("\\t" + cours);
            
        

        //7.释放资源
        sqlSession.close();
        is.close();
    


运行结果如下:

1.6 多对多配置总结

注解说明
@Results封装映射关系的父注解。
Result[] value():定义了 Result 数组
@Result封装映射关系的子注解。
column 属性:查询出的表中字段名称
property 属性:实体对象中的属性名称
javaType 属性:被包含对象的数据类型
many 属性:一对多查询固定属性
@Many一对多查询的注解。
select 属性:指定调用某个接口中的方法

以上是关于MyBatis注解开发---实现自定义映射关系和关联查询的主要内容,如果未能解决你的问题,请参考以下文章

MyBatis注解开发之一对一查询

MyBatis注解开发之多对多查询

mybatis如何实现一对多关联关系

阶段3 1.Mybatis_04.自定义Mybatis框架基于注解开发_3 基于注解的自定义再分析

MyBatis高级 注解开发

Mybatis-自定义Enum映射