首先我们来回顾一下上一篇的一些内容,上一篇我们通过一个小案例演示了一下利用xml文件进行增删改查的 操作,总结了一下操作的步骤:
-
导入所需要的包(数据库连接的包,mybatis的包)
-
添加一个mybatis-config.xml文件
-
编写一个dao类,在类的方法内获取SqlSession对象
-
确定自己需要执行的操作,调用SqlSession内相应的方法
-
补充一个mapper.xml的配置文件,增加所需的sql语句
>>>>昨天的mapper内的sql语句我们是在刚开始就已经给定了的 ,那么如果我们的需求改变了,不是查询我们给的sql语句,那么我们就需要重新更改sql,显然这样的问题就是因为我们在编写mapper.xml文件的时候将sql的值固定了,那么我们可不可以按照自己的意愿去传递这个值呢?答案是肯定的,今天我们的主要内容就是这个:如何在操作SQL语句执行时携带动态的信息?
增删改查都有两个重载的方法:我们昨天使用的就是这些方法的第一个方式,只是传递了一个sql语句的id,而没有传递参数,想要动态的传递参数就要就用后面的这个参数了,使用这个参数需要注意一下几点:
我们的sql语句必须使用特殊格式的sql语句,比如给定一个学生的学号让你查询这个学生的信息,那么我们的sql语句应该这样写:SELECT SNAME,SSEX,SAGE FROM STUDENTS WHERE SID = #{SID},很容易就可以发现这个参数位置利用了特殊的形式来代替而不是问号。
如果只有一个参数需要赋值,那么这个#{},井号花括号中的值可以随意写,建议和POJO的属性名一致或者和传递的Map集合的键相同。
如果不是只有一个参数需要赋值,那么#{},井号花括号中的值要和POJO的属性名字一致或者和传递的Map集合的键相同,否则无法匹配赋值。
我们就一些简单的例子来看一看:
mybatis-config.xml的信息:
小例子 A❌查询指定学生的信息:(主要代码如下)
小例子 B❌修改指定学生的性别:(主要代码如下)
看了上面的两个小例子之后我们来做个简单的说明:#{}其实是预编译处理,我们都知道,我们在使用PreparedStatement的时候,我们传递的sql是用?问号来作为参数的占位符的 ,其实MyBatis在处理#{ }时,它会将sql中的#{ }替换为?,然后调用PreparedStatement的setXxx方法来赋值,我们想想既然这样的话,那么每一个?问号,可以赋值为对应类型的值,就传入字符串而言,会在值两边加上单引号。使之成为一个真正可行的sql语句。#{}可以避免SQL注入。
既然如此我们考虑,如果我们想要实现按照学号排序,是升序还是降序我们可以随意指定,那么我们就需要设置一个参数,是用来给这个排序方式赋值的,那么现在如何实现呢,可以使用#{}吗?就这个sql语句来说select * from student order by id ?如果我们使用#{flag},传递的字符串是asc那么这条语句select * from student order by id 'asc',显然这条语句是不合法的,我们想要的是select * from student order by id asc。这是就是要使用${},那么我们先来看看它的作用:是字符串替换(传入参数是什么样就原封不动的替换成什么样)即,在处理是字符串替换,${}被替换成一模一样的字符,传入的数据不会加两边加上单引号。可能会导致SQL注入。
小例子 C❌对所有学生按学号排序:(主要代码如下)
至此两种参数的传递方式#{} 和 ${} 已经结束了。粗略的总结一下:
#{}:表示类型和值 ,通常用来做条件 /列的值。${}:表示的就是普通字串,通常是表名/列名/关键字,注意产生SQL注入的问题。
补充一个小知识,我们每次都写获得SqlSession对象的方法是不是特别的多,这里封装一下这些语句(代码如下):
package util;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;/** * 这个类是一个小工具,为了封装每个方法获取SqlSession时的诸多步骤的 */public class MySqlSession { // 官方建议一个SqlSession的生命周期是method scope/request scope。 // 而SqlSessionFactory是单例的。 // 这里的封装仅作参考 // SqlSessionFactory的openSession()是有参数的,所以为了可以传递参数构建对象,给个重载方法 // 我们用SqlSessionFactory作为属性,同时单例的只有一份。 static { factory = new SqlSessionFactoryBuilder().build(Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatis-config.xml")); } private static SqlSessionFactory factory; public static SqlSession getSqlSession() { return factory.openSession(false); } public static SqlSession getSqlSession(boolean b) { return factory.openSession(b); }}
使用方式(代码如下):
public Map selectMap (int sid) { try (SqlSession sqlSession = MySqlSession.getSqlSession(true)) { return sqlSession.selectOne("selectMap",sid); }}
<select id="selectMap" resultType="hashmap"> select * from students where sid = #{sid}select>
<欢迎大家指正错误,完善细节>