mybatis 级联

  级联是一个数据库实体的概念。一对多的级联,一对多的级联,在MyBatis中还有一种被称为鉴别器的级联,它是一种可以选择具体实现类的级联。
  级联不是必须的,级联的好处是获取关联数据十分便捷,但是级联过多会增加系统的复杂度,同时降低系统的性能,此增彼减,所以当级联的层级超过3层时,就不要考虑使用级联了,因为这样会造成多个对象的关联,导致系统的耦合、复杂和难以维护。在现实的使用过程中,要根据实际情况判断是否需要使用级联。

MyBatis中的级联

MyBatis的级联分为3种。
•鉴别器(discriminator):它是一个根据某些条件决定采用具体实现类级联的方案,比如体检表要根据性别去区分。
•一对一(association):比如学生证和学生就是一种一对一的级联,雇员和工牌表也是一种一对一的级联。
•一对多(collection):比如班主任和学生就是一种一对多的级联。
值得注意的是,MyBatis没有多对多级联,因为多对多级联比较复杂,使用困难,而且可以通过两个一对多级联进行替换,所以MyBatis不支持多对多级联了。

  为了更好地阐述级联,先给出一个雇员级联模型,如图所示。

分析雇员级联模型:
•该模型是以雇员表为中心的。
•雇员表和工牌表是一对一的级联关系。
•雇员表和员工任务表是一对多的级联关系。
•员工任务表和任务表是一对一的级联关系。
•每个雇员都会有一个体检表,随着雇员表字段性别取值的不同,会有不同的关联表。
据此给出级联模型建表SQL,如代码清单所示。

DROP TABLE
IF EXISTS t_female_health_form;

DROP TABLE
IF EXISTS t_male_health_form;

DROP TABLE
IF EXISTS t_task;

DROP TABLE
IF EXISTS t_work_card;

DROP TABLE
IF EXISTS t_employee_task;

DROP TABLE
IF EXISTS t_employee;

/*==============================================================*/
/* Table: t_employee                                            */
/*==============================================================*/
CREATE TABLE t_employee (
    id INT (12) NOT NULL AUTO_INCREMENT,
    real_name VARCHAR (60) NOT NULL,
    sex INT (2) NOT NULL COMMENT ‘1 - 男              0 -女‘,
    birthday DATE NOT NULL,
    mobile VARCHAR (20) NOT NULL,
    email VARCHAR (60) NOT NULL,
    POSITION VARCHAR (20) NOT NULL,
    note VARCHAR (256),
    PRIMARY KEY (id)
);

/*==============================================================*/
/* Table: t_employee_task                                       */
/*==============================================================*/
CREATE TABLE t_employee_task (
    id INT (12) NOT NULL,
    emp_id INT (12) NOT NULL,
    task_id INT (12) NOT NULL,
    task_name VARCHAR (60) NOT NULL,
    note VARCHAR (256),
    PRIMARY KEY (id)
);

/*==============================================================*/
/* Table: t_female_health_form                                  */
/*==============================================================*/
CREATE TABLE t_female_health_form (
    id INT (12) NOT NULL AUTO_INCREMENT,
    emp_id INT (12) NOT NULL,
    heart VARCHAR (64) NOT NULL,
    liver VARCHAR (64) NOT NULL,
    spleen VARCHAR (64) NOT NULL,
    lung VARCHAR (64) NOT NULL,
    kidney VARCHAR (64) NOT NULL,
    uterus VARCHAR (64) NOT NULL,
    note VARCHAR (256),
    PRIMARY KEY (id)
);

/*==============================================================*/
/* Table: t_male_health_form                                    */
/*==============================================================*/
CREATE TABLE t_male_health_form (
    id INT (12) NOT NULL AUTO_INCREMENT,
    emp_id INT (12) NOT NULL,
    heart VARCHAR (64) NOT NULL,
    liver VARCHAR (64) NOT NULL,
    spleen VARCHAR (64) NOT NULL,
    lung VARCHAR (64) NOT NULL,
    kidney VARCHAR (64) NOT NULL,
    prostate VARCHAR (64) NOT NULL,
    note VARCHAR (256),
    PRIMARY KEY (id)
);

/*==============================================================*/
/* Table: t_task                                                */
/*==============================================================*/
CREATE TABLE t_task (
    id INT (12) NOT NULL,
    title VARCHAR (60) NOT NULL,
    context VARCHAR (256) NOT NULL,
    note VARCHAR (256),
    PRIMARY KEY (id)
);

/*==============================================================*/
/* Table: t_work_card                                           */
/*==============================================================*/
CREATE TABLE t_work_card (
    id INT (12) NOT NULL AUTO_INCREMENT,
    emp_id INT (12) NOT NULL,
    real_name VARCHAR (60) NOT NULL,
    department VARCHAR (20) NOT NULL,
    mobile VARCHAR (20) NOT NULL,
    POSITION VARCHAR (30) NOT NULL,
    note VARCHAR (256),
    PRIMARY KEY (id)
);

ALTER TABLE t_employee_task ADD CONSTRAINT FK_Reference_4 FOREIGN KEY (emp_id) REFERENCES t_employee (id)
ON DELETE RESTRICT ON UPDATE RESTRICT;

ALTER TABLE t_employee_task ADD CONSTRAINT FK_Reference_8 FOREIGN KEY (task_id) REFERENCES t_task (id)
ON DELETE RESTRICT ON UPDATE RESTRICT;

ALTER TABLE t_female_health_form ADD CONSTRAINT FK_Reference_5 FOREIGN KEY (emp_id) REFERENCES t_employee (id)
ON DELETE RESTRICT ON UPDATE RESTRICT;

ALTER TABLE t_male_health_form ADD CONSTRAINT FK_Reference_6 FOREIGN KEY (emp_id) REFERENCES t_employee (id)
ON DELETE RESTRICT ON UPDATE RESTRICT;

ALTER TABLE t_work_card ADD CONSTRAINT FK_Reference_7 FOREIGN KEY (emp_id) REFERENCES t_employee (id)
ON DELETE RESTRICT ON UPDATE RESTRICT;

建立POJO

  根据设计模型建立对应的POJO。首先看体检表,由于男性和女性的体检表有多个字段重复,于是可以先设计一个父类,然后通过继承的方式来完成POJO,体检表设计类图如图所示。

如图所示,其中MaleHealthForm和FemaleHealthForm是HealthForm的子类,由此可得3个关于体检表的POJO,如代码清单所示。

//体检表父类
public abstract class HealthForm {
    private Long id;
    private Long empId;
    private String heart;
    private String liver;
    private String spleen;
    private String lung;
    private String kidney;
    private String note;
}

//女性体检表
public class FemaleHealthForm extends HealthForm {
    private String uterus;
}

//男性体检表
public class MaleHealthForm extends HealthForm {
    private String prostate;
}

接下来设计员工表、工牌表和任务表的POJO,它们是以员工表作为核心的,先完成工牌表和任务表的POJO,如代码清单所示。

//工牌
public class WorkCard {
    private Long id;
    private Long empId;
    private String realName;
    private String department;
    private String mobile;
    private String position;
    private String note;
}

//任务
public class Task {
    private Long id;
    private String title;
    private String context;
    private String note;
}

还剩雇员表和雇员任务表,它们有一定的关联。先从雇员任务表入手,雇员任务表是通过任务编号(task_id)和任务进行一对一关联的,这里只考虑其自身和任务编号的关联,而雇员对它的关联则由雇员去维护,这样就可以得到雇员任务POJO,如代码清单所示。

//雇员任务
public class EmployeeTask {
    private Long id;
    private Long empId;
    private Task task = null;
    private String taskName;
    private String note;
}

属性task是一个Task类对象,由它进行关联任务信息。设置雇员表是关键。雇员根据性别分为男雇员和女雇员,他们会有不同的体检表记录,但是无论男、女都是雇员,所以先建立一个雇员类(Employee)。它有两个子类:男雇员(MaleEmployee)和女雇员(FemaleEmployee)。在MyBatis中,这就是一个鉴别器,通过雇员类的字段性别(sex)来决定使用哪个具体的子类(MaleEmployee或者FemaleEmployee)初始化对象(Employee)。它与工牌表是一对一的关联关系,对于雇员任务表是一对多的关联关系,这样就可以得到3个类,如代码清单所示。

//雇员父类
public class Employee {
    private Long id;
    private String realName;
    private SexEnum sex = null;
    private Date birthday;
    private String mobile;
    private String email;
    private String position;
    private String note;
    //工牌按一对一级联
    private WorkCard workCard;
    // 雇员任务,一对多级联
    private List<EmployeeTask> emplyeeTaskList = null;
}

//男雇员类
public class MaleEmployee extends Employee {
    private MaleHealthForm maleHealthForm = null;
}

//女雇员类
public class FemaleEmployee extends Employee {
    private FemaleHealthForm femaleHealthForm = null;
}

MaleEmployee和FemaleEmployee都继承了Employee类,有着不同的体检表。Employee类是通过employeeTaskList属性和多个雇员任务进行一对多关联的,而工牌表是通过WorkCard进行一对一关联的,这样就完成了所有POJO的设计。

配置映射文件

<?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">
<mapper namespace="com.xc.mapper.employee.TaskMapper">

    <select id="getTask" parameterType="long" resultType="com.xc.pojo.employee.Task">
        select id, title, context, note
        from t_task
        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">
<mapper namespace="com.xc.mapper.employee.WorkCardMapper">

    <select id="getWorkCardByEmpId" parameterType="long" resultType="com.xc.pojo.employee.WorkCard">
        SELECT id, emp_id as empId, real_name as realName, department, mobile, position, note
        FROM t_work_card
        where emp_id = #{empId}
    </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">
<mapper namespace="com.xc.mapper.employee.EmployeeTaskMapper">

    <resultMap type="com.xc.pojo.employee.EmployeeTask" id="EmployeeTaskMap">
        <id column="id" property="id"/>
        <result column="emp_id" property="empId"/>
        <result column="task_name" property="taskName"/>
        <result column="note" property="note"/>
        <association property="task" column="task_id" select="com.xc.mapper.employee.TaskMapper.getTask"/>
    </resultMap>

    <select id="getEmployeeTaskByEmpId" parameterType="long" resultMap="EmployeeTaskMap">
        select id, emp_id, task_name, task_id, note
        from t_employee_task
        where emp_id = #{empId}
    </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">
<mapper namespace="com.xc.mapper.employee.MaleHealthFormMapper">

    <select id="getMaleHealthForm" parameterType="long" resultType="com.xc.pojo.employee.MaleHealthForm">
        select id,
               heart,
               liver,
               spleen,
               lung,
               kidney,
               prostate,
               note
        from t_male_health_form
        where emp_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">
<mapper namespace="com.xc.mapper.employee.FemaleHealthFormMapper">

    <select id="getFemaleHealthForm" parameterType="long" resultType="com.xc.pojo.employee.FemaleHealthForm">
        select id,
               heart,
               liver,
               spleen,
               lung,
               kidney,
               uterus,
               note
        from t_female_health_form
        where emp_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">

<mapper namespace="com.xc.mapper.employee.EmployeeMapper">

    <resultMap type="com.xc.pojo.employee.Employee" id="employee">
        <id column="id" property="id"/>
        <result column="real_name" property="realName"/>
        <result column="sex" property="sex" typeHandler="com.xc.util.typehandler.SexEnumTypeHandler"/>
        <result column="birthday" property="birthday"/>
        <result column="mobile" property="mobile"/>
        <result column="email" property="email"/>
        <result column="position" property="position"/>
        <result column="note" property="note"/>
        <!--association元素,对工牌进行一对一级联-->
        <association property="workCard" column="id" select="com.xc.mapper.employee.WorkCardMapper.getWorkCardByEmpId"/>
        <!--collection元素,一对多级联-->
        <collection property="employeeTaskList" column="id"
        select="com.xc.mapper.employee.EmployeeTaskMapper.getEmployeeTaskByEmpId"/>
        <!--discriminator元素,鉴别器-->
        <discriminator javaType="long" column="sex">
            <case value="1" resultMap="maleHealthFormMapper"/>
            <case value="2" resultMap="femaleHealthFormMapper"/>
        </discriminator>
    </resultMap>

    <resultMap type="com.xc.pojo.employee.FemaleEmployee" id="femaleHealthFormMapper" extends="employee">
        <association property="femaleHealthForm" column="id"
        select="com.xc.mapper.employee.FemaleHealthFormMapper.getFemaleHealthForm"/>
    </resultMap>

    <resultMap type="com.xc.pojo.employee.MaleEmployee" id="maleHealthFormMapper" extends="employee">
        <association property="maleHealthForm" column="id" select="com.xc.mapper.employee.MaleHealthFormMapper.getMaleHealthForm"/>
    </resultMap>

    <select id="getEmployee" parameterType="long" resultMap="employee">
        select id,
               real_name as realName,
               sex,
               birthday,
               mobile,
               email,
               position,
               note
        from t_employee
        where id = #{id}
    </select>

</mapper>

原文地址:https://www.cnblogs.com/ooo0/p/10946055.html

时间: 2024-10-12 02:22:47

mybatis 级联的相关文章

MyBatis 级联查询一对一与一对多

mybatis是通过映射sql语句把关系模型(数据库中的表)与领域模型(java中的实体类)关联起的  简单分析级联查询:       关系模型中:表与表只有主外键关联       领域模型中:实体类与实体类这间关联,只有一和多的关系.                            一是指别一个实体类以对象属性存在当前实体类中.                            多是指别一个实体类以集合对象属性存在当前实体类中 下面我以例子的形式给大家说明:数据库脚本如下:drop

Mybatis级联操作

对于Mybatis级联操作,网上好多资料都在讲级联查询的一些Mapping的标签,但是对于级联更新和插入的资料不是很多,但是这似乎是和Mybatis关系不大,只是之前用Hibernate用习惯了,感觉这些东西是由持久层框架l来维护的,由于Mybatis比Hibernate高效,摒弃了这些,所以对于INSERT和UPDATE的级联关系大部分是由数据库本身去维护的. 级联更新 有两个对象A和B,B的主键是A的外键,先需求是把B的保存后,在A的外键那随之更新: (1)先插入B到数据库中, (2)从数据

Mybatis 级联插入更新

刚开始接触Mybatis,在进行级联插入更新时发现不是很方便: 现有表A和B,B表的主键为A表的外键,先有需求是,插入一条B,并且与B关联的A也随之更新其外键. 所做的方式是先Save一条B, 然后查找出来B. 然后通过A的Set 方法把B set进去 然后UPDATE A 过程比较繁琐,不知大家有没有什么好的做法

MyBatis级联第四篇——N+1问题和全局延迟加载【推荐,MyBatis级联重要的一篇原创,建议认真读】

前面的三篇是我们介绍入门的章节,然而级联并非我们想象的那样简单.下面我们先描述一下N+1问题,再讨论全局设定的延迟加载. 1.N+1问题 在做完前面三篇入门的例子后,让我们运行一下以下: package com.ykzhen2014.csdn.main; import org.apache.ibatis.session.SqlSession; import com.ykzhen2014.csdn.util.SqlSessionFactoryUtil; import com.ykzhen2015.

mybatis级联

mybatis中有时候表不能都分成单表进行查询,表之间会有联系,这时候需要将表进行级联 下面讲一下如何将mybatis中 的表进行级联.映射表关系如下 1:创建数据表 DROP TABLE IF EXISTS t_female_health_form; DROP TABLE IF EXISTS t_male_health_form; DROP TABLE IF EXISTS t_task; DROP TABLE IF EXISTS t_work_card; DROP TABLE IF EXIST

mybatis 级联查询

MyBatis之级联小结

在这之前我们知道了MyBatis为我们提供了三种级联:一对一关系(assocation).一对多关系(collection).鉴别器(discriminator).在最后一个鉴别器例子中,看到了当层级关系比较负责时,我们似乎已经难以应对和维护各种级联关系,在对数据库进行查询是否应用MyBatis为我们提供的级联这需要在实际中去斟酌和取舍.在我们通过级联来查询信息时会发现有一个问题,当我们只想查询出学生的普通信息(姓名.性别),而不想查询出他的成绩.课程.体检表时,之前的三个例子不管你是否需要成绩

深入理解Mybatis原理与技术

目录 第1章 Mybatis简介 1.1 传统的JDBC编程 1.2 ORM模型 1.4 MyBatis 1.5 什么时候用MyBatis 第2章 MyBatis入门 2.2 MyBatis构成 2.3 SqlSession的作用 2.4 映射器 2.4.1 使用XML配置方式 2.4.2 使用注解的方式 2.4.3 MyBatis映射原理 2.5 生命周期 2.5.1 SqlSessionFactoryBuilder 2.5.2 SqlSessionFactory 2.5.3 SqlSessi

【MyBatis】Mapper XML 文件

Mapper XML文件 MyBatis 的真正强大在于它的映射语句,也是它的魔力所在.由于它的异常强大,映射器的 XML 文件就显得相对简单.如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码.MyBatis 就是针对 SQL 构建的,并且比普通的方法做的更好. SQL 映射文件有很少的几个顶级元素(按照它们应该被定义的顺序): cache – 给定命名空间的缓存配置. cache-ref – 其他命名空间缓存配置的引用. resultMap – 是最复杂