mybatis
第四章 Mybatis输入类型和结果类型
第1章
1.1 parameterType****(输入类型)
1.1.1 传递简单类型
参考第一天内容。
使用#{}占位符,或者${}进行Sql拼接。
1.1.2 传递Pojo对象
参考第一天的内容。
{}或者${}括号中的值为Pojo属性名称。
1.1.3 传递Pojo包装对象
包装对象:Pojo类中的一个属性是另外一个Pojo。
为什么使用包装对象?
在平时的开发中,不一定就是单纯的对一个实体进行增删改查,例如完成用户信息的综合查询,有时需要传入查询条件很复杂,可能包括用户信息、关联表的其它信息等。针对这种需求,在Mybatis中我们可以使用自定义的包装类型的Pojo,在包装类型的Pojo中将复杂的查询条件包装进去。
功能需求:根据用户名模糊查询用户信息,查询条件放到QueryVo的user属性中。
1.1.3.1 编写QueryVo
|
public class QueryVo {
// 包含其他的pojo
privateUser user;
public User getUser() {
return user;
}
public voidsetUser(User user) {
this.user= user;
}
}
|
1.1.3.2 Sql语句
SELECT * FROM USER WHERE USERNAME LIKE '%王%'
1.1.3.3 Mapper.xml文件
在UserMapper.xml中配置Sql,如下图。
[图片上传失败...(image-da9f7e-1594741154724)]
1.1.3.4 Mapper接口
在UserMapper接口中添加方法,如下图:
[图片上传失败...(image-1b59f5-1594741154724)]
1.1.3.5 测试方法
在UserMapeprTest增加测试方法,如下:
|
@Test
public void testQueryUserByQueryVo() {
SqlSession sqlSession= this.sqlSessionFactory.openSession();
UserMapper userMapper= sqlSession.getMapper(UserMapper.class);
// 使用userMapper执行查询,使用包装对象
QueryVo queryVo= new QueryVo();
// 设置user条件
User user= new User();
user.setUsername("%王%");
// 设置到包装对象中
queryVo.setUser(user);
// 执行查询
List<User> list= userMapper.queryUserByQueryVo(queryVo);
for(User u: list) {
System.out.println(u);
}
sqlSession.close();
}
|
1.1.3.6 效果
测试结果如下图:
[图片上传失败...(image-fce264-1594741154724)]
1.2 resultType(输出结果类型)
1.2.1 输出简单类型
功能需求:查询用户表数据条数
Sql语句:SELECT count(*) FROM user
1.2.1.1 M****apper.xml文件
在UserMapper.xml中配置Sql,如下图:
[图片上传失败...(image-5d5cba-1594741154724)]
1.2.1.2 M****apper接口
在UserMapper添加方法,如下图:
[图片上传失败...(image-e7f492-1594741154723)]
1.2.1.3 测试方法
在UserMapeprTest增加测试方法,如下:
|
@Test
public void testQueryUserCount() {
SqlSession sqlSession= this.sqlSessionFactory.openSession();
UserMapper userMapper= sqlSession.getMapper(UserMapper.class);
int count= userMapper.queryUserCount();
System.out.println(count);
sqlSession.close();
}
|
1.2.1.4 效果
测试结果如下图:
[图片上传失败...(image-8a347b-1594741154723)]
注意:输出简单类型必须查询出来的结果集有一条记录,最终将第一个字段的值转换为输出类型
1.2.2 输出Pojo对象
参考第一天内容
1.2.3 输出Pojo列表
参考第一天内容
1.3 resultMap
resultType可以指定将查询结果映射为Pojo,但需要Pojo的属性名和Sql查询的列名一致方可映射成功。
如果Sql查询字段名和Pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到Pojo对象中。
功能需求:查询订单表orders的所有数据
Sql语句:SELECT id, user_id, number, createtime, note FROM orders
1.3.1 创建数据表、初始化测试数据、****声明****P****ojo对象
创建订单表并查询订单表的全部数据,Sql语句如下:
|
-- Table structure for orders
DROP TABLE IF EXISTS orders
;
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=6 DEFAULT CHARSET=utf8;
-- Records of orders
INSERT INTO orders
VALUES ('3', '3', '1000010', '2015-02-04 13:22:35', null);
INSERT INTO orders
VALUES ('4', '3', '1000011', '2015-02-03 13:22:41', null);
INSERT INTO orders
VALUES ('5', '4', '1000012', '2015-02-12 16:13:23', null);
|
Orders对象:
|
public class Orders {
// 订单id
private int id;
// 用户id
privateInteger userId;
// 订单号
privateString number;
// 订单创建时间
privateDate createtime;
// 备注
privateString note;
get/set…
}
|
1.3.2 M****apper.xml文件
创建OrdersMapper.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.itheima.mybatis.mapper.OrdersMapper">
<select id="queryOrdersAll" resultType="orders">
SELECT id, user_id,
number,
createtime, note FROM orders
</select>
</mapper>
|
1.3.3 Mapper接口
编写接口如下:
|
public interface OrdersMapper {
/**
-
查询所有订单
-
@return
*/
List<Orders> queryOrdersAll();
}
|
1.3.4 测试方法
编写测试方法OrdersMapperTest如下:
|
public class OrdersMapperTest {
privateSqlSessionFactory sqlSessionFactory;
@Before
public voidinit() throws Exception {
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
this.sqlSessionFactory= new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testQueryAll() {
// 获取sqlSession
SqlSession sqlSession= this.sqlSessionFactory.openSession();
// 获取OrderMapper
OrdersMapper orderMapper= sqlSession.getMapper(OrdersMapper.class);
// 执行查询
List<Orders> list= orderMapper.queryOrdersAll();
for(Orders order: list) {
System.out.println(order);
}
sqlSession.close();
}
}
|
1.3.5 效果
测试效果如下图:
[图片上传失败...(image-325f71-1594741154720)]
发现userId为null
解决方案:使用resultMap
1.3.6 使用resultMap
由于上边的mapper.xml中Sql查询列(user_id)和Order类属性(userId)不一致,所以查询结果不能映射到Pojo中。
需要定义resultMap,把orderResultMap将Sql查询列(user_id)和Order类属性(userId)对应起来
改造OrderMapper.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.itheima.mybatis.mapper.OrdersMapper">
<resultMap type="orders" 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="queryOrdersAll" resultMap="orderResultMap">
SELECT id, user_id,
number,
createtime, note FROM orders
</select>
</mapper>
|
1.3.7 效果
只需要修改Mapper.xml就可以了,再次测试结果如下:
[图片上传失败...(image-7df7e5-1594741154719)]
第1章 Mybatis映射文件的SQL深入
Mybatis的映射文件中,前面我们的SQL都是比较简单的,有些时候业务逻辑复杂时,我们的SQL是动态变化的,此时在前面的学习中我们的SQL就不能满足要求了。
参考的官方文档,描述如下:
[图片上传失败...(image-c85a0f-1594741219533)]
通过Mybatis提供的各种标签方法实现动态拼接Sql。
功能需求:根据性别和名字查询用户
Sql语句:
SELECT id, username, birthday, sex, address FROM user
WHERE sex = 1 AND username LIKE '%张%'
1.1 If****标签
1.1.1 Mapper.xml文件
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>
|
1.1.2 Mapper接口
编写Mapper接口,如下图:
[图片上传失败...(image-c94ff7-1594741219533)]
1.1.3 测试方法
在UserMapperTest添加测试方法,如下:
|
@Test
public void testQueryUserByWhere() {
SqlSession sqlSession= this.sqlSessionFactory.openSession();
UserMapper userMapper= sqlSession.getMapper(UserMapper.class);
// 使用userMapper执行根据条件查询用户
User user= new User();
user.setSex("1");
user.setUsername("%王%");
List<User> list= userMapper.queryUserByWhere(user);
for(User u: list) {
System.out.println(u);
}
sqlSession.close();
}
|
1.1.4 效果
测试效果如下图:
[图片上传失败...(image-99183d-1594741219533)]
如果注释掉 user.setSex("1"),测试结果如下图:
[图片上传失败...(image-f6a548-1594741219533)]
测试结果二很显然不合理。
按照之前所学的,要解决这个问题,需要编写多个Sql,查询条件越多,需要编写的Sql就更多了,显然这样是不靠谱的。
解决方案,使用动态Sql的if标签
1.1.5 使用if标签
改造UserMapper.xml,如下:
|
<select id="queryUserByWhere" parameterType="user" resultType="user">
SELECT id, username, birthday, sex, address FROM user
WHERE 1=1
<if test="sex != null and sex != ''">
AND sex = #{sex}
</if>
<if test="username != null and username != ''">
AND username LIKE
{username}
</if>
</select>
|
注意字符串类型的数据需要做不等于空字符串校验。
1.1.6 效果
[图片上传失败...(image-ae7b8a-1594741219533)]
如上图所示,测试OK
1.2 W****here标签
上面的Sql还有where 1=1 这样的语句,很麻烦
可以使用where标签进行改造
改造UserMapper.xml,如下
|
<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>
|
1.2.1 效果
测试效果如下图:
[图片上传失败...(image-66c06-1594741219533)]
1.3 S****ql片段
Sql中可将重复的Sql提取出来,使用时用include引用即可,最终达到Sql重用的目的。
把上面例子中的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>
<sql id="userFields">
id, username, birthday, sex, address
</sql>
|
如果要使用别的Mapper.xml配置的Sql片段,可以在refid前面加上对应的Mapper.xml的namespace,如下
|
SELECT <include refid="com.itheima.mybatis.mapper.OrdersMapper.userFields" /> FROM user
|
1.4 foreach标签
向Sql传递List,Mybatis使用foreach解析。
功能需求:根据多个id查询用户信息
查询Sql语句:
SELECT * FROM user WHERE id IN (1,10,24)
1.4.1 Mapper.xml文件
UserMapper.xml添加Sql,如下:
|
<select id="queryUserByIds" parameterType="list" resultType="user">
SELECT * FROM user
<where>
<foreach collection="list" item="item" open="id IN (" close=")"
separator=",">
{item}
</foreach>
</where>
</select>
|
测试方法如下图:
|
@Test
public void testQueryUserByIds() {
SqlSession sqlSession= this.sqlSessionFactory.openSession();
UserMapper userMapper= sqlSession.getMapper(UserMapper.class);
// 使用userMapper执行根据条件查询用户
List<Integer> ids= new ArrayList<Integer>();
ids.add(2);
ids.add(3);
ids.add(4);
List<User> list= userMapper.queryUserByIds(ids);
for(User u: list) {
System.out.println(u);
}
sqlSession.close();
}
|
1.4.2 效果
测试效果如下图:
[图片上传失败...(image-a5840a-1594741219532)]