衔接上一篇 Mybatis基础
Mybatis简单入门:https://blog.csdn.net/qq_28863191/article/details/100847350
目录
resultMap
使用resultMap
动态sql
If 标签
Where 标签
Sql片段
foreach 标签
关联查询
一对一查询
一对多查询
resultType可以指定将查询结果映射为pojo,当pojo对象的属性名和 sql 中相应的表中对应的字段名一致时,才可以
当有属性名和 sql 中字段名不一致时,resultType无法获取该字段,输出null,这时我们就需要用 resultMap 来进行手动映射。
resultMap可以实现将查询结果映射为复杂类型的pojo(多表查询),resultType不行,它只能通过构建新的pojo对象的方式将多表联合起来。
数据库表如下图:
Order对象:
public class Order {
// 订单id
private int id;
// 用户id
private Integer userId;
// 订单号
private String number;
// 订单创建时间
private Date createtime;
// 备注
private String note;
get/set。。。
}
创建OrderMapper.xml配置文件,如下:
<mapper namespace="cn.itcast.mybatis.mapper.OrderMapper">
<select id="queryOrderAll" resultType="order">
SELECT id, user_id,
number,
createtime, note FROM `order`
select>
mapper>
查询后因为 pojo 中是 userId,而 sql 中是 user_id,不能自动映射输出时就会得到 null 的结果
由于上边的mapper.xml中sql查询列(user_id)和Order类属性(userId)不一致,所以查询结果不能映射到pojo中。
需要定义resultMap,把orderResultMap将sql查询列(user_id)和Order类属性(userId)对应起来
<mapper namespace="cn.itcast.mybatis.mapper.OrderMapper">
<resultMap type="order" id="orderResultMap">
<id property="id" column="id" />
<result property="userId" column="user_id" />
<result property="number" column="number" />
<result property="createtime" column="createtime" />
<result property="note" column="note" />
resultMap>
<select id="queryOrderAll" resultMap="orderResultMap">
SELECT id, user_id,
number,
createtime, note FROM `order`
select>
mapper>
注意:如果resultMap中只是单表的话,
通过mybatis提供的各种标签方法实现动态拼接sql。
需求:根据性别和名字查询用户
UserMapper.xml配置sql,如下:
<select id="queryUserByWhere" parameterType="user" resultType="user">
SELECT id, username, birthday, sex, address FROM `user`
WHERE sex = #{sex} AND username LIKE
'%${username}%'
select>
改造UserMapper.xml,如下:
<select id="queryUserByWhere" parameterType="user" resultType="user">
SELECT id, username, birthday, sex, address FROM `user`
<if test="sex != null and sex != ''">
AND sex = #{sex}
if>
<if test="username != null and username != ''">
AND username LIKE
'%${username}%'
if>
select>
上表中sex或者username没有时sql语句就会变成
SELECT id, username, birthday, sex, address FROM `user` AND sex = #{sex}(或者 AND username LIKE %${username}%')
虽然可以根据自己有没有传sex或者username来改变查询语句,但是and这个关键字会多出来导致sql语法错误,怎么办?
这时就需要 Where标签
<select id="queryUserByWhere" parameterType="user" resultType="user">
SELECT id, username, birthday, sex, address FROM `user`
<where>
<if test="sex != null">
AND sex = #{sex}
if>
<if test="username != null and username != ''">
AND username LIKE
'%${username}%'
if>
where>
select>
Where 标签 会将第一个有值的
Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的。
把上面例子中的 ----id, username, birthday, sex, address---- 提取出来,作为sql片段,如下:
<sql id="userFields">
id, username, birthday, sex, address
sql>
<select id="queryUserByWhere" parameterType="user" resultType="user">
SELECT <include refid="userFields" /> FROM `user`
<where>
<if test="sex != null">
AND sex = #{sex}
if>
<if test="username != null and username != ''">
AND username LIKE
'%${username}%'
if>
where>
select>
如果要使用别的Mapper.xml配置的sql片段,可以在refid前面加上对应的Mapper.xml的namespace
例如下图
向sql传递数组或List,mybatis使用foreach解析,如下:
根据多个id查询用户信息
查询sql:
SELECT * FROM user WHERE id IN (1,10,24)
改造QueryVo
如下图在pojo中定义list属性ids存储多个用户id,并添加getter/setter方法
Mapper.xml文件
UserMapper.xml添加sql,如下:
<select id="queryUserByIds" parameterType="queryVo" resultType="user">
SELECT * FROM `user`
<where>
<foreach collection="ids" item="item" open="id IN (" close=")"
separator=",">
#{item}
foreach>
where>
select>
通过order查询user,因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询。如果从用户信息出发查询用户下的订单信息则为一对多查询,因为一个用户可以下多个订单。
SELECT
o.id,
o.user_id userId,
o.number,
o.createtime,
o.note,
u.username,
u.address
FROM
`order` o
LEFT JOIN `user` u ON o.user_id = u.id
使用resultMap,定义专门的resultMap用于映射一对一查询结果
改造pojo类
在Order类中加入User属性,user属性中用于存储关联查询的用户信息,因为订单关联查询用户是一对一关系,所以这里使用单个User对象存储关联查询的用户信息。
改造Order如下图:
Mapper.xml
这里resultMap指定orderUserResultMap,如下:
<resultMap type="order" id="orderUserResultMap">
<id property="id" column="id" />
<result property="userId" column="user_id" />
<result property="number" column="number" />
<result property="createtime" column="createtime" />
<result property="note" column="note" />
<association property="user" javaType="user">
<id property="id" column="user_id" />
<result property="username" column="username" />
<result property="address" column="address" />
association>
resultMap>
<select id="queryOrderUserResultMap" resultMap="orderUserResultMap">
SELECT
o.id,
o.user_id,
o.number,
o.createtime,
o.note,
u.username,
u.address
FROM
`order` o
LEFT JOIN `user` u ON o.user_id = u.id
select>
Mapper接口
编写UserMapper如下图:
测试方法,如下:
@Test
public void testQueryOrderUserResultMap() {
// mybatis和spring整合,整合之后,交给spring管理
SqlSession sqlSession = this.sqlSessionFactory.openSession();
// 创建Mapper接口的动态代理对象,整合之后,交给spring管理
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 使用userMapper执行根据条件查询用户
List list = userMapper.queryOrderUserResultMap();
for (Order o : list) {
System.out.println(o);
}
// mybatis和spring整合,整合之后,交给spring管理
sqlSession.close();
}
案例:查询所有用户信息及用户关联的订单信息。
用户信息和订单信息为一对多关系。
sql语句:
SELECT
u.id,
u.username,
u.birthday,
u.sex,
u.address,
o.id oid,
o.number,
o.createtime,
o.note
FROM
`user` u
LEFT JOIN `order` o ON u.id = o.user_id
修改pojo类
在User类中加入List
在UserMapper.xml添加sql,如下:
<resultMap type="user" id="userOrderResultMap">
<id property="id" column="id" />
<result property="username" column="username" />
<result property="birthday" column="birthday" />
<result property="sex" column="sex" />
<result property="address" column="address" />
<collection property="orders" javaType="list" ofType="Order"(这是list中每一个元素的类型)>
<id property="id" column="oid" />
<result property="number" column="number" />
<result property="createtime" column="createtime" />
<result property="note" column="note" />
collection>
resultMap>
<select id="queryUserOrder" resultMap="userOrderResultMap">
SELECT
u.id,
u.username,
u.birthday,
u.sex,
u.address,
o.id oid,
o.number,
o.createtime,
o.note
FROM
`user` u
LEFT JOIN `order` o ON u.id = o.user_id
select>
Mapper接口
编写UserMapper接口,如下图:
测试方法
在UserMapperTest增加测试方法,如下
@Test
public void testQueryUserOrder() {
// mybatis和spring整合,整合之后,交给spring管理
SqlSession sqlSession = this.sqlSessionFactory.openSession();
// 创建Mapper接口的动态代理对象,整合之后,交给spring管理
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 使用userMapper执行根据条件查询用户
List
list = userMapper.queryUserOrder();
for (User u : list) {
System.out.println(u);
}
// mybatis和spring整合,整合之后,交给spring管理
sqlSession.close();
}