MyBatis learning summary (eight): MyBatis one-to-many and many-to-one query

One, one-to-many query

The one-to-many query environment is still based on the previous article. A department can have multiple employees, and there are three ways to implement one-to-many, which is consistent with the one-to-one query method. The difference is the one-to-one query method. , One-to-many uses collection.

Method 1: Nested query

(1) Add the collection attribute empList to Dept, and provide get and set methods, overwrite toString; remove the dept attribute in Emp and related methods.

public class Dept {
    private Integer id;
    private String deptName;
    private String deptDesc;
    private List<Emp> empList; 

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public String getDeptDesc() {
        return deptDesc;
    }

    public void setDeptDesc(String deptDesc) {
        this.deptDesc = deptDesc;
    }

    public List<Emp> getEmpList() {
        return empList;
    }

    public void setEmpList(List<Emp> empList) {
        this.empList = empList;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "id=" + id +
                ", deptName='" + deptName + '\'' +
                ", deptDesc='" + deptDesc + '\'' +
                ", empList=" + empList +
                '}';
    }
}
public class Emp {
    private Integer id;
    private String empName;
    private String empAge;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public String getEmpAge() {
        return empAge;
    }

    public void setEmpAge(String empAge) {
        this.empAge = empAge;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "id=" + id +
                ", empName='" + empName + '\'' +
                ", empAge='" + empAge + '\'' +
                '}';
    }
}

 (2) Add a method in IDeptDao.java

Dept selectDeptAndEmp(int id);

(3) Add sql mapping statement in deptMapper.xml and modify query statement in empMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace:指定了唯一的命名空间-->
<mapper namespace="com.day1.dao.IDeptDao">
    <resultMap type="com.day1.entity.Dept" id="deptAndEmp">
        <id property="id" column="id" />
        <result property="deptName" column="dept_name" />
        <result property="deptDesc" column="dept_desc" />
        <!-- 一对多级联查询,ofType表示集合中的元素类型,将uid传递给selectOrdersByld -->
        <collection property="empList" ofType="com.day1.entity.Emp"
                    column="id" select="com.day1.dao.IEmpDao.selectEmpById" />
    </resultMap>
    <select id="selectDeptAndEmp" parameterType="int"  resultMap="deptAndEmp">
        select * from t_dept where id = #{id}
    </select>
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace:指定了唯一的命名空间-->
<mapper namespace="com.day1.dao.IEmpDao">
        <resultMap type="com.day1.entity.Emp" id="emp">
            <id property="id" column="id"/>
            <result property="empName" column="emp_name"/>
            <result property="empAge" column="emp_age"/>
        </resultMap>
        <select id="selectEmpById" parameterType="int" resultMap="emp">
            select * from t_emp where dept_id = #{id};
        </select>
</mapper>

 (3) Perform testing

    @Test
    public void testSelect02() throws IOException {
        //1、读取配置文件
        InputStream in = Resources.getResourceAsStream("SqlMapperConfig.xml");
        //2、创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        //3、使用工厂生产SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //4、使用SqlSession创建dao接口的代理对象
        IDeptDao deptDao= sqlSession.getMapper(IDeptDao.class);
        //5、使用代理对象执行方案
        Dept dept = deptDao.selectDeptAndEmp(2);
        System.out.println(dept);
        //6、释放资源
        sqlSession.close();
        in.close();
    }

Method 2: Nested results

<resultMap type="com.day1.entity.Dept" id="deptAndEmp">
        <id property="id" column="id" />
        <result property="deptName" column="dept_name" />
        <result property="deptDesc" column="dept_desc" />
        <!-- 一对多级联查询,ofType表示集合中的元素类型,将uid传递给selectOrdersByld -->
        <collection property="empList" ofType="com.day1.entity.Emp">

            <result property="empName" column="emp_name"/>
            <result property="empAge" column="emp_age"/>
        </collection>
    </resultMap>
    <select id="selectDeptAndEmp" parameterType="int"  resultMap="deptAndEmp">
    select d.*, e.* from t_dept d, t_emp e where d.id=#{id} and  d.id=e.dept_id;
    </select>

 Small details: The id attribute of emp is not mapped in the collection. This is because when the primary key names of the primary table and the secondary table are the same, if the resultMap does not define a field similar to the primary key that can distinguish each result set, it will cause the latter data to overwrite the previous data, resulting in query results There is only one piece of data.

Solution:

Modify the id name of the main table or the detailed table to ensure inconsistency or give an alias to the query result.

Method 3: Use POJO to store results

Create an extended class of Dept

public class DeptExtend {
    private Integer id;
    private String deptName;
    private String deptDesc;
    private String empName;
    private String empAge;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public String getDeptDesc() {
        return deptDesc;
    }

    public void setDeptDesc(String deptDesc) {
        this.deptDesc = deptDesc;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public String getEmpAge() {
        return empAge;
    }

    public void setEmpAge(String empAge) {
        this.empAge = empAge;
    }

    @Override
    public String toString() {
        return "DeptExtend{" +
                "id=" + id +
                ", deptName='" + deptName + '\'' +
                ", deptDesc='" + deptDesc + '\'' +
                ", empName='" + empName + '\'' +
                ", empAge='" + empAge + '\'' +
                '}';
    }
}

Modify the SQL mapping statement

    <resultMap type="com.day1.entity.DeptExtend" id="deptExtend">
        <id property="id" column="id"/>
        <result property="deptName" column="dept_name"/>
        <result property="deptDesc" column="dept_desc"/>
        <result property="empName" column="emp_name"/>
        <result property="empAge" column="emp_age"/>
    </resultMap>
    <select id="selectDeptAndEmp" parameterType="int" resultMap="deptExtend">
        select d.*, e.* from t_dept d, t_emp e where d.id=#{id} and  d.id=e.dept_id;
       </select>

Modify the method in IDeptDao

    List<DeptExtend> selectDeptAndEmp(int id);

Modify the test method

    @Test
    public void testSelect02() throws IOException {
        //1、读取配置文件
        InputStream in = Resources.getResourceAsStream("SqlMapperConfig.xml");
        //2、创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        //3、使用工厂生产SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //4、使用SqlSession创建dao接口的代理对象
        IDeptDao deptDao= sqlSession.getMapper(IDeptDao.class);
        //5、使用代理对象执行方案
        List<DeptExtend> deptExtends = deptDao.selectDeptAndEmp(2);
        for(DeptExtend dept : deptExtends){
            System.out.println(dept);
        }
        //6、释放资源
        sqlSession.close();
        in.close();
    }

Two, many-to-one query

There are two ways of many-to-one query. Here we demonstrate the relationship between students and teachers.

Method 1: Nested query

(1) Create teacher table and student table and insert data.

 CREATE TABLE `t_teacher` (
  `tid` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  `major` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`tid`)
);
 insert into t_teacher(name, major) values("张娟","化学");
 insert into t_teacher(name, major) values("刘峰","物理");
CREATE TABLE `t_student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(30) DEFAULT NULL,
  `tid` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
);
insert into t_student(name, tid) values("张龙", 2);
 insert into t_student(name, tid) values("李飞", 2);
insert into t_student(name, tid) values("王刚", 1);
insert into t_student(name, tid) values("张倩", 1);
insert into t_student(name, tid) values("杨玉", 2);
insert into t_student(name, tid) values("刘菲", 2);

(2) Create entity classes Student and Teacher

Teacher category:

public class Teacher {
    private Integer tid;
    private String name;
    private String major;

    public Integer getTid() {
        return tid;
    }

    public void setTid(Integer tid) {
        this.tid = tid;
    }

    public String getName() {
        return name;
    }

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

    public String getMajor() {
        return major;
    }

    public void setMajor(String major) {
        this.major = major;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "tid=" + tid +
                ", name='" + name + '\'' +
                ", major='" + major + '\'' +
                '}';
    }
}

Student class:

public class Student {
   private Integer id;
   private String name;
   private Teacher teacher;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public Teacher getTeacher() {
        return teacher;
    }

    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", teacher=" + teacher +
                '}';
    }
}

(3) Create ITeacherDao and ITudentDao

ITeacherDao

public interface ITeacherDao {
    Teacher findTeacherById(int id);
}

IStudentDao

public interface IStudentDao {
    List<Student> findAll();
}

(4) Create studentMapper.xml and teacherMapper.xml

teacherMapper.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace:指定了唯一的命名空间-->
<mapper namespace="com.day1.dao.ITeacherDao">

    <select id="findTeacherById" parameterType="int" resultType="com.day1.entity.Teacher">
        select * from t_teacher where tid = #{tid}
    </select>
</mapper>

studentMapper.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace:指定了唯一的命名空间-->
<mapper namespace="com.day1.dao.IStudentDao">
    <select id="findAll" resultMap="studentTeacher">
        select * from t_student;
    </select>
    <!--
    思路:
    1. 查询所有的学生信息
    2.根据查询出来的学生的tid.寻找对应的老师!
    -->
    <resultMap id="studentTeacher" type="com.day1.entity.Student">
        <result property="id" column="id" />
        <result property="name" column="name"/>
        <!--复杂的属性,我们需要单独处理 对象: association 集合:collection -->
        <association property="teacher" column="tid" javaType="com.day1.entity.Teacher" select="com.day1.dao.ITeacherDao.findTeacherById"/>
    </resultMap>
</mapper>

(5) Configuration in SqlMapperConfig

        <mapper resource="com/day1/studentMapper.xml"></mapper>
        <mapper resource="com/day1/teacherMapper.xml"></mapper>

(6) Perform a test.

    @Test
    public void testSelect() throws IOException {
        //1、读取配置文件
        InputStream in = Resources.getResourceAsStream("SqlMapperConfig.xml");
        //2、创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        //3、使用工厂生产SqlSession对象
        SqlSession sqlSession = factory.openSession();
        //4、使用SqlSession创建dao接口的代理对象
        IStudentDao studentDao= sqlSession.getMapper(IStudentDao.class);
        //5、使用代理对象执行方案
        List<Student> students = studentDao.findAll();
        for(Student stu : students){
            System.out.println(stu);
        }
        //6、释放资源
        sqlSession.close();
        in.close();
    }

Method 2: Nested results

Modify the SQL mapping statement as follows:

<select id="findAll" resultMap="studentTeacher">
        select stu.id ,stu.name,t.name, t.major
         from t_student stu,t_teacher t
         where stu.tid = t.tid;
    </select>
    <resultMap id="studentTeacher" type="com.day1.entity.Student">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <collection property="teacher" javaType="com.day1.entity.Teacher">
            <result property="name" column="name"/>
            <result property="major" column="major"/>
        </collection>
    </resultMap>

 

Guess you like

Origin blog.csdn.net/weixin_47382783/article/details/113837595