2.MyBatis映射

1 默认映射方式

  1. 上一节的select语句的resultType默认映射方式要求将查询出来字段属性名和模型类属性名一一对应。有如下规则。

    如果查询出来的列名和pojo中的属性名全部不一致,没有创建pojo对象。 只要查询出来的列名和pojo中的属性有一个一致,就会创建pojo对象。

这就是默认的映射方式。

  1. 如果映射出来的模型对象有另一个对象作为他的属性。则不能够使用默认映射,需要使用使用resultMap结点。

图片.png

2 一对多、多对多的E-R图

图片.png

  1. sql脚本
  1. drop database how2java;
  2. create database how2java;
  3. use how2java;
  4. -- 分类表
  5. CREATE TABLE category_ (
  6. id int(11) NOT NULL AUTO_INCREMENT,
  7. name varchar(32) DEFAULT NULL,
  8. PRIMARY KEY (id)
  9. ) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
  10. -- 产品表
  11. create table product_(
  12. id int NOT NULL AUTO_INCREMENT,
  13. name varchar(30) DEFAULT NULL,
  14. price float DEFAULT 0,
  15. cid int ,
  16. PRIMARY KEY (id)
  17. )AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
  18. -- 插入数据
  19. delete from category_;
  20. INSERT INTO category_ VALUES (1,'衣服');
  21. INSERT INTO category_ VALUES (2,'玩具');
  22. delete from product_;
  23. INSERT INTO product_ VALUES (1,'帽子', 30, 1);
  24. INSERT INTO product_ VALUES (2,'鞋子', 20, 1);
  25. INSERT INTO product_ VALUES (3,'袜子', 10, 1);
  26. INSERT INTO product_ VALUES (4,'变形金刚', 50, 2);
  27. INSERT INTO product_ VALUES (5,'赛车', 70, 2);
  28. INSERT INTO product_ VALUES (6,'芭比娃娃', 100.5, 2);
  29. select * from category_;
  30. select * from product_;
  31. create table order_ (
  32. id int(11) NOT NULL AUTO_INCREMENT,
  33. code varchar(32) DEFAULT NULL,
  34. PRIMARY KEY (id)
  35. ) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
  36. create table order_item_(
  37. id int(11) NOT NULL AUTO_INCREMENT,
  38. oid int ,
  39. pid int ,
  40. number int ,
  41. PRIMARY KEY(id)
  42. )AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
  43. INSERT INTO order_ VALUES (1,'code000A');
  44. INSERT INTO order_ VALUES (2,'code000B');
  45. INSERT INTO order_item_ VALUES (null, 1, 1, 100);
  46. INSERT INTO order_item_ VALUES (null, 1, 2, 100);
  47. INSERT INTO order_item_ VALUES (null, 1, 3, 100);
  48. INSERT INTO order_item_ VALUES (null, 2, 2, 100);
  49. INSERT INTO order_item_ VALUES (null, 2, 3, 100);
  50. INSERT INTO order_item_ VALUES (null, 2, 4, 100);
  51. select * from order_;
  52. select * from order_item_;
  1. 模型类

    1. Order模型
    2. OrderItem模型
    3. Category模型
    4. Product模型

      3 一对多

      3.1 从商品类别的角度是一对多

  2. 映射文件中select结点不用resultType属性,不使用默认映射,而是使用resultMap来指向一个resultMap结点。

一个select出的条目传入到resultMap中映射,创建相对应的对象。

  1. <select id="listCategory" resultMap="categoryBean">
  2. <!-- 对于重复字段需要给出别名 -->
  3. <!-- 内连接就是指定两张表上具有相同字段的行连接到一起组成新的行 -->
  4. <!-- 左外连接=内连接+左表中连接字段为空的行 -->
  5. <!-- 右外连接=内连接+右表中连接字段为空的行 -->
  6. <!-- 全外连接=内连接+左右表中连接字段为空的行 -->
  7. <!-- 自然连接在相同字段上做笛卡儿积 -->
  8. select c.id 'cid', p.id 'pid', c.name 'cname', p.name 'pname',price from category_ c left join product_ p on c.id=p.cid
  9. </select>
  1. 映射文件中resultMap结点,id属性定义唯一标志,type属性表示模型类。
    1. id和result结点来对简单数据类型的映射。 column指定SQL语句查询结果的属性,property指定返回对象的某个属性
    2. collection结点对于集合类型(数组、List等)映射,property指定返回对象,property指定集合元素的类型。其中的id和result结点用来集合中的各个元素。
  1. <resultMap type="Category" id="categoryBean">
  2. <!-- column指定SQL语句查询结果的行,property指定返回对象的某个属性 -->
  3. <id column="cid" property="id"/>
  4. <result column="cname" property="name"/>
  5. <!-- 一对多的属性用collection标签,把上述属性相同的条目聚合到一起 -->
  6. <!-- property: 指的是集合属性的值, ofType:指的是集合中元素的类型 -->
  7. <collection property="products" ofType="Product">
  8. <id column="pid" property="id" />
  9. <result column="pname" property="name" />
  10. <result column="price" property="price" />
  11. </collection>
  12. </resultMap>

3.2 从商品的角度是多对一,对于单个商品来说是一对一

  1. 映射文件中select结点。
  1. <!-- 根据cid关联查询所有 -->
  2. <select id="listProduct" resultMap="productBean">
  3. select p.*,c.*,
  4. p.id 'pid',c.id 'cid',
  5. p.name 'pname',c.name 'cname'
  6. from product_ p
  7. left join category_ c on c.id = p.cid
  8. </select>
  1. 映射文件中resultMap结点。其他结点与上述相同。association结点用来表示单个对象。
  1. <resultMap type="Product" id="productBean">
  2. <id column="pid" property="id" />
  3. <result column="pname" property="name" />
  4. <result column="price" property="price" />
  5. <!-- 多对一的关系用association标签 -->
  6. <!-- property: 指的是属性名称, javaType:指的是属性的类型 -->
  7. <association property="category" javaType="Category">
  8. <id column="cid" property="id"/>
  9. <result column="cname" property="name"/>
  10. </association>
  11. </resultMap>

4 多对多

多对多关系,通常需要第三张表的介入,对于订单和商品两张表,需要订单条目的介入。

  1. 一个订单条目对应一个订单。
  2. 一个订单对应多个订单条目。
  3. 一个订单条目对应一个商品。
  4. 一个商品对应多个订单条目

    4.1 从商品的角度对订单条目看

  1. <resultMap type="Product" id="productBean2">
  2. <id column="p_id" property="id" />
  3. <result column="pname" property="name" />
  4. <result column="price" property="price" />
  5. <!-- 多对一的关系用association标签 -->
  6. <!-- property: 指的是属性名称, javaType:指的是属性的类型 -->
  7. <association property="category" javaType="Category">
  8. <id column="c_id" property="id"/>
  9. <result column="cname" property="name"/>
  10. </association>
  11. <!-- 一对多的关系用collection标签 -->
  12. <collection property="orderItems" ofType="OrderItem">
  13. <id column="oi_id" property="id" />
  14. <result column="number" property="number" />
  15. <association property="order" javaType="Order">
  16. <id column="o_id" property="id"/>
  17. <result column="code" property="code"/>
  18. </association>
  19. </collection>
  20. </resultMap>
  21. <!-- 查询所有关于该商品的订单和类别的记录 -->
  22. <select id="listProductandItems" resultMap="productBean2">
  23. select p.*,c.*,oi.*,o.*,
  24. p.id 'p_id',c.id 'c_id',o.id 'o_id',oi.id 'oi_id',
  25. p.name 'pname',c.name 'cname'
  26. from product_ p
  27. left join category_ c on p.cid = c.id
  28. left join order_item_ oi on p.id =oi.pid
  29. left join order_ o on oi.oid=o.id
  30. </select>

4.2 从订单的角度对订单条目看

  1. <resultMap type="Order" id="orderBean">
  2. <id column="oid" property="id" />
  3. <result column="code" property="code" />
  4. <!-- 当前Order对象对应多个OrderItem -->
  5. <collection property="orderItems" ofType="OrderItem">
  6. <id column="oiid" property="id" />
  7. <result column="number" property="number" />
  8. <association property="product" javaType="Product">
  9. <id column="pid" property="id"/>
  10. <result column="pname" property="name"/>
  11. <result column="price" property="price"/>
  12. </association>
  13. </collection>
  14. </resultMap>
  15. <!-- 订单表、订单条目表、商品表三表连接,查询出每个订单下各个条目具体信息 -->
  16. <select id="listOrder" resultMap="orderBean">
  17. select o.*,p.*,oi.*, o.id 'oid', p.id 'pid', oi.id 'oiid', p.name 'pname'
  18. from order_ o
  19. left join order_item_ oi on o.id =oi.oid
  20. left join product_ p on p.id = oi.pid
  21. </select>
  22. <select id="getOrder" resultMap="orderBean">
  23. select o.*,p.*,oi.*, o.id 'oid', p.id 'pid', oi.id 'oiid', p.name 'pname'
  24. from order_ o
  25. left join order_item_ oi on o.id =oi.oid
  26. left join product_ p on p.id = oi.pid
  27. where o.id = #{id}
  28. </select>

4.3 从订单条目对商品、订单看

可以通过对订单条目增加减少对于多对多关系增加

  1. !-- 在中间表上添加条目,相当于增加关系 -->
  2. <insert id="addOrderItem" parameterType="OrderItem">
  3. insert into order_item_
  4. values(null,#{order.id},#{product.id},#{number})
  5. </insert>
  6. <!-- 在中间表删除条目,想到那与删除关系 -->
  7. <insert id="deleteOrderItem" parameterType="OrderItem">
  8. delete from order_item_
  9. where oid = #{order.id} and pid = #{product.id}
  10. </insert>

5 总结

5.1 映射方式

  1. 默认映射方式,resultType指定特定类型。
  2. 指定映射方式,resultMap指定某个resultMap结点,通过id、result结点中的column、porperty指定sql中的属性、类中的属性。

    5.2 一对多、多对多关系

    这些关系都是要从自己这方面看一对多用collection结点,多对一或一对一用association结点。

    5.3 连接查询

    连接查询为了避免一些不必要的特殊问题,连接查询时多个表中的相同字段需要用别名区分。用这种方式查询到所有的结点之后。
    同时要注意别名的效果,可能别名也会有冲突,因此映射文件的SQL语句要现在可视化终端执行后再写入到映射配置文件里。
    例如在下面的四个表连接时。
    1. select p.*,c.*,oi.*,o.*,
    2. p.id 'pid',c.id 'c_id',o.id 'o_id',oi.id 'oi_id',
    3. p.name 'pname',c.name 'cname'
    4. from product_ p
    5. left join category_ c on p.cid = c.id
    6. left join order_item_ oi on p.id =oi.pid
    7. left join order_ o on oi.oid=o.id
    图片.png