Mybatis处理数据库中关联关系

605 阅读6分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

Mybatis处理数据库中关联关系

数据库关联关系

# 数据库关联关系
- 一对一关联关系、一对多关联关系、多对多关联关系
- 一对一:用户信息 --> 唯一的身份信息
- 一对多:部门信息 --> 员工信息
- 多对多:老师信息 --> 学生信息		还有 学生信息 --> 课程信息

1. 一对一关联关系处理

mybatis处理一对一关联关系中保存(插入操作)

  • 数据库中有如下两张表:

    -- 一对一关联关系
    
    -- 用户信息表
    create table t_person(
    	id int(6) PRIMARY KEY auto_increment,
    	name varchar(40),
    	age int(3), 
    	cardno varchar(18) REFERENCES	t_info(cardno)
    );
    
    -- 身份信息表
    create table t_info(
    	id int(6) PRIMARY KEY auto_increment,
    	cardno varchar(18),
    	address varchar(100)
    );
    
  • mybatis中保存身份信息

    java中身份对象:

    
    public class Info {
    
        private Integer id;
        private String cardno;  // 身份证号
        private String address; // 地址
    
        // 为了不占用太大的篇幅,get、set、toString方法就不复制了,但是这些方法是有的
        get,set,toString...
    }
    

    在这里插入图片描述

    身份信息接口InfoDAO:

    public interface InfoDAO {
    
        // 保存身份信息的方法
        int save(Info info);
    }
    

    在这里插入图片描述

    创建mapper配置文件,并在文件里面添加save对应的实现:

    <mapper namespace="com.baizhi.dao.InfoDAO">
    
        <!--save-->
        <insert id="save" parameterType="com.baizhi.eneity.Info" keyProperty="id" useGeneratedKeys="true">
            insert into t_info values (#{id}, #{cardno}, #{address})
        </insert>
    
    </mapper>
    

    在这里插入图片描述

    另外还要在mybatis-config.xml文件中注册mapper配置文件:

    <!--注册项目中mapper.xml配置文件-->
    <mappers>
        <!--身份信息-->
        <mapper resource="com/baizhi/mapper/InfoDAO.xml"/>
    </mappers>
    

    在这里插入图片描述

    保存身份信息的java代码:

    // 保存信息
    @Test
    public void testSaveInfo() throws IOException {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        InfoDAO infoDAO = sqlSession.getMapper(InfoDAO.class);
        try {
            Info info = new Info();
            info.setCardno("165342789384233455");
            info.setAddress("北京市朝阳区");
            infoDAO.save(info);
            sqlSession.commit();
        } catch (Exception e) {
            e.printStackTrace();
            sqlSession.rollback();
        } finally {
            MybatisUtil.close(sqlSession);
        }
    }
    

    在这里插入图片描述

    结果:

    在这里插入图片描述

  • mybatis中保存用户信息

    java中用户对象:

    
    // 用户信息
    public class Person {
    
        private Integer id;
        private String name;
        private Integer age;
        private String cardno;  // 外键
        // 为了不占用太大的篇幅,get、set、toString方法就不复制了,但是这些方法是有的
        get,set,toString...
    }
    

    在这里插入图片描述

    用户信息接口PersonDAO:

    public interface PersonDAO {
    
        // 保存用户信息方法
        public void save(Person person);
    }
    

    在这里插入图片描述

    创建mapper配置文件,并在文件里面添加save对应的实现:

    <mapper namespace="com.baizhi.dao.PersonDAO">
    
        <!--保存用户信息的方法-->
        <insert id="save" parameterType="com.baizhi.eneity.Person" keyProperty="id" useGeneratedKeys="true">
            insert into t_Person values (#{id}, #{name}, #{age}, #{cardno})
        </insert>
    
    </mapper>
    

    在这里插入图片描述

    另外还要在mybatis-config.xml文件中注册mapper配置文件:

    <!--注册项目中mapper.xml配置文件-->
    <mappers>
        <!--用户信息-->
        <mapper resource="com/baizhi/mapper/PersonDAO.xml"/>
    </mappers>
    

    在这里插入图片描述

    保存用户信息的java代码:

    // 保存用户信息
        @Test
        public void testSavePerson() throws IOException {
            SqlSession sqlSession = MybatisUtil.getSqlSession();
            PersonDAO personDAO = sqlSession.getMapper(PersonDAO.class);
    
            try {
                Person person = new Person();
                person.setName("小陈");
                person.setAge(23);
                // 外键信息
                person.setCardno("165342789384233455");
                personDAO.save(person);
                sqlSession.commit();
            } catch (Exception e) {
                e.printStackTrace();
                sqlSession.rollback();
            } finally {
                MybatisUtil.close(sqlSession);
            }
        }
    

    在这里插入图片描述

    结果:

    在这里插入图片描述

mybatis处理一对一关联关系中查询(查询操作)

  • 根据用户信息并将他(她)的身份信息一并查询

    在java中用对象表示关系,我们可以在用户类里面定义一个身份信息对象,表示关系。

    在这里插入图片描述

    在PersonDAO接口中定义查询方法:

    // 查询所有用户信息(查询用户信息的同时把身份信息也查询出来)
    List<Person> queryAll();
    

    在对应的mapper配置文件中需要添加的内容:

    <resultMap id="personMap" type="com.baizhi.eneity.Person">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="age" property="age"/>
        <result column="cardno" property="cardno"/>
        <!--处理一对一 association: 用来处理一对一关联关系的标签 property: 用来书写封装的关系属性名-->
        <!--javaType: 关系属性的java类型-->
        <association property="info" javaType="com.baizhi.eneity.Info">
            <id column="iid" property="id"/>
            <result column="icardno" property="cardno"/>
            <result column="address" property="address"/>
        </association>
    </resultMap>
    <!--查询所有(查询用户信息的同时也把身份信息查出来)-->
    <select id="queryAll" resultMap="personMap">
        select p.id, p.name, p.age, p.cardno,
               i.id iid, i.cardno icardno, i.address
        from t_person p
        left join t_info i
        on p.cardno = i.cardno
    </select>
    

    在这里插入图片描述

    查询的java代码:

    // 查询所有用户信息(查询用户信息的同时也把身份信息查询出来)
    // 查询不需要控制事务,所以查询完后直接关闭,不用try/catch/finally
    @Test
    public void testQueryAll() throws IOException {
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        PersonDAO personDAO = sqlSession.getMapper(PersonDAO.class);
        // maven默认jdk1.7,lambda表达式是在1.8添加的,这里 Alt + 回车
        personDAO.queryAll().forEach(person -> {
            System.out.println("当前用户信息:" + person + "身份信息:" + person.getInfo());
        });
        MybatisUtil.close(sqlSession);
    }
    

    结果:

    在这里插入图片描述

2. 一对多关联关系处理

数据库表:

-- 部门表
create table t_dept(
	id int(6)	primary key auto_increment,
	name varchar(40)
);

-- 员工表
create table t_emp(
	id int(6)	primary key auto_increment,
	name varchar(40),
	age int(3),
	bir timestamp,
	deptid int(6) references t_dept(id)
);
-- 注意:在处理一对多关联关系时外键最好在多的一方

在这里插入图片描述

在这里插入图片描述

根据一查询多的一方(查询所有部门并将部门中所有的员工查询出来)

构建部门对象、员工对象:

// 部门对象
public class Dept {

    private Integer id;
    private String name;

    // 对象   关系属性
    private List<Emp> emps; //员工

    // 为了不占用太大的篇幅,get、set、toString方法就不复制了,但是这些方法是有的
    get,set,toString...
}
// 员工对象

public class Emp {

    private Integer id;
    private String name;
    private Integer age;
    private Date bir;
    // 为了不占用太大的篇幅,get、set、toString方法就不复制了,但是这些方法是有的
    get,set,toString...
}

在这里插入图片描述

构建DeptDAO接口,并定义查询所有部门并将每个部门的员工信息查询出来的方法:

public interface DeptDAO {

    // 查询所有部门并将每个部门的员工信息查询出来
    List<Dept> queryAll();
}

在这里插入图片描述

创建DeptDAO对应的mapper配置文件:

<mapper namespace="com.baizhi.dao.DeptDAO">

    <!--resultMap-->
    <resultMap id="deptMap" type="com.baizhi.eneity.Dept">
        <!--封装部门信息-->
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <!--封装员工信息  如果是一对一用association 但是如果一对多,员工有多个用collection标签-->
        <!--collection 用来处理一对多关联关系时的标签
            property :封装的关系属性名(关系名,也就是对象的名字,在java中用对象表示关系)
            javaType:关系属性类型(类的名字)
            ofType:用来书写关系属性中泛型的类型(也就是List结合中封装的类的类型)
        -->
        <collection property="emps" javaType="java.util.List" ofType="com.baizhi.eneity.Emp">
            <id column="eid" property="id"/>
            <result column="ename" property="name"/>
            <result column="age" property="age"/>
            <result column="bir" property="bir"/>
        </collection>
    </resultMap>

    <!--查询所有部门-->
    <select id="queryAll" resultMap="deptMap">
        select
            d.id,
            d.name,
            e.id eid,
            e.name ename,
            e.age,
            e.bir
        from
            t_dept d
                left join t_emp e on d.id = e.deptid;
    </select>
</mapper>

在这里插入图片描述

最后要在主配置文件mybatis-config.xml中注册一下mapper文件:

在这里插入图片描述

执行查询操作的java代码:

// 查询所有
@Test
public void testQueryAll() throws IOException {
    SqlSession sqlSession = MybatisUtil.getSqlSession();
    DeptDAO deptDAO = sqlSession.getMapper(DeptDAO.class);
    deptDAO.queryAll().forEach(dept -> {
        System.out.println("部门信息:====>" + dept);
        dept.getEmps().forEach(emp -> {
            System.out.println("        员工信息:====>" + emp);
        });
        System.out.println("---------------------");
    });

    MybatisUtil.close(sqlSession);
}

结果:

在这里插入图片描述

查询员工并查询每个员工的部门

创建EmpDAO接口:

public interface EmpDAO {

    // 查询所有员工并查询每个员工的部门
    List<Emp> queryAll();
}

在Emp类中添加一个dept对象表示关系:

在这里插入图片描述

创建对应的mapper配置文件:

<mapper namespace="com.baizhi.dao.EmpDAO">

    <resultMap id="empMap" type="com.baizhi.eneity.Emp">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="age" property="age"/>
        <result column="bir" property="bir"/>
        <!--封装部门信息-->
        <association property="dept" javaType="com.baizhi.eneity.Dept">
            <id column="did" property="id"/>
            <result column="dname" property="name"/>
        </association>
    </resultMap>
    <select id="queryAll" resultMap="empMap">
        select
               e.id, e.name, e.age, e.bir,
               d.id did, d.name dname
        from t_emp e
        left join t_dept d
        on e.deptid = d.id
    </select>
</mapper>

在这里插入图片描述

在主配置文件mybatis-config.xml中注册mapper配置文件:

在这里插入图片描述

查询所有员工并查询员工所在部门的java代码:

// queryAll
@Test
public void testQueryAll() throws IOException {
    SqlSession sqlSession = MybatisUtil.getSqlSession();
    EmpDAO empDAO = sqlSession.getMapper(EmpDAO.class);
    empDAO.queryAll().forEach(emp -> {
        System.out.println("员工信息:" + emp + "    " + "部门信息:" + emp.getDept());
    });
    MybatisUtil.close(sqlSession);
}

在这里插入图片描述

3. 多对多关联关系处理

学生和课程关系是多对多关系

数据库中的表:

-- 学生表
create table t_student(
	id int(6) primary key auto_increment,
	name varchar(2)
);

-- 课程表
create table t_course(
	id int(6) primary key auto_increment,
	name varchar(2)
);

-- 中间表
create table t_student_course(
	id int(6) primary key auto_increment,
	sid int(6) references t_student(id),
	cid int(6) references t_course(id)
);

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

java中的学生类、课程类:

// 学生类
public class Student {

    private Integer id;
    private String name;

    // 关系属性  课程  选择哪些课
    private List<Course> courses;
	
    // 为了不占用太大的篇幅,get、set、toString方法就不复制了,但是这些方法是有的
    get,set,toString...
}
// 课程类
public class Course {

    private Integer id;
    private String name;

    // 关系属性 当前课程被哪些学生选择
    private List<Student> students;
    
    // 为了不占用太大的篇幅,get、set、toString方法就不复制了,但是这些方法是有的
    get,set,toString...
}

用学生的id查询学生的信息并查询该学生的课程信息

创建StudentDAO接口:

public interface StudentDAO {

    // 查询学生信息并查询所选课程
    Student queryById(Integer id);
}

在这里插入图片描述

创建对应的mapper配置文件:

<mapper namespace="com.baizhi.dao.StudentDAO">

    <resultMap id="studentMap" type="com.baizhi.eneity.Student">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <!--关系属性 多-->
        <collection property="courses" javaType="java.util.List" ofType="com.baizhi.eneity.Course">
            <id column="cid" property="id"/>
            <result column="cname" property="name"/>
        </collection>
    </resultMap>
    <!--queryById-->
    <select id="queryById" parameterType="Integer" resultMap="studentMap">
        select
            s.id, s.name,
            c.id cid, c.name cname
        from t_student s
                 left join t_student_course tc
                           on s.id = tc.sid
                 left join t_course c
                           on tc.cid = c.id
        where s.id = #{id}
    </select>
</mapper>

在这里插入图片描述

在主配置文件mybatis-config.xml中注册:

在这里插入图片描述

执行的由id查询操作的代码:

@Test
public void testQueryById() throws IOException {
    SqlSession sqlSession = MybatisUtil.getSqlSession();
    StudentDAO studentDAO = sqlSession.getMapper(StudentDAO.class);
    Student student = studentDAO.queryById(11);
    System.out.println("学生信息:" + student);
    student.getCourses().forEach(course -> {
        System.out.println("    课程信息:" + course);
    });
    MybatisUtil.close(sqlSession);
}

结果:

在这里插入图片描述