文章目录
1. Mapper.xml与Mapper接口中返回值的对应关系
- 在Mapper.xml文件中,虽然这条sql语句查询出来的结果可能会有多条,但是这里的resuleType依然写Student就行,不用写List
<select id="findStudentByUsername" parameterType="String" resultType="cn.ykf.domain.Student">
SELECT * FROM student WHERE username LIKE #{key};
</select>
- 在不使用Mapper接口的情况下,应该使用selectList()方法,该方法会自动将查询的多条记录封装成对应类型的List集合
List<Student> students = sqlSession.selectList("test.findStudentByUsername", "%测试%");
- 如果使用Mapper接口,那么在Mapper接口中应该这样定义对应的方法,这里的返回值应该定义为List,那么调用的时候就会返回一个封装了多条Student的集合
/**
* 根据用户名模糊查询
*
* @param key 用户名模糊查询关键字
* @return 全部符合条件的Student集合
*/
List<Student> findStudentByUsername(String key);
- 如果像上面那个定义sql语句的话,调用的时候应该是这样的。就是说传参的时候需要自己在参数前后加上’%'
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List<Student> students = mapper.findStudentByUsername("%测试%");
- 如果想传参的时候只传入关键字,那么就可以将sql语句修改为
<select id="findStudentByUsername" parameterType="String" resultType="cn.ykf.domain.Student">
SELECT * FROM student WHERE username LIKE "%"#{key}"%";
</select>
或者
<select id="findStudentByUsername" parameterType="String" resultType="cn.ykf.domain.Student">
SELECT * FROM student WHERE username LIKE '%${value}%';
</select>
-
推荐第一种方案,因为第二种方案的 {value},不能乱写,否则会报错
- 还有,使用第一种方案的时候,参数应该写 “%”#{key}"%"。就是 %两侧需要加上双引号,不能单引号。因为#{…}解析成sql语句时候,会在变量外侧自动加单引号,所以这里 % 需要使用双引号,不能使用单引号,不然会查不到任何结果
- 第一种方案sql的参数名称可以随便写
-
参考资料
2. 关于增删查改的返回值
- 只有查询<select></select>标签才有resultType属性,其他增删改<insert></insert>、<delete></delete>、<update></update>都没有resultType属性,默认返回影响条数,int类型
3. 关于修改数据时的坑
3.1. 修改时参数为NULL覆盖了原本存在的字段值
- 首先在Mapper.xml中定义的修改sql语句如下,该sql语句会修改记录中除去id的所有字段值
<update id="updateStudent" parameterType="cn.ykf.domain.Student">
UPDATE student SET username = #{username}, password = #{password}, birthday = #{birthday}, chinese = #{chinese}, math = #{math}, english = #{english} WHERE id = #{id}
</update>
- 然后有以下测试代码,其中创建一个id为5,只有username和password属性不为空的Student对象,然后使用该对象作为参数进行修改
@Test
public void testUpdateStudent() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
// 测试数据,如果对象只有一个属性被赋值,那么写入数据库后,数据库中原本有值的字段是否会变成NULL?
Student stu = new Student();
stu.setId(5);
stu.setUsername("test");
stu.setPassword("test");
int flag = mapper.updateStudent(stu);
// 提交事务
sqlSession.commit();
System.out.println(flag);
// 释放资源
MybatisUtils.close(sqlSession);
}
- 查看日志,传入方法的参数中含有NULL
- 原本的数据库中id为5的记录如下图
- 修改结束后,该记录变为
- - 结论
- 在修改数据时,如果sql语句修改了多个字段,那么应该要小心传入参数中某个属性为NULL,避免将数据库中某条记录原本存在的值更改为NULL
3.2. 传入不存在的id值
- 如果将上面代码中的测试数据的id改为一个数据库中不存在的值,比如
stu.setId(1000);
,那么会发生什么? - 经过测试发现,如果传入一个不存在的id值,那么在数据库中找不到对应的记录存在,就不会发生修改,因此不会对数据库中的数据造成影响
3.3. 修改/删除/插入记录时调用错方法
- 假如我们想要更新某一条记录,在Mapper.xml文件中定义的sql语句是正确的,但是在代码中,我们不小心调用错了方法,会发生什么?比如下列代码
<mapper namespace="test">
<!-- 修改 -->
<update id="updateStudent" parameterType="cn.ykf.domain.Student">
UPDATE student SET username = #{username}, password = #{password}, birthday = #{birthday}, chinese = #{chinese}, math = #{math}, english = #{english} WHERE id = #{id}
</update>
</mapper>
@Test
public void testUpdateStudent() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
Student stu = new Student();
stu.setId(5);
stu.setUsername("test");
stu.setPassword("test");
// 比如在这里想要修改数据,结果调用了delete()或者insert()
int flag = sqlSession.delete("test.updateStudent", stu);
// 提交事务
sqlSession.commit();
System.out.println(flag);
// 释放资源
MybatisUtils.close(sqlSession);
}
- 在上面代码中,我们想要修改id为5的记录,本来应该使用update(),但是由于我们手误,不小心使用了delete()或者insert()。点击运行后,我们很惊奇地发现,程序没有报错,而且查看数据库后发现,数据修改成功了。为什么?
- 修改前
- 修改后
- 分析
- 查看Mybatis源码中的org.apache.ibatis.session.defaults.DefaultSqlSession
- 发现里面有这么一段代码,其中的insert()和delete()方法最后都是调用了update()。所以虽然我们在代码中调用了delete()/insert()来进行update操作,但是最后Mybatis都是使用update()来更新数据的,所以并不影响
public int insert(String statement) { return insert(statement, null); } public int insert(String statement, Object parameter) { return update(statement, parameter); } public int update(String statement) { return update(statement, null); } public int update(String statement, Object parameter) { try { dirty = true; MappedStatement ms = configuration.getMappedStatement(statement); return executor.update(ms, wrapCollection(parameter)); } catch (Exception e) { throw ExceptionFactory.wrapException("Error updating database. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } } public int delete(String statement) { return update(statement, null); } public int delete(String statement, Object parameter) { return update(statement, parameter); }
- 参考资料