点滴记载,点滴进步,愿自己更上一层楼。
废话不多说,进入主题。
项目还是在上篇 mybatis学习之路----非代理方式的增删改查用法 基础之上进行开发
一个简单的模糊查询sql。
SELECT * FROM t_user WHERE username LIKE '%黄%'
根据以上sql,查询结果。
像这样的用到模糊查询的地方很多。下面来介绍mybatis的三种方式。
1 使用${}代替#{}接收参数。此种方式有sql注入风险。关于sql注入在下面会有实例演示。
2 使用mysql的concat语法给传入参数拼%号。即concat('%',param,'%').
3 直接接收带%号的参数进行查询 此种方式存在硬编码,不推荐。
在user.xml中添加如下信息。也就是上面三种方法的实现
/**
* 模糊查询第一种方式
* @param username 参数
* @return
*/
List findUserByName01(String username);
/**
* 模糊查询第二种方式 使用concat拼接查询命令
* @param username 参数
* @return
*/
List findUserByName02(String username);
/**
* 模糊查询第三种方式 直接接收拼好的字符串
* @param username 参数
* @return
*/
List findUserByName03(String username);
/**
* 模糊查询第一种方式
* @param username 参数
* @return
*/
public List findUserByName01(String username) {
String statementId = "test.findUserByName1";
return findUserList(statementId,username);
}
/**
* 模糊查询第二种方式 使用concat拼接查询命令
* @param username 参数
* @return
*/
public List findUserByName02(String username) {
String statementId = "test.findUserByName2";
return findUserList(statementId,username);
}
/**
* 模糊查询第三种方式 直接接收拼好的字符串
* @param username 参数
* @return
*/
public List findUserByName03(String username) {
String statementId = "test.findUserByName3";
return findUserList(statementId,username);
}
/**
* 由于都需要三种方式查询除了两个地方不一样其他的处理都相同,此处抽取相同部分
* @param statementId
* @param param
* @return
*/
private List findUserList(String statementId, Object param){
SqlSession sqlSession = null;
try {
sqlSession = SqlsessionUtil.getSqlSession();
return sqlSession.selectList(statementId,param);
} catch (Exception e) {
e.printStackTrace();
} finally {
SqlsessionUtil.closeSession(sqlSession);
}
return new ArrayList();
}
UserDaoTest.java 中添加对应的测试代码。
@Test
public void findUserByName01() throws Exception {
List users = dao.findUserByName01("黄");
for(User user:users){
System.out.println("findUserByName01:" + user);
}
}
@Test
public void findUserByName02() throws Exception {
List users = dao.findUserByName02("黄");
for(User user:users){
System.out.println("findUserByName02:" + user);
}
}
@Test
public void findUserByName03() throws Exception {
// 此种方式存在硬编码,不推荐
List users = dao.findUserByName03("%黄%");
for(User user:users){
System.out.println("findUserByName03:" + user);
}
}
三种方法测试结果。
到此,三种实现模糊查询方式示例完毕。
上面写到使用${}来接收参数的时候,说有sql注入的风险。那么什么是sql注入呢?
sql注入传送门
其实简单来说,传入的参数中有一段有风险的并且可执行sql代码。如果没有规避掉,可能是系统直接瘫痪。下面进行演示。
测试代码findUserByName01使用的是${}来接收参数,即
@Test
public void findUserByName01() throws Exception {
List users = dao.findUserByName01("黄");
for(User user:users){
System.out.println("findUserByName01:" + user);
}
}
这段代码怎么sql注入呢?
如果将参数修改成带有可执行sql的参数即("4' or username in (select username from t_user) or username like '3")
其中有了 or username in (select username from t_user) 这个条件,sql执行结果就是全表数据显示。
修改后带有sql注入的java代码。
@Test
public void findUserByName01() throws Exception {
List users = dao.findUserByName01("黄' or username in (select username from t_user) or username like '3");
for(User user:users){
System.out.println("findUserByName01:" + user);
}
}
执行结果。
可以看到全表的数据都显示出来了。
想想如果注入的sql是删除语句的话。。。。。。
但是同样的带有sql注入代码的参数,放到findUserByName02中,结果大不相同。
@Test
public void findUserByName02() throws Exception {
List users = dao.findUserByName02("黄' or username in (select username from t_user) or username like '3");
for(User user:users){
System.out.println("findUserByName02:" + user);
}
}
这就是说为什么,不提倡${}的方式来写模糊查询,而推荐使用concat拼接方式来进行模糊查询了。