MyBatis

MyBatis简介

ORM(Object Relational Mapping)思想的提出:

数据库中数据是以表的形式存在的,而java中使用的数据都是对象型的。所以不得不要将表数据转换成对象数据。 这样就会产生大量的没有技术含量的纯 “体力” 型代码。

while(rs.next()) {
    Business business = new Business();
    business.setBusinessId(rs.getInt("businessId"));
    business.setPassword(rs.getString("password"));
    business.setBusinessName(rs.getString("businessName"));
    business.setBusinessAddress(rs.getString("businessAddress"));
    business.setBusinessExplain(rs.getString("businessExplain"));
    business.setStarPrice(rs.getDouble("starPrice"));
    business.setDeliveryPrice(rs.getDouble("deliveryPrice"));
    list.add(business);
}

上面代码就属于纯 “体力” 型代码。这些代码工作量大、单调枯燥、占用大量开发时间。为了解决这个 问题,出现了ORM思想。 ORM(对象-关系映射):完成对象数据到关系型数据映射的机制称为对象-关系映射。

MyBatis框架:

MyBatis就是一个ORM框架。当然,也是一个持久层框架。 MyBatis封装了JDBC, 将数据库中的表数据自动封装到对象中。这样就可以以面向对象的方式操作数 据了。它的出现,使得开发工作量变小了,可以将精力集中在业务逻辑的处理上。

MyBatis 是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis 消除了几乎所有的 JDBC代码和参数的手工设置以及结果集的检索。MyBatis 使用简单的 XML注解用于配置和原始映 射,将接口和 Java 的POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。 实际上,MyBatis最核心的功能,就是实现了输入映射输出映射

Mybatis架构简介

 

sql输出映射参数

sql输入映射参数

Mybatis配置

SqlMapConfig.xml/application.yml

HashMap

String,Integer基本数据类型

Java对象

HashMap

String,Integer基本数据类型

Java对象

mapper.xml/sql注解

配置运行环境:数据库连接池+数据库事务管理等

SqlSessionFactory

SqlSession

Executor

Mapped Statement

数据库

MyBatis的输入映射和输出映射

输入映射总结

当sql语句需要一个参数时:

  1. 接口方法参数为一个基本数据类型;parameterType配置一个基本数据类型; 当sql语句需要多个参数时:

  2. 接口方法参数为一个实体对象类型;parameterType配置一个实体对象类型;

  3. 接口方法参数为一个集合类型(List、Map);parameterType配置集合中元素的类型;

注意:当sql语句中需要判断一个基本数据类型的值是否为空时:

  1. 值的类型必须为包装类。

  2. 即使是只传一个基本数据类型,也要使用实体对象传值。 因为:如果在parameterType中设置 Integer类型,那么Mybatis会自动寻找get方法来获取对象属性值。因此会出现没有get方法异常。

输出映射总结

当sql语句中的字段名与实体对象中的属性名一致时,使用resultType:

  1. 返回一条记录时,resultType可以配置成对象类型。

  2. 返回多条记录时,resultType也要配置成对象类型(表示集合中存储的对象)。

  3. 返回一条记录,且只有一列时,resultType可以配置成简单数据类型。

注意:当sql语句中的字段名与实体对象中的属性名不一致时,使用resultMap:

  1. 在resultMap中,显式的书写sql字段名与实体对象属性名的映射

resultMap的使用

当sql语句中的字段名与实体对象中的字段名不一致时,可以使用resultMap来显式的进行映射。

<resultMap type="Student" id="StudentResult">
        <id property="id" column="id"/>
        <result property="classNo" column="class_no"/>
        <result property="collegeName" column="college_name"/>
        <result property="majorName" column="major_name"/>
        <result property="studentId" column="student_id"/>
        <result property="name" column="name"/>
        <result property="sex" column="sex"/>
        <result property="age" column="age"/>
        <result property="status" column="status"/>
        <result property="intro" column="intro"/>
        <result property="entranceDate" column="entrance_date"/>
        <result property="createBy" column="create_by"/>
        <result property="createTime" column="create_time"/>
        <result property="updateBy" column="update_by"/>
        <result property="updateTime" column="update_time"/>
    </resultMap>

注意:

  1. resultMap标签中的 id 属性:是此resultMap的唯一标识。

  2. resultMap标签中的 type 属性:是此resultMap 映射的实体对象(也就是model包的Student类)。

  3. 子标签id 和子标签 result 中的 property 属性,对应实体类中的属性,column 属性对应sql语句中的字段。

  4. resultMap标签中的子标签id,用来配置主键的映射;子标签 result 用来配置其它字段的映射。

MyBatis配置文件

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!-- 以上这行代码指定了xml版本和编码格式 -->
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- 以上这三行代码指定了mybatis dtd约束 -->
<configuration>
​
    <settings>
        <setting name="cacheEnabled"             value="true" />  <!-- 全局映射器启用缓存 -->
        <setting name="useGeneratedKeys"         value="true" />  <!-- 允许 JDBC 支持自动生成主键 -->
        <setting name="defaultExecutorType"      value="REUSE" /> <!-- 配置默认的执行器 -->
        <setting name="logImpl"                  value="SLF4J" /> <!-- 指定 MyBatis 所用日志的具体实现 -->
        <!-- <setting name="mapUnderscoreToCamelCase" value="true"/>  驼峰式命名 -->
    </settings>
​
</configuration>

mybatis-config.xml中还可以配置数据源(如jdbc驱动、数据库用户名,用户密码等),但是本工程把这些配置放在了application.yml里。

application.yml

datasource:
    # 数据库地址
    url: jdbc:mysql://119.3.199.81:3366/neuq_examples?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false
    # 连接数据库用户名
    username: example
    # 连接数据库密码
    password: neuq168168
    # 设置驱动
    driver-class-name: com.mysql.cj.jdbc.Driver
    # 连接池设置
    type: com.alibaba.druid.pool.DruidDataSource
    # 初始化时建立物理连接的个数
    initialSize: 10
    # 最大连接池数量
    maxActive: 50
    # 最小连接池数量
    minIdle: 10
# MyBatis配置
mybatis:
  # 搜索指定包别名
  typeesAliasPackage: cn.codnoy.springboot.examples.model
  # 配置mapper的扫描,找到所有的mapper.xml映射文件
  mapperLocations: classpath*:mapper/**/*Mapper.xml
  # 加载全局的配置文件
  configLocation: classpath:mybatis/mybatis-config.xml

封装持久层(DAO层)

MyBatis开发DAO层有两种方式:

  1. 原始dao方式

  2. mapper代理方式

由于本工程采取的是mapper代理方式,且原始dao方式有诸多弊端(如存在大量重复代码、调用sqlSession方法时,将statement的id硬编码了等),我们在这就不予讲解使用原始dao方式封装持久层。

Mapper代理

程序员只需要mapper接口mapper.xml映射文件(也可使用注解来配置映射语句),Mybatis可以自动生成mapper接口实现类代理对象。程序员编写mapper接口需要遵循一些开发规范。 mapper代理方式开发规范:

  1. 映射文件中的 namespace 必须是 mapper 接口的地址。

  2. 映射文件中 statement 的 id 必须与 mapper 接口中的方法名一致。

  3. 映射文件中 parameterType 必须与 mapper 接口中的方法参数类型一致。

  4. 映射文件中 resultType 必须与 mapper 接口中的返回值类型一致。(实际上,代理对象就是根据返 回值类型来判断是使用selectOne方法还是selectList方法)

mapper接口

package com.neusoft.mapper;
import java.util.List;
import com.neusoft.po.Emp;
public interface EmpMapper {
   public Emp getEmpById(int empno);
   public List<Emp> listEmpAll();
}

MyBatis XML映射文件

MyBatis XML映射文件一般在resources文件夹的子文件夹mapper下。

本项目里的xml映射文件过大,笔者就单独写了个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">
<mapper namespace="emp">
    <select id="getEmpById" parameterType="int"
resultType="com.neusoft.po.Emp">
        <!-- 参数类型为int,返回结果类型为Emp对象 -->
        select * from emp where empno = #{empno}
    </select>
</mapper>

常用数据库操作

多条件查询

<select id="listEmp" parameterType="Emp" resultType="Emp">
   select *
   from emp
   where job like concat('%',#{job},'%') and deptno=#{deptno}
   order by empno
</select>
Emp emp = new Emp();
emp.setJob("经");
emp.setDeptno(20);
List<Emp> list = mapper.listEmp(emp);
for(Emp e : list) {
   System.out.println(e);
}

注意:

  1. parameterType只有⼀个。所以,有多个参数时使⽤对象传值(这就是输⼊映射)。

  2. {} 中书写的是实体对象的属性名,所以要严格区分⼤⼩写。

转义字符查询

由于 <(⼩于号)是标签关键词,因此不能识别⼩于号等。所以MyBatis中设计了⼀些转义字符,来代替⼀些特殊字符:

Mybatis转义字符表


Mybatis语句代表符号含义
&lt;<小于
&gt;>大于
&amp;&
&apos;'单引号
&quot;"双引号
<select id="listEmpBySal" parameterType="double" resultType="Emp">
   select * from emp where sal &lt; #{sal} order by empno
</select>
List<Emp> list = mapper.listEmpBySal(2000.0);
for(Emp e : list) {
   System.out.println(e);
}

返回单值查询

<select id="listEmpCount" resultType="int">
   select count(*) from emp
</select>
int count = mapper.listEmpCount();
System.out.println(count);

注意:只有返回⼀⾏⼀列,resultType才能使⽤基本数据类型

插入(不获取主键)

<insert id="insertEmp1" parameterType="Emp">
   insert into emp(ename,job,hiredate,deptno)
   values(#{ename},#{job},#{hiredate},#{deptno})
</insert>
SqlSession sqlSession = Util.getSqlSessionFactory().openSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
Emp emp = new Emp();
emp.setEname("张三");
emp.setJob("职员");
emp.setHiredate("2020-09-04");
emp.setDeptno(10);
int result = mapper.insertEmp1(emp);
sqlSession.commit();                 //注意:要commit提交
System.out.println(result);

注意:增删改都会返回int值,表示影响的⾏数。但是,insert标签中不能书写resultType属性

插入(获取主键1)

<insert id="insertEmp2" parameterType="Emp">
   <selectKey keyProperty="empno" resultType="int" order="AFTER">
       select LAST_INSERT_ID()
   </selectKey>
   insert into emp(ename,job,hiredate,deptno)
   values(#{ename},#{job},#{hiredate},#{deptno})
</insert>
SqlSession sqlSession = Util.getSqlSessionFactory().openSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
Emp emp = new Emp();
emp.setEname("张三");
emp.setJob("职员");
emp.setHiredate("2020-09-04");
emp.setDeptno(10);
int result = mapper.insertEmp2(emp);
sqlSession.commit();
System.out.println(result);
System.out.println(emp.getEmpno());     //获取返回的主键

注意:

  1. selectKey标签中的 select LAST_INSERT_ID() 语句就能获取⽣成的主键

  2. selectKey标签中的keyProperty属性就是主键名,MyBatis会⾃动将获取的主键封装给此属性。

  3. order的值有两种:BEFORE、AFTER

  • BEFORE:先获取主键,然后执⾏insert; ⽐如 Oracle数据库。

  • AFTER:先执⾏insert,然后获取主键; ⽐如 MySql数据库。

插入(获取主键2)

<insert id="insertEmp3" parameterType="Emp" useGeneratedKeys="true"
keyProperty="empno">
   insert into emp(ename,job,hiredate,deptno)
   values(#{ename},#{job},#{hiredate},#{deptno})
</insert>
SqlSession sqlSession = Util.getSqlSessionFactory().openSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
Emp emp = new Emp();
emp.setEname("张三");
emp.setJob("职员");
emp.setHiredate("2020-09-04");
emp.setDeptno(10);
int result = mapper.insertEmp3(emp);
sqlSession.commit();
System.out.println(result);
System.out.println(emp.getEmpno());     //获取返回的主键

useGeneratedKeys设置为true后,mybatis会使⽤JDBC的getGeneratedkeys⽅法获取由数据库内部 ⾃动⽣成的主键,并将该值赋值给由keyProperty指定的属性;

注意:此种⽅式只适合于有⾃增⻓列的 数据库(mysql、sqlserver等)

修改

<update id="updateEmp" parameterType="Emp">
   update emp set job=#{job},sal=#{sal} where empno=#{empno}
</update>
Emp emp = new Emp();
emp.setEmpno(7934);
emp.setJob("经理");
emp.setSal(2000.0);
int result = mapper.updateEmp(emp);
sqlSession.commit();
System.out.println(result);

注意:增删改都会返回int值,表示影响的⾏数。但是,update等”增删改“标签中不能书写resultType属性

删除

<delete id="deleteEmp" parameterType="int">
   delete from emp where empno=#{empno}
</delete>
int result = mapper.deleteEmp(7939);
sqlSession.commit();
System.out.println(result);

使用注解实现MyBatis映射

MyBatis也⽀持使⽤注解来配置映射语句。 主要有四种注解来实现增删改查:@Select、@Insert、 @Update、@Delete

package com.neusoft.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Select;
import com.neusoft.po.Emp;
public interface EmpMapper {
   @Select("select * from emp where empno = #{empno}")
   public Emp getEmpById(int empno);
   @Select("select * from emp order by empno")
   public List<Emp> listEmpAll();
}

注意:

  1. 在映射⽂件中使⽤的所有的CRUD操作,都可以使⽤注解的形式完成。

  2. 当使⽤基于注解的映射器接⼝时,就不再需要映射配置⽂件了。

  3. 在实际开发中,可以单独使⽤映射⽂件,也可以单独使⽤注解,也可以混合使⽤。

动态sql

动态sql主要⽤于解决查询条件不确定的情况。

也就是说:在实际开发中,经常需要根据⽤户是否输⼊了 某个值,来确定是否需要这个条件。

MyBatis中⽤于动态sql的元素主要有:if、where、trim、set、 foreach、choose等

if+where标签

<select id="listEmp" parameterType="Emp" resultType="Emp">
   select * from emp
   <where>
       <if test="job!=null and job!=''">
           and job like concat('%',#{job},'%')
       </if>
       <if test="deptno!=null and deptno!=''">
           and deptno = #{deptno}
       </if>
   </where>
   order by empno
</select>
Emp emp = new Emp();
//emp.setJob("经");
//emp.setDeptno(10);       //注意:deptno属性必须为Integer类型,方便判断非空与否
List<Emp> list = mapper.listEmp(emp);
for(Emp e : list) {
   System.out.println(e);
}

if+where会实现以下功能:

  1. ⾃动添加where

  2. 不需要考虑where后是否加and,mybatis会⾃动处理

  3. 不需要考虑是否加空格,mybatis会⾃动处理

  4. 没有 else 标签,也没有 else if 标签。

  • 注意: job!= '' 此处只可以判断是否为空,不能判断是否为某个值或比较大小。也就是说:job!= '经理' 是不好使 的。

choose标签

<select id="listEmp" parameterType="Emp" resultType="Emp">
   select * from emp
   <where>
       <choose>
           <when test="job!=null and job!=''">
               and job like concat('%',#{job},'%')
           </when>
           <when test="deptno!=null and deptno!=''">
               and deptno = #{deptno}
           </when>
           <otherwise></otherwise>
       </choose>
   </where>
   order by empno
</select>
Emp emp = new Emp();
emp.setJob("职员");
emp.setDeptno(10);
List<Emp> list = mapper.listEmp(emp);
for(Emp e : list) {
   System.out.println(e);
}

choose会实现如下功能:

  1. 多个 when 标签中,只能执⾏⼀个。也就是说:当⼀个 when 条件满⾜并执⾏后,其它的 when 将 不再执⾏。

  2. 当所有 when 都不满⾜条件时,执⾏ otherwise 标签。

  • if 与 choose 的区别:if 相当于java中的if语句; choose相当于java中的switch语句。

trim标签

trim标签可以在⾃⼰包含的内容中加上某些前缀或后缀,与之对应的属性是:prefix、suffix。

还可以把 包含内容的开始内容覆盖,即忽略。也可以把结束的某些内容覆盖,对应的属性是:prefixOverrides、 suffixOverrides

<insert id="insertEmp1" parameterType="Emp">
   insert into emp
   <trim prefix="(" suffix=")" suffixOverrides=",">
       ename,deptno,
       <if test="job!=null and job!=''">
           job,
       </if>
       <if test="hiredate!=null and hiredate!=''">
           hiredate,
       </if>
   </trim>
   <trim prefix="values(" suffix=")" suffixOverrides=",">
       #{ename},#{deptno},
       <if test="job!=null and job!=''">
           #{job},
       </if>
       <if test="hiredate!=null and hiredate!=''">
           #{hiredate},
       </if>
   </trim>
</insert>
SqlSession sqlSession = Util.getSqlSessionFactory().openSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
Emp emp = new Emp();
emp.setEname("张三");
emp.setJob("职员");
//emp.setHiredate("2020-09-04");
emp.setDeptno(10);
int result = mapper.insertEmp1(emp);
sqlSession.commit();
System.out.println(result);

注意:

  1. prefix与suffix可以在sql语句中拼接出⼀对⼩括号。

  2. suffixOberrides可以将最后⼀个逗号去掉。(自动筛选效果)

set标签

set标签主要⽤于更新操作时使⽤

<update id="updateEmp" parameterType="Emp">
   update emp
   <set>
       <if test="job!=null and job!=''">
           job=#{job},
       </if>
       <if test="sal!=null and sal!=''">
           sal=#{sal},
       </if>
   </set>
   where empno=#{empno}
</update>
Emp emp = new Emp();
emp.setEmpno(7943);
//emp.setJob("职员1");
emp.setSal(3000.0);
int result = mapper.updateEmp(emp);
sqlSession.commit();
System.out.println(result);

注意:

  1. set可以在sql语句中⾃动加上set关键词。

  2. 可以⾃动将最后的逗号去掉。

  3. 上⾯写法中,必须要保证有⼀个if成⽴

foreach标签

foreach标签可以在sql中迭代⼀个集合或数组,主要⽤于拼接in条件。下⾯是⼀个批量删除示例:

<delete id="deleteEmp" parameterType="int">
   delete from emp where empno in
   <foreach collection="array" item="empno" open="(" close=")" separator=",">
       #{empno}
   </foreach>
</delete>
int[] arr = {7941,7942,7943};
int result = mapper.deleteEmp(arr);   //注意:此接⼝参数应为int数组
sqlSession.commit();
System.out.println(result);

foreach标签的属性:

  1. collection:需要遍历的类型,值有:list、array

  2. item:表示遍历出来的对象

  3. open:表示语句的开始部分

  4. close:表示语句的结束部分

  5. separator:表示每次迭代之间以什么符号为间隔

  6. index:每次迭代的位置索引,就是循环变量

MyBatis关联查询

我们知道,在数据库中,表关系有:一对一、多对一、一对多、多对多。 那么在实际开发中,很多查询 都是通过多个表之间的关系,进行多表连接查询的。 那么,在多表连接查询中,MyBatis如何实现输出映射呢,这就要使用MyBatis的关联查询。 MyBatis关联查询有两种:

  1. 多表连接形式(嵌套结果)

  2. 单独查询形式(嵌套查询)

在讲解关联查询之前,我们先来简单了解下SQL JOIN操作符。

SQL JOIN

SQL join 用于根据两个或多个表中的列之间的关系,从这些表中查询数据。

SQL JOIN有

  • JOIN:: 如果表中有至少一个匹配,则返回行

  • INNNER JOIN:在表中存在至少一个匹配时,INNER JOIN 关键字返回行

  • LEFT JOIN:即使右表中没有匹配,也从左表返回所有的行

  • RIGHT JOIN:即使左表中没有匹配,也从右表返回所有的行

  • FULL JOIN(MYSQL不支持):只要其中一个表中存在匹配,就返回行

实例:

“Person”表:

Id_PLastNameFirstNameAddressCity
1AdamsJohnOxford StreetLondon
2BushGeorgeFifth AvenueNew York
3CarterThomasChangan StreetBeijing

"Orders" 表:

Id_OOrderNoId_P
1778953
2446783
3224561
4245621
53476465

请注意,"Id_O" 列是 Orders 表中的的主键,同时,"Orders" 表中的 "Id_P" 列用于引用 "Persons" 表中的人,而无需使用他们的确切姓名。

请留意,"Id_P" 列把上面的两个表联系了起来。

我们应该怎么样得知谁订购了产品,并且他们订购了什么产品呢?

如果我们希望列出所有人的定购,可以使用下面的 SELECT 语句:

SELECT Persons.LastName, Persons.FirstName, Orders.OrderNo
FROM Persons
INNER JOIN Orders
ON Persons.Id_P = Orders.Id_P
ORDER BY Persons.LastName

多表连接形式

多对一关联查询

  1. 修改实体类

    Dept是one的一方,Emp是many的一方; 在many的一方添加one的一方的对象,这就配置了实体类 之间的多对一关联。

  2. 使用resultMap映射关联

    <resultMap type="Emp" id="empResultMap">
        <id property="empno" column="empno"/>
        <result property="ename" column="ename"/>
        <result property="job" column="job"/>
        <result property="hiredate" column="hiredate"/>
        <result property="sal" column="sal"/>
        <result property="deptno" column="deptno"/>
        <association property="dept" javaType="Dept">
            <id property="deptno" column="ddeptno"/>
            <result property="dname" column="ddname"/>
            <result property="loc" column="dloc"/>
        </association>
      </resultMap>
      <select id="getEmpById" parameterType="int" resultMap="empResultMap">
    	  select e.*,
        		 d.deptno ddeptno,
    			 d.dname ddname,
    			 d.loc dloc
    	  from emp e left join dept d
    		   on e.deptno=d.deptno
    	  where e.empno = #{empno}
      </select>
      <select id="listEmpAll" resultMap="empResultMap">
    	  select e.*,
    			 d.deptno ddeptno,
    			 d.dname ddname,
    			 d.loc dloc
    	  from emp e left join dept d
    		   on e.deptno=d.deptno
    </select>

    association表示配置单个对象的关联映射 :

    1. association标签中的property:many的一方的实体类中,添加的属性名。

    2. association标签中的javaType:many的一方的实体类中,添加的属性类型。

    3. id标签和result标签中的property:one的一方的实体类中的属性名。

    4. id标签和result标签中的column:one的一方的,查询出来的字段名。

一对多关联查询

  1. 修改实体类

    Dept是one的一方,Emp是many的一方; 在one的一方添加many的一方的集合,这就配置了实体类 之间的一对多关联。

  2. 使用resultMap映射关联

    <resultMap type="Dept" id="deptResultMap">
        <id property="deptno" column="deptno"/>
        <result property="dname" column="dname"/>
        <result property="loc" column="loc"/>
        <collection property="empList" ofType="Emp">
            <id property="empno" column="eempno"/>
            <result property="ename" column="eename"/>
            <result property="job" column="ejob"/>
            <result property="hiredate" column="ehiredate"/>
            <result property="sal" column="esal"/>
            <result property="deptno" column="edeptno"/>
        </collection>
    </resultMap>
    <select id="getDeptById" parameterType="int" resultMap="deptResultMap">
    	select d.*,
    		   e.empno eempno,
    	       e.ename eename,
    		   e.job ejob,
    		   e.hiredate ehiredate,
    		   e.sal esal,
    		   e.deptno edeptno
    	from dept d left join emp e
    	     on d.deptno=e.deptno
    	where d.deptno = #{deptno}
    </select>
    <select id="listDeptAll" resultMap="deptResultMap">
    	select d.*,
    		   e.empno eempno,
    	 	   e.ename eename,
    		   e.job ejob,
    		   e.hiredate ehiredate,
    		   e.sal esal,
    		   e.deptno edeptno
    	from dept d left join emp e
    		 on d.deptno=e.deptno
    </select>

    collection表示配置多个对象的集合的关联映射 :

    1. collection标签中的property:one的一方的实体类中,添加的集合属性名。

    2. collection标签中的ofType:one的一方的实体类中,添加的集合中的元素类型。

    3. id标签和result标签中的property:many的一方的实体类中的属性名。

    4. id标签和result标签中的column: many的一方的,查询出来的字段名。

单独查询形式

多对一关联查询

  1. 先在one的一方添加关联查询

    <select id="getDeptByIdLazy" parameterType="int" resultType="Dept">
    	select * from dept where deptno = #{deptno}
    </select>

    注意:此查询可以不在接口中书写响应的方法

  2. many的一方添加查询

    <resultMap type="Emp" id="empResultMap">
    	<id property="empno" column="empno"/>
    	<result property="ename" column="ename"/>
    	<result property="job" column="job"/>
    	<result property="hiredate" column="hiredate"/>
    	<result property="sal" column="sal"/>
    	<result property="deptno" column="deptno"/>
    	<association property="dept" javaType="Dept"
    		   select="com.neusoft.mapper.DeptMapper.getDeptByIdLazy"
    column="deptno" />
    </resultMap>
    <select id="getEmpById" parameterType="int" resultMap="empResultMap">
    	select * from emp where empno = #{empno}
    </select>

一对多关联查询

  1. 先在many的一方添加关联查询

    <select id="getEmpByIdLazy" parameterType="int" resultType="Emp">
    	select * from emp where deptno = #{deptno}
    </select>

    注意:此查询可以不在接口中书写响应的方法

  2. one的一方添加查询

    <resultMap type="Dept" id="deptResultMap">
    	<id property="deptno" column="deptno"/>
    	<result property="dname" column="dname"/>
    	<result property="loc" column="loc"/>
    	<collection property="empList" ofType="Emp"
    		   select="com.neusoft.mapper.EmpMapper.getEmpByIdLazy"
    column="deptno"/>
    </resultMap>
    <select id="getDeptById" parameterType="int" resultMap="deptResultMap">
    	select * from dept where deptno = #{deptno}
    </select>

关联映射总结

使用resultMap实现关联映射时:

  1. 使用association标签完成多对一或一对一映射。 a. association标签:将关联查询信息映射到一个po对象中。 b. association标签中的javaType属性:表示该po对象的类型。 c. association标签中的select属性:表示应用哪一个关联查询。 d. association标签中的column属性:表示应用关联查询的条件。

  2. 使用collection标签完成一对多,多对多映射。 a. collection标签:将关联查询信息映射到一个list集合中。 b. collection标签的ofType属性:表示该集合中的元素对象的类型。 c. collection标签中的select属性:表示应用哪一个关联查询。 d. collection标签中的column属性:表示应用关联查询的条件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值