MyBatisSSM框架开发web项目系列(三) MyBatis之resultMap及关联映射

  前言

  在上篇MyBatis基础篇遇我们独立使用MyBatis构建了一个大概的数据库访问程序,可以实现单表的骨干增删改查等操作,通过该实例我们可以开始摸底MyBatis操作数据库需要之有组成部分(配置文件、实体类、SQL映射文件、Mapper接口等等)和关键对象(SqlSession、Mapper实例等等)。有矣一体化认知后,我们就是可更深入学习MyBatis的运,resultMap本文主要围绕resultMap展开。

  resultMap作为MyBatis的Sql映射文件被重要性的素之一,主要用来实现复杂的结果映射,其子元素结构如下:

MyBatis 1

  constructor

  constructor是构造器的意,对反射出基本了解的还应该不见面生。借这我们先行想起一下面前定义的一个简单resulMap映射内容

<resultMap type="person" id="personResultMap" >
    <id column="id" property="id" />
    <result column="name" property="name" />
    <result column="gender" property="gender" />
</resultMap>

  上面是一个突出的在resultMap中定义数据表和实体类的照耀关系,type这里用的号指向Person类,id为该映射的唯一标识,用于在背后我们的概念语句被援,内部的id和result分别针对许主键和一般字段定义,column指数据表中配段名,property指实体类中属性名。在前的演示中,通过是一个照关系,我们查询出来的结果就转会为了一个Person类对象。

  这个Person类对象无须由于我们创建出来,而是由mybatis调用了Person类的默认无参构造函数创建对象,再调用set方法呢目标赋值,这样才回去了俺们怀念如果的结果。下面结合之前的以身作则,做片反以便观察。

package com.mmm.pojo;
/**
 * Person实体类
 * */
public class Person {

    private String id;

    private String name;

    private String gender;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
        System.out.println("为主键属性id赋值");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        System.out.println("为属性name赋值");
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
        System.out.println("为属性gender赋值");
    }

    public Person() {
        System.out.println("调用无参构造创建对象");
    }
}

<select id="selectById"resultMap="personResultMap">
    select * from `person` where id = #{id}
</select>

  调用该找方法后会见相控制高出口如下信:

MyBatis 2

  说明确实是mybatis调用了这些方式帮助我们创建了对象,基于构造器。说打构造器,在我们定义的pojo实体类中,简单的私家属性加上set/get方法声明即完成,在java类中,会默认提供一个无参的构造方法,例如这里的Person类

public Person(){}

  我们下语句 Person p = new
Person();这里虽调用的拖欠管参构造。方法还可以重载,构造方法也无例外。可大重点的少数,我们于重载构造方法后,原本默认提供的管参构造就无法利用了,需要出示声明,这点下会被出示例。resultMap中constructor就是因重载的带参构造方法创建对象,如下:

<resultMap type="person" id="personResultMap" >
    <constructor>
        <idArg column="id" javaType="string" />
        <arg column="name" javaType="string" />
        <arg column="gender" javaType="string" />
    </constructor>
</resultMap>

  于实业类吃增长重载的带参构造方法

public Person(String id, String name, String gender) {
    this.id = id;
    this.name = name;
    this.gender = gender;
        System.out.println("直接调用带参构造函数创建对象");
}

  再次调用查找方法后会见见到控制高出口如下信:

MyBatis 3

  这样一来,使用constructor同样以到了数。

  这个时候如果我们管实体类中之默认无参构造方法的显得声明删除,即单独来一个带参的构造方法,这样咱们又把Sql映射文件中<resultMap>内容还原成文中一样开始定义之卓著<id><result>等,再调用方法,为了还显著,在地方栏中经controller层层调用到该措施,报错乍一扣押,一百般失误好,其实标题末尾一句子话虽出来了

  MyBatis 4

  不在拖欠办法,该法指的就是Person实体类吃的无参构造方法,在事先我们从没显示声明没有问题,那是以在接近吃设没有任何的构造方法声明,会默认提供一个无参构造;但是咱运用construtor的时光以实体类吃重载了一个带参的构造方法,使得本来默认的甭管参构造无法使了,这里要还要待运用,可以以实业类吃显示声明。

   id、result

  前面的单表典型基本投就是出于这半只元素做,所以应该比好理解。id和result都用来将表明中字段和实体类中属性建立起映射关系,区别是id是用于主键字段的照,result用于一般字段映射。两个元素中都发出5单特性供定义,分别是column、property、javaType、jdbcType、typeHandler。

  column:这里用于单表查询的语可以概括的知道吧数据表中字段,前面为是相近处理,但是实际上并无是这般简单,例如我们以描写SQL语句时经常会面以及号,别名的利虽无复述了,特别是进展多表查询时,这里我们在SQL映射文件的<select>语句子被呢可行使别名,这个别名与这里的column就本着诺高达了,不在意这点的讲话或来问题,后面介绍涉查询会生出示范。

  property:实体类中定义的和表字段对应的性质

  javaType:类型这里可以采用人名,也堪运用别名,例如地方的string就是一个号。我们当概念基本的实业类映射时,mybatis一般可自动确定项目。

  jdbcType:这里是指对数据表字段方的jdbc类型,mybatis中支持下的 JDBC 类型。

  MyBatis 5

  typeHandler:在运用数据库创建表,定义字段名,选择字段类型时,例如MySql中字符串类型varchar,然后我们用mybatis映射到实体类吃成为Java字符串类型String,这个转换过程是怎落实的?其中mybatis就已经预定义了有些门类处理器,也尽管是此typeHandler,我们吧可以根据需要由定义有色处理器。

  association(对一)

  association意思为沟通、关联,针对单个(一个)对象,典型的一定、多对平关系映射关系还得通过该因素实现,下面是基本概念内容。

<association property="关联的对象在本对象实体类中的属性名" column="关联表的主键在本表中的字段名" javaType="关联对象的实体类类型(可用别名)">
    <id column="ID" property="id" />
    <result column="数据表字段名" property="实体类属性名" />
  <result column="数据表字段名" property="实体类属性名" />
  ...
</association>

  通过地方的关系定义,然后以<select>元素中定义多表关联查询语句即可实现关系查询功能。这个<association>内部的<id><result>等因素,我们不自然要这么定义,也足以经额外定义一个resultMap填入这些要素,然后<association>有一个resultMap属性,值就填额外之reslutMap的id,这样吗可以实现关系映射。除此之外,也得以经一个提到的嵌套查询语句实现,即额外定义一个针对性关联表的<select>元素,然后<association>有一个select属性,值就是填<select>的id,这样同样能够落实。

  collection(对多)

  collection意为汇,这里要用以关联多只目标的炫耀关系定义,例如典型的同等对多,下面是着力概念内容。

<collection property="关联的对象在本对象实体类中的属性名" column="本表的主键在关联表中的字段名" ofType="关联集合中对象的实体类类型(可用别名)">
    <id column="ID" property="id" />
    <result column="数据表字段名" property="实体类属性名" />
    <result column="数据表字段名" property="实体类属性名" />
  ...
</collection>

   类似上面的association,也足以额外定义<select>元素,然后引入,从而实现关系查询。

  关联映射下得比多,关联属性为针锋相对复杂一些,光凭文字和一部分描述良麻烦快速解,下面坐一个一对多暨多对平做的以身作则来圆应用相同涂鸦。

  关联映射实例(一对多/多针对平)

  背景关系

  MyBatis 6

  这里因为部门作查询的实业对象,从图被不难理解,部门及企业是差不多对相同干,部门和员工是同对多关系,我们询问一个部门对象时,要将这单位所属的合作社消息查阅下,还要将机关下的持有员工信息查阅下。

  准备工作

  这里对象分公司、部门、员工一起三类,所以率先准备三张数据表,结构如下

 MyBatis 7MyBatis 8

MyBatis 9

MyBatis 10

 这里要掌握一些,基于主键关联,不管是同一对几近,还是多对平,在“多“”的一律着表中,都出一个和“一”的一方表主键对应之字段,例如这里的单位表明中COMPANY_ID和员工表中的DEPT_ID,用来涉及对应表

  新建maven工程,这里不待建web项目,普通的java项目即实行。pom依赖可以参照SSM框架开发web项目系列(一)
环境搭建篇。整体结构如下所示

  MyBatis 11

  然后新建三只目标实体类,如下所示

package com.mmm.pojo;
//公司
public class Company {
    private Integer id;              //主键
    private String companyName;     //公司名称

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getCompanyName() {
        return companyName;
    }
    public void setCompanyName(String companyName) {
        this.companyName = companyName;
    }
    @Override
    public String toString() {
        return "Company [id=" + id + ", companyName=" + companyName + "]";
    }
}

package com.mmm.pojo;

import java.util.List;
//部门
public class Dept {
    private Integer id;             //主键
    private String deptName;    //部门名称
    private Company company;    //部门所属公司---------多对一
    private List<Emp> empList;    //部门下面员工---------一对多

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getDeptName() {
        return deptName;
    }
    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }
    public Company getCompany() {
        return company;
    }
    public void setCompany(Company company) {
        this.company = company;
    }
    public List<Emp> getEmpList() {
        return empList;
    }
    public void setEmpList(List<Emp> empList) {
        this.empList = empList;
    }
    @Override
    public String toString() {
        return "Dept [id=" + id + ", deptName=" + deptName + ", company=" + company + ", empList=" + empList + "]";
    }

}

package com.mmm.pojo;
//员工实体类
public class Emp {
    private Integer id;            //主鍵
    private String name;        //员工姓名
    private String gender;        //员工性别

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    @Override
    public String toString() {
        return "Emp [id=" + id + ", name=" + name + ", gender=" + gender + "]";
    }
}

  配置文件(mybatis-config.xml)  

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 这里可以定义类的别名,在mapper.xml文件中应用会方便很多 -->
    <typeAliases>
        <typeAlias alias="emp" type="com.mmm.pojo.Emp" />
        <typeAlias alias="dept" type="com.mmm.pojo.Dept" />
        <typeAlias alias="company" type="com.mmm.pojo.Company" />
    </typeAliases>
    <!-- 环境配置 -->
    <environments default="envir">
        <environment id="envir">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/ssm?characterEncoding=utf-8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/mmm/mapper/deptMapper.xml"/>
    </mappers>
</configuration>

  mapper接口及针对承诺sql映射文件

package com.mmm.mapper;
import com.mmm.pojo.Dept;
public interface DeptMapper {
    public Dept selectById(Integer id);
}

<?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.mmm.mapper.DeptMapper">
    <resultMap type="dept" id="deptResultMap">
        <!-- 下面的column就是前面说的要注意的,如果简单的认为是字段名会出问题 -->
        <id column="d_id" property="id" />
        <result column="d_name" property="deptName" />
        <!-- 一个公司下面多个部门,部门与公司,多对一关系 -->
        <association property="company" column="COMPANY_ID" javaType="company" resultMap="companyResultMap">
            <!-- <id column="ID" property="id" />
            <result column="COMPANY_NAME" property="companyName" /> -->
        </association>
        <!-- 一个部门下有多个员工,部门与员工,一对多关系 -->
        <collection property="empList" column="DEPT_ID" ofType="emp">
            <id column="ID" property="id" />
            <result column="EMP_NAME" property="name" />
            <result column="EMP_GENDER" property="gender" />
        </collection>
    </resultMap>

    <!-- 也可以通过类似下面的定义然后引入到association中,association的resultMap属性值对应下面resultMap的id -->
    <!-- <resultMap type="company" id="companyResultMap">
        <id column="ID" property="id" />
        <result column="COMPANY_NAME" property="companyName" />
    </resultMap> -->

    <!-- 根据主键id查找记录 -->
    <select id="selectById" resultMap="deptResultMap">
        select e.*,d.ID AS d_id,d.DEPT_NAME AS d_name,c.* from `TBL_EMP` e, `TBL_DEPT` d, `TBL_COMPANY` c where d.ID = #{id} and d.COMPANY_ID = c.id and d.ID = e.DEPT_ID; 
    </select>
</mapper>

   最后,测试一下是否能够落实关系查询

package com.mmm.test;

import java.io.IOException;
import java.io.Reader;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import com.mmm.mapper.DeptMapper;
import com.mmm.pojo.Dept;

public class TestMyBatis {

    @Test
    public void testCore() throws IOException {
        //直接实例SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //MyBatis配置文件路径
        String path = "mybatis-config.xml";
        //通过路径获取输入流
        Reader reader = Resources.getResourceAsReader(path);
        //通过reader构建sessionFactory
        SqlSessionFactory sessionFactory = builder.build(reader);
        //获取SqlSession对象
        SqlSession sqlSession = sessionFactory.openSession();
        //获取Mapper实例
        DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
        //根据id查找制定的部门,并关联查询出其公司和员工信息
        Dept dept = mapper.selectById(10001);
        System.out.println(dept);
    }
}

  控制高出口信息过长,复制下来粘贴如下内容:

  Dept [id=10001, deptName=资产部,
company=Company [id=10003, companyName=公司一], empList=[Emp
[id=10001, name=员工一, gender=男], Emp [id=10002, name=员工二,
gender=男], Emp [id=10003, name=员工三, gender=男]]]

  可以观看,至此基本落实了,查询部门经常,也涉查询有了所属企业信息、下面有机关职工信息。

  我们于浏览网站,点击链接跳转,每个页面的基础代谢,大多是时时刻刻以恳求查询数据库中之数据,当然为不备是查询,例如会产生日记记录,也是插操作等等。查询是一个于关键之始末,怎样干查询,怎么优化查询语句,减少查询次数,提高查询速度等等都是待去琢磨与上之地方。

网站地图xml地图