MyBatis②CRUD和模糊查询
3、CRUD
3.1、Mapper映射
常用属性
namespace:命名空间,用于绑定接口;select标签:匹配SQL查询语句。CRUD操作分别匹配不同的标签,如果误用可能会报错。id:方法名,要与接口中方法名一致;resultType:返回结果类型,要填写全类名;parameterType:参数类型,一般是pojo类的全类名或基本数据类型。
<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="">
<select id="" resultType="" parameterType="">
/*SQL语句*/
</select>
</mapper>
3.2、CRUD
3.2.1、select
查询的返回值一般为pojo类,增删改的返回值一般为int(受影响行数)或boolean(是否成功)。
Mapper接口
/**
* 根据ID查询用户
*
* @param id 用户ID
* @return 用户
*/
User getUserById(int id);
Mapper.xml
这里传递的参数是基本数据类型,则#{参数值}填写参数名。
<select id="getUserById" resultType="indi.jaywee.pojo.User" parameterType="int">
select *
from mybatis.user
where id = #{id}
</select>
JUnit测试
@Test
public void testGetUserById() {
// 获取SqlSession实例
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 获取Mapper
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 执行方法
User user = mapper.getUserById(2);
System.out.println(user);
// 关闭连接
sqlSession.close();
}
3.2.2、insert
注意:
增删改操作,需要提交事务;- 在
Mapper.xml中,增加操作对应的是insert标签
Mapper接口
/**
* 新增用户
*
* @param user 待新增用户
* @return 受影响行数
*/
int insertUser(User user);
Mapper.xml
这里传入的参数是User,而不是基本数据类型,则#{参数值}填写User类中的属性名。
<insert id="insertUser" parameterType="indi.jaywee.pojo.User">
insert into mybatis.user(name, password)
value (#{name}, #{password})
</insert>
JUnit
@Test
public void testInsertUser() {
// 获取SqlSession实例
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 获取Mapper
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 执行方法
int i = mapper.insertUser(new User("demo", "123456"));
if (i > 0) {
System.out.println("插入" + i + "行数据");
}
// 提交事务!!
sqlSession.commit();
// 关闭连接
sqlSession.close();
}
注意:报错org.apache.ibatis.binding.BindingException: Mapper method 'indi.jaywee.dao.UserMapper.insertUser attempted to return null from a method with a primitive return type (int)。说明Mapper.xml中可能使用了select标签,正确的是使用insert标签。
3.2.3、remove
注意:
增删改操作,需要提交事务;- 在
Mapper.xml中,删除操作对应的是delete标签
Mapper接口
/**
* 通过ID删除用户
*
* @param id 用户ID
* @return 受影响行数
*/
int deleteUserById(int id);
Mapper.xml
这里传递的参数是基本数据类型,则#{参数值}填写参数名。
<delete id="deleteUserById" parameterType="int">
delete from mybatis.user
where id = #{id}
</delete>
JUnit
@Test
public void testDeleteUserById() {
// 获取SqlSession实例
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 获取Mapper
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 执行方法
int i = mapper.deleteUserById(10);
if (i > 0) {
System.out.println("删除" + i + "行数据");
}
// 提交事务!!
sqlSession.commit();
// 关闭连接
sqlSession.close();
}
3.2.4、update
注意:
增删改操作,需要提交事务;- 在
Mapper.xml中,更新操作对应的是update标签
Mapper
/**
* 更新用户
* @param user 用户
* @return 受影响行数
*/
int updateUser(User user);
Mapper.xml
这里传入的参数是User,而不是基本数据类型,则#{参数值}填写User类中的属性名。
<update id="updateUser" parameterType="indi.jaywee.pojo.User">
update mybatis.user
set name=#{name},
password=#{password}
where id = #{id}
</update>
JUnit
@Test
public void testUpdateUser() {
// 获取SqlSession实例
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 获取Mapper
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 执行方法
int i = mapper.updateUser(new User(8, "ppp", "2424"));
if (i > 0) {
System.out.println("更新" + i + "行数据");
}
// 提交事务!!
sqlSession.commit();
// 关闭连接
sqlSession.close();
}
3.3、Map参数的使用
当实体类的属性(数据库中的表的字段)或参数过多时,应当考虑使用Map。
将Map<String,Object>作为方法的参数,以更新用户为例。
Mapper
/**
* 更新用户
* @param map 参数
* @return 受影响行数
*/
int updateUser1(Map<String, Object> map);
Mapper.xml
这里传入的参数是map,则#{参数值}填写map中键值对的Key。
<update id="updateUser1" parameterType="map">
update mybatis.user
set name=#{newName},
password=#{newPassword}
where id = #{id};
</update>
JUnit
注意:map的Key与Mapper.xml中的参数值一致。
@Test
public void testUpdateUser1() {
// 获取SqlSession实例
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 获取Mapper
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map<String, Object> map = new HashMap<>();
map.put("id",1);
map.put("newName","administrator");
map.put("newPassword","admin123");
// 执行方法
int i = mapper.updateUser1(map);
if (i > 0) {
System.out.println("更新" + i + "行数据");
}
// 提交事务!!
sqlSession.commit();
// 关闭连接
sqlSession.close();
}
3.4、再次说明
增删改操作,需要提交事务;- 在
Mapper.xml中,CRUD操作对应的不同标签; - 接口方法的参数问题
- 参数是基本数据类型:在
Mapper.xml中的#{参数值}填写参数列表中的参数名; - 参数是POJO类:在
Mapper.xml中的#{参数值}填写pojo类的属性名; - 参数是map:在
Mapper.xml中的#{参数值}填写map中键值对的Key。
- 参数是基本数据类型:在
4、模糊查询
只要涉及到模糊查询,就离不开SQL注入问题。
4.1、SQL注入问题
SQL注入攻击是指恶意拼接SQL作为参数,传递给Web服务器,进而传给数据库服务器以执行数据库命令,获取数据库的信息以及提权。
举例:登录需要验证用户名和密码,SQL语句和参数拼接:
"SELECT * FROM user WHERE name = '"
+ name
+ "' AND psw = '"
+ psw + "'";
SQL注入:
String name = "' or '1=1"
String psw = "' or '1=1"
name和psw被恶意注入,导致SQL语句为
SELECT *
FROM user
WHERE `name` = '' or '1=1'
AND `psw` = '' or '1=1'
此SQL语句相当于SELECT * FROM user,即不需要name和psw,通过SQL注入查出了所有用户。
4.2、解决SQL注入问题
编写SQL时,如果采取SQL和参数拼接的方式,很容易被SQL注入。
如何解决呢?使用占位符?来替代参数部分就可以了。
4.3、JDBC解决SQL注入问题
JDBC编写SQL的2种方式:
-
拼接字符串:会将接收到的参数内容不加任何修饰符,拼接在 SQL 中。会引起SQL注入问题。
例子:可以参照上面的例子。
-
占位符:接收到的参数中如果有特殊符号,将会被转义。可以解决SQL注入问题。
例子:
【' or '1=1】会被转义为【\' or \'1=1】
4.4、MyBatis解决SQL注入问题
MyBatis编写SQL语句的参数的2种方式:
- ${value}:表示拼接字符串。会引起SQL注入问题。
- #{value}:在预处理时,用占位符
?来替代参数部分。可以解决SQL注入问题。
4.5、模糊查询举例
Mapper
/**
* 模糊查询用户
* @param str 用户名的一部分
* @return 用户
*/
List<User> getUserLikeStr(String str);
Mapper.xml
<select id="getUserLikeStr" parameterType="String" resultType="indi.jaywee.pojo.User">
select * from mybatis.user
where name like concat('%',#{str},'%');-- 防止SQL注入
</select>
JUnit
分别用拼接字符串和常规填写的参数,调用接口方法,查看结果。
@Test
public void getUserLike() {
// 获取SqlSession实例
SqlSession sqlSession = MyBatisUtils.getSqlSession();
// 获取Mapper
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 执行方法:尝试SQL注入
List<User> users = mapper.getUserLikeStr("' or '1=1"); // SQL注入无法
System.out.println("users");
for (User user : users) {
System.out.println(user);
}
System.out.println("-------------------------");
// 执行方法:正常填写参数
List<User> users1 = mapper.getUserLikeStr("d"); // SQL注入无法
System.out.println("users1");
for (User user1 : users1) {
System.out.println(user1);
}
// 关闭连接
sqlSession.close();
}
运行结果
可以看出:尝试SQL注入失败,一个用户都没查出来,有效防止了SQL注入。


浙公网安备 33010602011771号