Mybatis映射-8

  

一.一对多关联

1 一对多广泛存在于实际应用中,部门和员工,县区和街道

2 一对多的分类,从方向来分可以分为

  • 单向一对多:只在一的一方配置多方的关联

  • 单向多对一:只在多的一方配置一方的关联

  • 双向一对多:在两方都配置

3.mybaits中配置一对多

在mybatis配置一对多的方式两种

3.1 嵌套映射的配置方式

案例:配置单向一对多

1)数据库表结构

CREATE TABLE `dept` (

`DEPTNO` INT(2) NOT NULL,

`DNAME` VARCHAR(14) DEFAULT NULL,

`LOC` VARCHAR(13) DEFAULT NULL,

PRIMARY KEY (`DEPTNO`)

) ENGINE=INNODB DEFAULT CHARSET=utf8;

INSERT INTO `dept` VALUES ('10', 'ACCOUNTING', 'NEW YORK');

INSERT INTO `dept` VALUES ('20', 'RESEARCH', 'DALLAS');

INSERT INTO `dept` VALUES ('30', 'SALES', 'CHICAGO');

INSERT INTO `dept` VALUES ('40', 'OPERATIONS', 'BOSTON');

DROP TABLE IF EXISTS `emp`;

CREATE TABLE `emp` (

`EMPNO` INT(4) NOT NULL,

`ENAME` VARCHAR(10),

`JOB` VARCHAR(9),

`MGR` INT(4),

`HIREDATE` DATE,

`SAL` INT(7),

`COMM` INT(7),

`DEPTNO` INT(2),

PRIMARY KEY (`EMPNO`),

KEY `FK_DEPTNO` (`DEPTNO`),

CONSTRAINT `FK_DEPTNO` FOREIGN KEY (`DEPTNO`) REFERENCES `dept` (`DEPTNO`)

) ENGINE=INNODB DEFAULT CHARSET=utf8;

INSERT INTO `emp` VALUES ('7369', 'SMITH', 'CLERK', '7902', '1980-12-17', '800', NULL, '20');

INSERT INTO `emp` VALUES ('7499', 'ALLEN', 'SALESMAN', '7698', '1981-02-20', '1600', '300', '30');

INSERT INTO `emp` VALUES ('7521', 'WARD', 'SALESMAN', '7698', '1981-02-22', '1250', '500', '30');

INSERT INTO `emp` VALUES ('7566', 'JONES', 'MANAGER', '7839', '1981-04-02', '2975', NULL, '20');

INSERT INTO `emp` VALUES ('7654', 'MARTIN', 'SALESMAN', '7698', '1981-09-28', '1250', '1400', '30');

INSERT INTO `emp` VALUES ('7698', 'BLAKE', 'MANAGER', '7839', '1981-05-01', '2850', NULL, '30');

INSERT INTO `emp` VALUES ('7782', 'CLARK', 'MANAGER', '7839', '1981-06-09', '2450', NULL, '10');

INSERT INTO `emp` VALUES ('7788', 'SCOTT', 'ANALYST', '7566', '1987-04-19', '3000', NULL, '20');

INSERT INTO `emp` VALUES ('7839', 'KING', 'PRESIDENT', NULL, '1981-11-17', '5000', NULL, '10');

INSERT INTO `emp` VALUES ('7844', 'TURNER', 'SALESMAN','7698', '1981-09-08', '1500', '0', '30');

INSERT INTO `emp` VALUES ('7876', 'ADAMS', 'CLERK', '7788', '1987-05-23', '1100', NULL, '20');

INSERT INTO `emp` VALUES ('7900', 'JAMES', 'CLERK', '7698', '1981-12-03', '950', NULL, '30');

INSERT INTO `emp` VALUES ('7902', 'FORD', 'ANALYST', '7566', '1981-12-03', '3000', NULL, '20');

INSERT INTO `emp` VALUES ('7934', 'MILLER', 'CLERK', '7782', '1982-01-23', '1300', NULL, '10');

2)创建实体对象

@Data

public class Dept {

   private Byte deptno;

   private String dname;

   private String loc;

   private List<Emp> emps;

}

@Data

public class Emp {

   private Short empno;

   private String ename;

   private String job;

   private Short mgr;

   private Date hiredate;

   private Float sal;

   private Float comm;

}

3)编写接口

public interface DeptMapper {

   public Dept selectDeptByNo(Byte deptno);

}

4)映射文件

<?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.woniuxy.dao.DeptMapper">

   <resultMap id="detpMap" type="dept">

       <id property="deptno" column="deptno"></id>

       <result property="dname" column="dname"></result>

       <result property="loc" column="loc"></result>

       <!--

         collection:在一方配置多方关联的节点,常用的属性如下

            |- property: 关联对象的属性名

            |-ofType:表示的是集合中的元素的类型,可以是类全名,也可以是别名

       -->

       <collection property="emps" ofType="Emp">

           <id property="empno" column="empno"></id>

           <result property="ename" column="ename"></result>

           <result property="job" column="job"></result>

           <result property="mgr" column="mgr"></result>

           <result property="hiredate" column="hiredate"></result>

           <result property="sal" column="sal"></result>

           <result property="comm" column="comm"></result>

       </collection>

   </resultMap>

   <select id="selectDeptByNo" parameterType="byte" resultMap="detpMap">

       SELECT *

       FROM dept d INNER JOIN emp e ON d.deptno=e.deptno

       WHERE d.deptno=#{deptno}

   </select>

</mapper>

5)编写测试

package com.woniuxy;

import static org.junit.Assert.assertTrue;

import com.woniuxy.dao.DeptMapper;

import com.woniuxy.pojo.Dept;

import com.woniuxy.pojo.Emp;

import com.woniuxy.util.MyBatisUtil;

import org.apache.ibatis.session.SqlSession;

import org.apache.log4j.Logger;

import org.junit.Test;

import java.util.List;

/**

* Unit test for simple App.

*/

public class AppTest

{

   private Logger logger= Logger.getLogger(AppTest.class);

   @Test

   public void test1()

   {

       SqlSession sqlSession= MyBatisUtil.crateSqlSession();

       DeptMapper deptMapper=sqlSession.getMapper(DeptMapper.class);

       Dept dept=deptMapper.selectDeptByNo((byte)10);

       logger.info("部门信息:"+dept.getDeptno()+" "+dept.getDname()+" "+dept.getLoc());

       List<Emp> emps=dept.getEmps();

       if(emps!=null&& !emps.isEmpty()){

           logger.info("该部门有"+emps.size()+"个员工");

           logger.info("员工信息如下:");

           for(Emp emp:emps){

               logger.info(emp.getEmpno()+" "+emp.getEname()

                       +" "+emp.getJob()+" "+emp.getMgr()

                       +" "+emp.getHiredate()

                       +" "+emp.getSal()+" "+emp.getComm());

           }

       }

       MyBatisUtil.closeSqlSession(sqlSession);

   }

}

 

3.2分步查询的配置一对多的方式【重点掌握】

1)编写实体

@Data

public class Emp {

   private Short empno;

   private String ename;

   private String job;

   private Short mgr;

   private Date hiredate;

   private Float sal;

   private Float comm;

}

@Data

public class Dept {

   private Byte deptno;

   private String dname;

   private String loc;

   private List<Emp> emps;

}

2)编写接口

public interface DeptMapper {

   /**

    * 通过部门编号查询部门对象

    */

   public Dept selectDeptByDeptno(Byte deptno);

}

public interface EmpMapper {

   /**

    * 通过部门编号查询该部门中所有员工信息

    */

   public List<Emp> selectEmpsByDeptno(Byte deptno);

}

3)编写映射文件

<?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.woniuxy.dao.DeptMapper">

   <resultMap id="deptMap" type="dept">

       <id property="deptno" column="deptno"></id>

       <result property="dname" column="dname"></result>

       <result property="loc" column="loc"></result>

       <!--

          collection:完成一对多的配置,用于集合设置,常用的属性

              |- property:关联集合对象的属性名

              |-select:完成分步查询的SQL语句

              |-column:传递的参数,是dept表的主键

       -->

       <collection property="emps"

                   select="com.woniuxy.dao.EmpMapper.selectEmpsByDeptno"

                   column="deptno">

       </collection>

   </resultMap>

   <select id="selectDeptByDeptno" parameterType="Byte" resultMap="deptMap">

       SELECT DEPTNO,DNAME,LOC FROM DEPT WHERE DEPTNO=#{deptno}

   </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.woniuxy.dao.EmpMapper">

   <select id="selectEmpsByDeptno" parameterType="Byte" resultType="emp">

       SELECT * FROM EMP WHERE DEPTNO=#{deptno}

   </select>

</mapper>

4)编写测试

package com.woniuxy;

import static org.junit.Assert.assertTrue;

import com.woniuxy.dao.DeptMapper;

import com.woniuxy.pojo.Dept;

import com.woniuxy.pojo.Emp;

import com.woniuxy.util.MyBatisUtil;

import org.apache.ibatis.session.SqlSession;

import org.apache.log4j.Logger;

import org.junit.Test;

import java.util.List;

public class AppTest

{

   private Logger logger=Logger.getLogger(AppTest.class);

   @Test

   public void test1()

   {

       SqlSession sqlSession= MyBatisUtil.crateSqlSession();

       DeptMapper deptMapper=sqlSession.getMapper(DeptMapper.class);

       Dept dept=deptMapper.selectDeptByDeptno((byte)10);

       logger.info("部门信息:"+dept.getDeptno()+" "+dept.getDname()+" "+dept.getLoc());

       List<Emp> emps=dept.getEmps();

       if(emps!=null&& !emps.isEmpty()){

           logger.info("该部门有"+emps.size()+"个员工");

           logger.info("员工信息如下:");

           for(Emp emp:emps){

               logger.info(emp.getEmpno()+" "+emp.getEname()

                       +" "+emp.getJob()+" "+emp.getMgr()

                       +" "+emp.getHiredate()

                       +" "+emp.getSal()+" "+emp.getComm());

           }

       }

       MyBatisUtil.closeSqlSession(sqlSession);

   }

}

20200703_170245_507.png

通过控制台信息的输出会发现,此时属于立即加载

在mybatis-config.xml文件中配置延迟加载

<setting name="lazyLoadingEnabled" value="true"></setting>

<setting name="aggressiveLazyLoading" value="false"></setting>

20200703_171206_534.png

当然也可以在collection节点中通过fetchType进行设置

为了演示fetchType是否能做延迟加载,在DeptMapper.xml文件中设置

20200703_171224_944.png

此时控制台输出告诉我们,我们现在是立即加载,所以可以证明在SQL映射文件中通过fetchType设置是否要延迟加载优先级要高于mybatis配置文件中通过setting运行时的设置。

20200703_171237_153.png

 

 

作业:完成如下操作

20200703_175955_118.png

设计数据库表,使用mybatis完成一对多的关系

客户-----1:n------>联系人

客户-----1:n--------->交往记录

客户-----1:n---------->订单

订单-----1:n----------->订单明细

posted @ 2020-10-08 17:40  Mistory  阅读(78)  评论(0)    收藏  举报