MyBatis的使用七(处理表与表之间的关系)

科技资讯 投稿 6600 0 评论

MyBatis的使用七(处理表与表之间的关系)

一. 介绍t_emp和t_dept表

1. t_emp表结构

2. t_dept表结构

二. 数据表的关系

1. 阐明关系

2. 实体类pojo的声明

1 Employee类的声明如下

public class Employee { private Integer empId; private String empName; private Integer age; private String gender; private Department dept; public Employee( { } get和set(方法... @Override public String toString( { return "Employee{" + "empId=" + empId + ", empName='" + empName + '\'' + ", age=" + age + ", gender='" + gender + '\'' + ", dept=" + dept + '}'; } }

由于一个员工只能属于一个部门,因此在Employee中才会有 private Department dept 成员变量。

public class Department {
    private Integer deptId;
    private String deptName;

    private List<Employee> employees;

    public Department( {
    }

    get和set(方法...

    @Override
    public String toString( {
        return "Department{" +
                "deptId=" + deptId +
                ", deptName='" + deptName + '\'' +
                ", employees=" + employees +
                '}';
    }
}

由于一个部门可以有多个员工,因此在Department类中才会有 private List<Employee> employees 成员变量

三. 使用mybatis解决多对一【一对多】

1. 多对一的关系

1)提出问题:

当需要查询单个员工信息以及所在部门时,应该如何处理?

public interface EmpMapper {
    // 根据id查询员工信息
    Employee selectEmpAndDept(@Param("id" int id;
}

2)处理方式:

方式1:采用级联的方式

    <!--// 根据id查询员工信息
    Employee selectEmpAndDept(@Param("id" int id;-->
    <!--使用: resultType="Employee"结果: Employee{empId=4, empName='赵六', age=24, gender='男', dept=null}-->
    <!--级联-->
    <resultMap id="resultEmpAndDept1" type="Employee">
        <id column="emp_id" property="empId" />
        <result column="emp_name" property="empName" />
        <result column="dept_id" property="dept.deptId" />
        <result column="dept_name" property="dept.deptName" />
    </resultMap>
    <select id="selectEmpAndDept" resultMap="resultEmpAndDept1">
        SELECT t_emp.*,t_dept.`dept_name`
        FROM t_emp,t_dept
        WHERE t_emp.dept_id = t_dept.dept_id and emp_id = #{id}
    </select>

前面提过resultMap可以自定义映射名,下面阐述<resultMap>标签

<!-- resultMap: id:resultMap标签的唯一标识 type:返回类型 <id>:表t_emp的主键的字段名 <result>:表t_emp的非主键的字段名 其中 <result column="dept_id" property="dept.deptId" /> column:字段名dept_id,property:实体类的属性名dept.deptId 意义是将查询到的部门信息--封装--》Department对象 --赋值--》Employee类中的dept成员变量 --> <resultMap id="resultEmpAndDept1" type="Employee"> <id column="emp_id" property="empId" /> <result column="emp_name" property="empName" /> <result column="dept_id" property="dept.deptId" /> <result column="dept_name" property="dept.deptName" /> </resultMap>

注意:<result column="dept_id" property="dept.deptId" />,是Employee类的成员对象dept . 属性名

EmpMapper.xml文件声明如下

<resultMap id="resultEmpAndDept2" type="Employee"> <id column="emp_id" property="empId"></id> <result column="emp_name" property="empName"></result> <result column="age" property="age"></result> <result column="gender" property="gender"></result> <!--association的 property:是需要处理映射关系的属性名,如dept javaType:是设置要处理属性的类型名称--> <association property="dept" javaType="Department"> <id column="dept_id" property="deptId"></id> <id column="dept_name" property="deptName"></id> </association> </resultMap> <select id="selectEmpAndDept" resultMap="resultEmpAndDept2"> SELECT t_emp.*,t_dept.`dept_name` FROM t_emp,t_dept WHERE t_emp.dept_id = t_dept.dept_id and emp_id = #{id} </select>

下面阐述<association>标签 的内容

<!--association的 property:是需要处理映射关系的属性名,如dept javaType:是设置要处理属性的类型名称--> <association property="dept" javaType="Department"> <id column="dept_id" property="deptId"></id> <id column="dept_name" property="deptName"></id> </association>

方式3:采用分步查询

因此,需要创建DeptMapper接口,DeptMapper接口的声明如下

public interface DeptMapper { // 根据id查询部门 Department selectDeptById(@Param("id" int id; }

DeptMapper.xml文件声明如下

<!--namespace绑定mapper的接口所在的包名.接口名--> <mapper namespace="com.hspedu.mapper.DeptMapper"> <!--// 根据id查询部门 Department selectDeptById(@Param("id" int id;--> <select id="selectDeptById" resultType="Department"> select * from t_dept where dept_id = #{id} </select> </mapper>

EmpMapper.xml文件声明如下

<resultMap id="resultEmpAndDept3" type="Employee"> <id column="emp_id" property="empId"></id> <result column="emp_name" property="empName"></result> <result column="age" property="age"></result> <result column="gender" property="gender"></result> <!--association的 property:设置需要处理映射关系的属性的属性名 select:设置分步查询的sql语句的唯一标识 column:将select标签中查询出的某一个字段作为分步查询的条件 fetchType:是否开启延迟加载【针对某一个sql语句】eager立刻,lazy延迟 --> <association property="dept" fetchType="eager" select="com.hspedu.mapper.DeptMapper.selectDeptById" column="dept_id"> </association> </resultMap> <select id="selectEmpAndDeptThree" resultMap="resultEmpAndDept3" > select * from t_emp where emp_id = #{id} </select>

下面阐述 <association> 标签的内容

<!--association的 property:设置需要处理映射关系的属性的属性名 select:设置分步查询的sql语句的唯一标识 column:将select标签中查询出的某一个字段作为分步查询的条件 fetchType:在方法中是否开启延迟加载【针对某一个sql语句】eager立刻,lazy延迟 --> <association property="dept" fetchType="eager" select="com.hspedu.mapper.DeptMapper.selectDeptById" column="dept_id"> </association>

注意:association标签中的select的意义,

在t_dept表中按照部门编号dept_id查询相对应的部门信息。

分步查询 插入一个知识点:延迟加载

当我们只是想查询员工信息的姓名时,例如 

@Test // 查询指定id的员工信息 public void test02({ Employee employee = mapper.selectEmpAndDept(4; System.out.println(employee.getEmpName(; }

如果没有延迟加载的话,执行结果如下

DEBUG 02-04 15:37:05,646 ==> Parameters: 4(Integer (BaseJdbcLogger.java:137 DEBUG 02-04 15:37:05,669 ====> Preparing: select * from t_dept where dept_id = ? (BaseJdbcLogger.java:137 DEBUG 02-04 15:37:05,669 ====> Parameters: 100(Integer (BaseJdbcLogger.java:137 DEBUG 02-04 15:37:05,675 <==== Total: 1 (BaseJdbcLogger.java:137 DEBUG 02-04 15:37:05,677 <== Total: 1 (BaseJdbcLogger.java:137 赵六

即执行了查询员工信息的sql语句,又执行了查询部门信息的sql语句,如何让它不执行查询部门信息的sql语句呢?

在mybatis-config.xml文件中添加如下setting标签,引入延迟加载

<settings> <!--将MySQL中_映射为java的驼峰--> <setting name="mapUnderscoreToCamelCase" value="true"/> <!-- 开启延时加载【懒加载】--> <setting name="lazyLoadingEnabled" value="true"/> <!--强制加载所有的懒配置--> <setting name="aggressiveLazyLoading" value="false"/> </settings>

并将<association fetchType="eager"> 的  fetchType = "lazy",即在执行该sql语句时,使用延迟加载,执行结果如下

DEBUG 02-04 15:42:26,231 ==> Preparing: select * from t_emp where emp_id = ? (BaseJdbcLogger.java:137 DEBUG 02-04 15:42:26,261 ==> Parameters: 4(Integer (BaseJdbcLogger.java:137 DEBUG 02-04 15:42:26,322 <== Total: 1 (BaseJdbcLogger.java:137 赵六

只执行了查询员工信息的sql语句,说明延迟加载有了效果。

c> 延迟加载总结:

引入延迟加载,在mybatis配置文件中添加setting标签......【全局 延迟加载】

如果对于某一个sql语句,不想使用延迟加载,则<association fetchType="eager"> 【局部 不使用延迟加载】

3)总结:

将部门信息--反射-->Department类的对象--赋值-->Employee类的成员变量dept。

2. 一对多关系

1)提出问题

按照部门编号查询一个部门有多少员工?

public interface DeptMapper {

    // 查询一个部门有多少员工
    Department selectDeptAndEmp(@Param("id" int id;
}

2)处理方式

方式1:使用collection标签

    <!--// 查询一个部门有多少员工
    Department selectDeptAndEmp(@Param("id" int id;-->
    <resultMap id="resultDeptAndEmp1" type="Department">
        <id column="dept_id" property="deptId"></id>
        <result column="dept_name" property="deptName"></result>
        <collection property="employees" ofType="Employee">
            <id column="emp_id" property="empId"></id>
            <result column="emp_name" property="empName"></result>
            <result column="age" property="age" ></result>
            <result column="gender" property="gender"></result>
        </collection>
    </resultMap>
    <select id="selectDeptAndEmp" resultMap="resultDeptAndEmp1">
        SELECT t_emp.*,t_dept.*
        FROM t_emp,t_dept
        WHERE t_emp.`dept_id` = t_dept.`dept_id` and t_dept.dept_id = #{id}
    </select>

下面阐述collection标签

<collection property="employees" ofType="Employee"> <id column="emp_id" property="empId"></id> <result column="emp_name" property="empName"></result> <result column="age" property="age" ></result> <result column="gender" property="gender"></result> </collection>

property:实体类的成员变量【属性】,ofType:表示将查询的结果--封装-->实体类对象--装入-->集合

第一步:在t_dept表中根据传入的dept_id查询部门信息

EmpMapper接口的声明如下

public interface EmpMapper { // 根据部门编号查询员工信息 List<Employee> selectEmployeesByDeptId(@Param("id" int id; }

EmpMapper.xml文件声明如下

<!-- // 根据部门编号查询员工信息 List<Employee> selectEmployeesByDeptId(@Param("id" int id;--> <resultMap id="resultEmployeesByDeptId" type="Employee"> <id column="emp_id" property="empId"></id> <result column="emp_name" property="empName"></result> <result column="age" property="age"></result> <result column="gender" property="gender"></result> </resultMap> <select id="selectEmployeesByDeptId" resultMap="resultEmployeesByDeptId"> select * from t_emp where dept_id = #{id} </select>

DeptMapper.xml文件声明如下

<resultMap id="resultDeptAndEmp" type="Department"> <id column="dept_id" property="deptId"></id> <result column="dept_name" property="deptName"></result> <association property="employees" fetchType="lazy" select="com.hspedu.mapper.EmpMapper.selectEmployeesByDeptId" column="dept_id"></association> </resultMap> <select id="selectDeptAndEmpTwo" resultMap="resultDeptAndEmp"> select * from t_dept where dept_id = #{id} </select>

使用association标签,

select:调用EmpMapper接口的 selectEmployeesByDeptId(方法,即 根据得到的部门信息中的dept_id,在t_emp表中查询该部门的所有员工信息。

3)总结

 

编程笔记 » MyBatis的使用七(处理表与表之间的关系)

赞同 (24) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽