在多表联合查询操作时,存在一对一、一对多、多对多的关系
每张表中的数据内容
每张表的主要字段:外键字段,非空字段
表与表之间的业务关系
数据库表:
user(用户表):记录购买商品的用户信息
orders(订单表):记录用户创建的所有订单
orderdetail(订单明细表):记录订单的详细的购买信息
items(商品表):记录商品信息
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) NOT NULL COMMENT '用户名称',
`sex` char(1) DEFAULT NULL COMMENT '性别',
`address` varchar(256) DEFAULT NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8
CREATE TABLE `orders` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL COMMENT '下单用户id',
`number` varchar(32) NOT NULL COMMENT '订单号',
`createtime` datetime NOT NULL COMMENT '创建订单时间',
`note` varchar(100) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`),
KEY `FK_orders_1` (`user_id`),
CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8
CREATE TABLE `orderdetail` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`orders_id` int(11) NOT NULL COMMENT '订单id',
`items_id` int(11) NOT NULL COMMENT '商品id',
`items_num` int(11) DEFAULT NULL COMMENT '商品购买数量',
PRIMARY KEY (`id`),
KEY `FK_orderdetail_1` (`orders_id`),
KEY `FK_orderdetail_2` (`items_id`),
CONSTRAINT `FK_orderdetail_1` FOREIGN KEY (`orders_id`) REFERENCES `orders` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `FK_orderdetail_2` FOREIGN KEY (`items_id`) REFERENCES `items` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8
CREATE TABLE `items` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL COMMENT '商品名称',
`price` float(10,1) NOT NULL COMMENT '商品定价',
`detail` text COMMENT '商品描述',
`pic` varchar(64) DEFAULT NULL COMMENT '商品图片',
`createtime` datetime NOT NULL COMMENT '生产日期',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8
需求:通过订单号查询订单及用户信息
分析:通过分析:订单号是在订单表中,通过订单表中的user_id字段可以查询到用户信息
主表:orders 从表:user
SQL:select * from orders o,user u where o.user_id=u.id and o.number=?
pojo类中添加User类型的属性:
public class Orders {
private int id;
private int userId;
private long number;
private Date createtime;
private String note;
// 增加一个User类型
private User user;
private String createTime;
//Getter和Setter方法
}
接口:
public Orders getOrdersByNumber(String number);
Mapper的XML文件
使用resultType配置一对一映射:
<select id="getOrdersByNumber" parameterType="java.lang.String" resultType="com.tulun.maventest.pojo.Orders">
select o.*,u.id "user.id",u.username "user.username",u.sex "user.sex",u.address "user.address" from orders o,user u where o.user_id=u.id and o.number=#{number}
</select>
使用resultMap配置一对一映射:
<resultMap id="OrderUserResultMap" type="com.tulun.maventest.pojo.Orders">
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime" javaType="java.util.Date" jdbcType="TIMESTAMP"/>
<result column="note" property="note"/>
<!--user配置-->
<result column="u_id" property="user.id"/>
<result column="u_username" property="user.username"/>
<result column="u_sex" property="user.sex"/>
<result column="u_address" property="user.address"/>
</resultMap>
<select id="getOrdersByNumber" parameterType="java.lang.String" resultMap="OrderUserResultMap">
select o.*,u.id u_id,u.username u_username,u.sex u_sex,u.address u_address from orders o,user u where o.user_id=u.id and o.number=#{number}
</select>
使用resultMap提供的association配置一对一映射:
<resultMap id="OrderUserResultMap" type="com.tulun.maventest.pojo.Orders">
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime" javaType="java.util.Date" jdbcType="TIMESTAMP"/>
<result column="note" property="note"/>
<!--
association:用于映射关联查询单个对象的信息
property:关联查询映射到对应的自定义的对象属性
javaType:映射的Java属性的全限定名
-->
<association property="user" columnPrefix="u_" javaType="com.tulun.maventest.pojo.User">
<!--user配置-->
<result column="id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
</association>
</resultMap>
<select id="getOrdersByNumber" parameterType="java.lang.String" resultMap="OrderUserResultMap">
select o.*,u.id u_id,u.username u_username,u.sex u_sex,u.address u_address from orders o,user u where o.user_id=u.id and o.number=#{number}
</select>
优化1:使用extends属性继承当前的主类
<!--优化1:使用association关联映射对象,extends继承主类-->
<!--association配置-->
<resultMap id="OrderUserResultMap" extends="OrdersResultMap" type="com.tulun.maventest.pojo.Orders">
<association property="user" columnPrefix="u_" javaType="com.tulun.maventest.pojo.User">
<!--user配置-->
<result column="id" property="id"/>
<result column="username" property="username"/>
<result column="sex" property="sex"/>
<result column="address" property="address"/>
</association>
</resultMap>
优化2:使用association中的resultMap属性
<!--优化2:使用association关联映射对象,extends继承主类,使用association标签下resultMap的属性-->
<!--association配置-->
<resultMap id="OrderUserResultMap" extends="OrdersResultMap" type="com.tulun.maventest.pojo.Orders">
<!--association的resultMap属性指向已存在Mapper的全路径名-->
<association property="user" columnPrefix="u_" resultMap="com.tulun.maventest.dao.UserMapper.ResultUserMapper"/>
</resultMap>
一对一映射中,使用到resultMap的association标签。
resultMap和resultType的区别?
需要关联的映射是一个List结果
需求:查询用户的订单信息(例如:通过用户ID)
分析:通过用户(主表:user)的关键信息查询所有相关的订单(从表:orders)
SQL:select u.*,o.* from user u,orders o where u.id =o.user_id and u.id=?
映射对象:
public class User {
private int id;
private String username;
private String sex;
private String address;
//增加一个Order类型的集合
private List<Orders> orders;
}
Mybatis的XML文件中SQL片段的复原示例:
XML文件配置:
<!--
使用resultMap中的Collection配置一对多关系
Collection:将关联查询的多条记录映射到集合对象中
property:将关联查询的多条记录映射到的属性名:orders
ofType:指定映射的集合属性中的自定义类型
extends:继承主类
-->
<resultMap id="ResultUserOrdersMapper" extends="ResultUserMapper" type="com.tulun.maventest.pojo.User">
<!--orders的结果集-->
<collection property="orders" columnPrefix="order_" ofType="com.tulun.maventest.pojo.Orders">
<result column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="number" property="number"/>
<result column="createtime" property="createtime"/>
<result column="note" property="note"/>
</collection>
</resultMap>
<sql id="selectId">
u.id,
u.username,
u.sex,
u.address,
o.id order_id,
o.user_id order_user_id,
o.number order_number,
o.createtime order_createtime,
o.note order_note
</sql>
<select id="getUserOrdersById" parameterType="int" resultMap="ResultUserOrdersMapper">
select
<include refid="selectId"/>
from user u, orders o where u.id=o.user_id and u.id=#{uid}
</select>
一对多的映射:使用到resultMap下的Collection标签
需求:查询用户及用户的商品信息
分析:主表是user
存在用户对象User,存在订单表对象Orders,存在订单明细表对象OrderDetail,商品表对象Items
映射的对象为User对象,在User对象中添加一个订单列表的属性:Lise
在Orders中添加订单明细的属性List
在订单明细中OrderDetail中添加Items的属性,将订单明细所对应的商品映射到item
resultType:
作用:将查询结果的SQL列名和pojo类的属性名完成一致性的映射
缺点:若SQL结果列名和pojo类属性名不一致,则无法自动完成映射
resultMap:
使用association和Collection完成一对一和一对多的高级映射(对结果有特殊要求的映射对象 )
作用:将关联查询的信息映射到一个pojo对象中
使用resultType无法将查询结果映射到pojo对象的pojo属性中时,选择resultMap来处理(association)
Collection:
作用:将关联查询映射到一个List集合中
使用resultType无法将查询结果映射到pojo对象的List类型的pojo属性时,使用resultMap的Collection标签来处理