实例解析:MyBatis中复杂resultMap结果映射

来源:互联网 发布:彩票预测算法 编辑:程序博客网 时间:2024/05/16 11:02

resultMap是MyBatis里面最复杂的元素,它的作用是定义映射规则、级联的更新、定制类型转化器等。

在实际的应用中,数据库中的实体存在三种基本的级联关系:
1、一对一关系
2、一对多关系
3、多对多关系

多对多关系在转化成物理表结构之后,可以分解为两个一对多的关系。那么在使用MyBatis时,如何处理“一对一关系”,“多对多关系”?

在MyBatis中,官方文档描述如下:

resultMap:

  • constructor - 类在实例化时,用来注入结果到构造方法中
    idArg - ID 参数;标记结果作为 ID 可以帮助提高整体效能
    arg - 注入到构造方法的一个普通结果
  • id – 一个 ID 结果;标记结果作为 ID 可以帮助提高整体效能
  • result – 注入到字段或 JavaBean 属性的普通结果
  • association – 一个复杂的类型关联;许多结果将包成这种类型
    嵌入结果映射 – 结果映射自身的关联,或者参考一个
  • collection – 复杂类型的集
    嵌入结果映射 – 结果映射自身的集,或者参考一个
  • discriminator – 使用结果值来决定使用哪个结果映射
    case – 基于某些值的结果映射
    ◾嵌入结果映射 – 这种情形结果也映射它本身,因此可以包含很多相 同的元素,或者它可以参照一个外部的结果映射。

代码片段……,一个resultMap的例子:

<resultMap id="productsResultMap" type="com.keymen.domain.Products">        <id column="productid" property="productid" jdbcType="VARCHAR" />        <result column="productname" property="productname" jdbcType="VARCHAR" />        <result column="productmemo" property="productmemo" jdbcType="VARCHAR" />        <result column="createtime" property="createtime" jdbcType="TIMESTAMP" />        <result column="updatetime" property="updatetime" jdbcType="TIMESTAMP" />        <result column="deletetime" property="deletetime" jdbcType="TIMESTAMP" />        <!-- 定义产品类型与产品的对应关系 ,一个产品类型对应多个产品,这是一对多的关系 -->        <association property="prodtype" resultMap="productsTypeResult" />    </resultMap>

关联
关联元素处理“有一个”类型的关系。比如,在我们的示例中,一个博客有一个用户。 关联映射就工作于这种结果之上。你指定了目标属性,来获取值的列,属性的 java 类型(很多情况下 MyBatis 可以自己算出来) ,如果需要的话还有 jdbc 类型,如果你想覆盖或获取的结果值还需要类型控制器。

关联中不同的是你需要告诉 MyBatis 如何加载关联。MyBatis 在这方面会有两种不同的 方式:

  • 嵌套查询:通过执行另外一个 SQL 映射语句来返回预期的复杂类型。
  • 嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集。首先,然让我们来查看这个元素的属性。所有的你都会看到,它和普通的只由select 和resultMap 属性的结果映射不同。

下面通过实例在说明resultMap结果映射的关系(一对一)

需要提前准备的内容:

在MySQL数据库中,创建一个testdb数据库。再创建两张数据表:

  • 产品类型表(tb_products_type)
  • 产品表(tb_products)

其中包含的实体关系:每一个产品都有唯一的产品类型;而一类产品类型,包含多个产品。

创建数据表的SQL语句如下:

create table tb_products_type(prodtypeid integer not null primary key,prodtypename varchar(40) not null,prodparentid integer,createtime time,updatetime time,deletetime time);create table tb_products(productid varchar(40) not null primary key,prodtypeid integer not null,productname varchar(80) not null,productunit varchar(40),productmemo varchar(100),createtime time,updatetime time,deletetime time);

需要注意的是,要在产品表(tb_products表)中的prodtypeid列上建外键(Foreign Key)。

向表中插入测试数据:

insert into tb_products_type values(1001,'Clothes',null,now(),null,null);insert into tb_products_type values(4210,'Man Suit',1001,now(),null,null);insert into tb_products values('TC180001',4210,'Dock Man Suit','unit','Made in China',now(),null,null);commit;

查询表中的数据。
这样数据库表就准备好了。

下面在创建JAVA Project类实现复杂的resultMap结果映射。

1. 规划工程的包结构和配置文件结构
src
- com.keymen.application
- com.keymen.dao
- com.keymen.domain
- com.keymen.sqlMappers
- com.keymen.test
- Configurations.xml
-jdbc.properties
-mybatis.xml
再在工程中加入包:
mybatis-3.2.6.jar和mysql-connector-java-5.1.13-bin.jar。

2. 编写POJO类
2.1 编写产品类型POJO类:ProductsType

package com.keymen.domain;import java.util.Date;public class ProductsType {    private int producttypeid;    private String prodtypename;    private int prodparentid;    private Date createtime;    private Date updatetime;    private Date deletetime;    public ProductsType() {        super();    }    public ProductsType(int producttypeid, String prodtypename, int prodparentid, Date createtime, Date updatetime,            Date deletetime) {        super();        this.producttypeid = producttypeid;        this.prodtypename = prodtypename;        this.prodparentid = prodparentid;        this.createtime = createtime;        this.updatetime = updatetime;        this.deletetime = deletetime;    }    public int getProducttypeid() {        return producttypeid;    }    public void setProducttypeid(int producttypeid) {        this.producttypeid = producttypeid;    }    public String getProdtypename() {        return prodtypename;    }    public void setProdtypename(String prodtypename) {        this.prodtypename = prodtypename;    }    public int getProdparentid() {        return prodparentid;    }    public void setProdparentid(int prodparentid) {        this.prodparentid = prodparentid;    }    public Date getCreatetime() {        return createtime;    }    public void setCreatetime(Date createtime) {        this.createtime = createtime;    }    public Date getUpdatetime() {        return updatetime;    }    public void setUpdatetime(Date updatetime) {        this.updatetime = updatetime;    }    public Date getDeletetime() {        return deletetime;    }    public void setDeletetime(Date deletetime) {        this.deletetime = deletetime;    }}

2.2 编写产品POJO类:Products

package com.keymen.domain;import java.util.Date;public class Products {    private String productid;    //注意这个属性:产品类型对象    private ProductsType prodtype;    private String productname;    private String productunit;    private String productmemo;    private Date createtime;    private Date updatetime;    private Date deletetime;    public Products() {        super();    }    public Products(String productid, ProductsType prodtype, String productname, String productunit, String productmemo,            Date createtime, Date updatetime, Date deletetime) {        super();        this.productid = productid;        this.prodtype = prodtype;        this.productname = productname;        this.productunit = productunit;        this.productmemo = productmemo;        this.createtime = createtime;        this.updatetime = updatetime;        this.deletetime = deletetime;    }    public String getProductid() {        return productid;    }    public void setProductid(String productid) {        this.productid = productid;    }    public ProductsType getProdtype() {        return prodtype;    }    public void setProdtype(ProductsType prodtype) {        this.prodtype = prodtype;    }    public String getProductname() {        return productname;    }    public void setProductname(String productname) {        this.productname = productname;    }    public String getProductunit() {        return productunit;    }    public void setProductunit(String productunit) {        this.productunit = productunit;    }    public String getProductmemo() {        return productmemo;    }    public void setProductmemo(String productmemo) {        this.productmemo = productmemo;    }    public Date getCreatetime() {        return createtime;    }    public void setCreatetime(Date createtime) {        this.createtime = createtime;    }    public Date getUpdatetime() {        return updatetime;    }    public void setUpdatetime(Date updatetime) {        this.updatetime = updatetime;    }    public Date getDeletetime() {        return deletetime;    }    public void setDeletetime(Date deletetime) {        this.deletetime = deletetime;    }}

3. 编写MyBatis配置文件:Configurations.xml

<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"  "http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration>    <properties resource="jdbc.properties"></properties>    <environments default="development">        <environment id="development">            <transactionManager type="JDBC" />            <dataSource type="POOLED">                <property name="driver" value="${jdbc.driverClassName}" />                <property name="url" value="${jdbc.url}" />                <property name="username" value="${jdbc.username}" />                <property name="password" value="${jdbc.password}" />            </dataSource>        </environment>    </environments>    <mappers>        <mapper resource="com/keymen/sqlMappers/products.xml" />    </mappers></configuration>  

编写 jdbc.properties数据库连接配置文件

jdbc.driverClassName=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://localhost:3306/testdbjdbc.username=rootjdbc.password=baggio800jdbc.initialSize=0jdbc.maxActive=20jdbc.maxIdle=20jdbc.minIdle=1jdbc.maxWait=60000

4. 编写XML映射文件

mybatis.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>    <mappers>        <mapper resource="com/keymen/sqlMappers/products.xml" />    </mappers></configuration>

编写products.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="com.keymen.dao.ProductsDAO">    <resultMap id="productsResultMap" type="com.keymen.domain.Products">        <id column="productid" property="productid" jdbcType="VARCHAR" />        <result column="productname" property="productname" jdbcType="VARCHAR" />        <result column="productmemo" property="productmemo" jdbcType="VARCHAR" />        <result column="createtime" property="createtime" jdbcType="TIMESTAMP" />        <result column="updatetime" property="updatetime" jdbcType="TIMESTAMP" />        <result column="deletetime" property="deletetime" jdbcType="TIMESTAMP" />        <!-- 定义产品类型与产品的对应关系 ,一个产品类型对应多个产品,这是一对多的关系 -->        <association property="prodtype" resultMap="productsTypeResult" />    </resultMap>    <resultMap id="productsTypeResult" type="com.keymen.domain.ProductsType">        <!-- 注意此处,在Domain类中的属性和在数据库表中对应的字段名称不一致,下面的property和column的对应关系 -->        <id property="producttypeid" column="prodtypeid" />        <result property="prodtypename" column="prodtypename" />        <result property="prodparentid" column="prodparentid" />        <result property="createtime" column="createtime" />        <result property="updatetime" column="updatetime" />        <result property="deletetime" column="deletetime" />    </resultMap>    <select id="getProductsByID" resultMap="productsResultMap">        select        p.productid,p.productname,p.prodtypeid,pt.prodtypename        from tb_products p join tb_products_type pt        on p.prodtypeid=pt.prodtypeid        and p.productid = #{id}    </select></mapper>

5. 编写DAO接口

package com.keymen.dao;import com.keymen.domain.Products;public interface ProductsDAO {    public Products getProductsByID(String productid);}

6. 编写测试类

package com.keymen.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 com.keymen.dao.ProductsDAO;import com.keymen.domain.Products;public class TestSelectProducts {    public static void main(String[] args) {        // TODO Auto-generated method stub        String resource = "Configurations.xml";        // 通过Mybatis包中的Resources对象很轻松的获取到配置文件        Reader reader = null;        try {            reader = Resources.getResourceAsReader(resource);        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }        // 通过SqlSessionFactoryBuilder创建        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);        // 获得session实例        SqlSession session = sqlSessionFactory.openSession();        if (session != null) {            System.out.println("Already got session ....");            ProductsDAO productDAO = session.getMapper(ProductsDAO.class);            Products product = productDAO.getProductsByID("TC180001");            System.out.println("executing searching....");            System.out.println(product.getProductname() + "\n" + product.getProdtype().getProducttypeid() + "\n"                    + product.getProdtype().getProdtypename() + "\n");        } else {            System.out.println("session is null....");        }        session.commit();        session.close();        System.out.println(sqlSessionFactory);    }}

7. 总结

运行结果:

Already got session ….
executing searching….
Dock Man Suit (数据来自产品表)
4210 (数据来自产品类型表)
Man Suit (数据来自产品类型表)

从运行结果来看:
程序创建了session,然后执行查询,从产品表和产品类型表中进行了连接查询,获取了相应的数据。

完毕。

0 0