深入理解参数
传入参数
传递一个参数
将java代码中把数据传入到Mapper文件的SQL语句中.
-
parameterType : 写在Mapper文件中的一个属性, 表示dao接口中方法的参数的数据类型的.
public student selectStudentById(Integer id)
public interface StudentDao { Student selectStudentById(Integer id); }
-
在Mapper文件中增加SQL语句
用 #{ 数据名称 } 来传入一个参数
<select id="selectStudentById" parameterType="java.lang.Integer" resultType="com.bipt.domain.Student"> select id,name,email,age from student where id = #{id} </select>
-
编写测试类
public static void main(String[] args) throws IOException { SqlSession sqlSession = MyBatisUtils.getSqlSession(); StudentDao dao = sqlSession.getMapper(StudentDao.class); Student student = dao.selectStudentById(1003); System.out.println(student); }
结果:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SBssfuQu-1620291075771)(C:\Users\GX\Desktop\学习文档\imags\0ba382cb8bb5fc124911eed02a93d8e.png)]
通过日志我们发现mabatis将Integer类型的1003赋值给了sql语句中的"?"
那我们在mapper文件中增加的parameterType能不能去掉呢?
我们去掉parameterType再试一次~
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-je6HEF0a-1620291075775)(C:\Users\GX\Desktop\学习文档\imags\778d070faf81dfd3e2504b61895dfc5.png)]
通过再试一次能看到,查询也成功了~那是为什么呢?
因为parameterType是dao接口中方法的数据类型, 是java数据类型全限定名称或者是mybatis定义的别名(别名可在mybatis文档中查看到)。
例如: parameterType = “java.lang.Integer”
parameterType = “int”
注意:parameterType不是强制的,MyBatis通过反射机制能够发现接口参数的数据类型。所以没有也可以,一般我们也不写。
简单类型:mybatis把java的基本数据类型和String都叫简单类型。 在mapper文件获取简单类型的一个参数的值,使用#{ 任意字符 }
接口:public Student selectStudentById(Integer id);
mapper: select id,name,email,age from student where id = #{id}
Mybatis是封装的JDBC操作
使用#{}之后,mybatis执行SQL是使用的JDBC中的preparedStatement对象
由mybatis执行下面的代码:
1. mybatis创建connection,preparedStatement对象
String sql = "select id,name,email,age from student where id = ?"
PreparedStatement pst = comm.preparedStatement(sql);
pst.setInt(1,1001);
2. 执行SQL封装为resultType = "com.bipt.domain.Student"这个对象
ResultSet rs = ps.executeQuery();
while(rs.next()){
//从数据库取一行数据,存到java对象的属性中
Student studnet = new Student();
studnet.setId(rs.getInt("id"));
studnet.setName(rs.getString("name"));
studnet.setEmail(rs.getString("email"));
studnet.setAge(rs.getInt("age"));
}
return srudent; // 把他赋给了方法调用的返回值
传递多个参数 -----使用@param(命名参数)
dao接口 :(使用 @param(“参数名”) String name )
public List<Student> selectMulitParam(@param("myname")String name,@param("myage")Integer age);
mapper 文件:
<select id="selectMulitParam" resultType="com.bipt.domain.Student">
select id,name,email,age from student where name=#{myname} or age = #{myage}
</select>
测试:
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<Student> s = dao.selectMulitParam("张飞", 24);
for (Student student : s) {
System.out.println("student"+student);
}
sqlSession.close();
结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gKxH6bNT-1620291075777)(C:\Users\GX\Desktop\学习文档\imags\11f60463a2af49e82e8d8b4a778dcf2.png)]
传递多个参数 ---- 使用对象传参(实际中使用较多)
dao接口:
List<Student> selectMulitStudent(Student student);
Mapper文件:
#{}中的参数为Student类中相应属性的名称
语法规则 : 多个参数,使用对象的属性值,作为参数实际值
使用对象的语法#{属性名,javaType=类型名称,jdbc=数据类型}最完整的语法格式,很少用。
javaType : 值java中的属性类型
jdbcType : 在数据库中的数据类型
例如: #{paraName,javaType=java.lang.String,jdbcType=VARCHAR}
上面的语法我们不用,使用的是简化的方式:
#{属性名} ,javaType和JDBCType的值mybatis反射能获取。不用提供
<select id="selectMulitStudent" resultType="com.bipt.domain.Student">
select id,name,email,age from student where name= #{name} or age = #{age}
</select>
测试文件:
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
Student student = new Student();
student.setAge(24);
student.setName("张飞");
List<Student> students = dao.selectMulitStudent(student);
for (Student student1 : students) {
System.out.println("Student="+student1);
}
sqlSession.close();
传递多个参数 ---- 使用位置传参
参数位置从0开始,引用参数语法为#{arg 位置} ,第一个参数是#{arg0},第二个为#{arg1}… 以此类推
注意:mybatis3.3版本之前用#{0},#{1}表示,3.3版本之后用上方方法进行表示
dao接口:
List<Student> selectMultiPosition(String name,Integer age);
Mapper文件:
<select id="selectMultiPosition" resultType="com.bipt.domain.Student">
select id,name,email,age from student where name=#{arg0} or age = #{arg1}
</select>
测试代码:
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<Student> students = dao.selectMultiPosition("张飞", 24);
for (Student student : students) {
System.out.println("student="+student);
}
sqlSession.close();
结果:
多个参数 ---- 使用Map进行传参
Map 集合可以存储多个值,使用Map向Mapper文件一次传入多个参数。Map集合使用String的Key,Object类型的值存储采纳数。Mapper文件中使用#{key}引用参数。
dao接口:
List<Student> selectMultiByMap(Map<String,Object> map);
Mapper文件:
<select id="selectMultiByMap" resultType="com.bipt.domain.Student">
<!-- 使用的语法是#{Map中的key}-->
select id,name,email,age from student where name=#{myname} or age = #{myage}
</select>
测试代码
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
HashMap<String, Object> student = new HashMap<>();
student.put("myname","张飞");
student.put("myage",24);
List<Student> students = dao.selectMultiByMap(student);
for (Student student1 : students) {
System.out.println("student="+student);
}
sqlSession.close();
结果:
Map传参的缺点:
- #{Key}中的Key参数是在进行方法调用时进行定义的,所以较为随意,不太利于代码的书写
- 在进行方法调用的时候无法看见具体参数有几个,可读性差,给的信息太少了
#与$的区别
#: 占位符,告诉mybatis使用实际的参数值进行代替。并使用PrapareStatement对象执行sql语句,#{…}代替SQL语句中的"?"。这样做通常更安全、更迅速,通常也是首选的做法。一般替换为"="右侧,为列值。
转换为Mybatis执行的是:
String sql = " select id , name , email , age from student where id = ?";
PrepareStatement ps = conn.prepareStatement(sql);
ps.setInt(1,1001);
: 字 符 串 替 换 , 告 诉 m y b a t i s 使 用 :字符串替换,告诉mybatis使用 :字符串替换,告诉mybatis使用包含的“字符串”替换坐在位置。使用Statement对象吧sql语句和${…}的内容链接起来。主要用在替换表明,列名,不同列排序等操作。效率比PreparedStatement低。
String sql = " select id , name , email , age from student where id =" + "1001";
使用占位符替换列名
Dao:
List<Student> selectUser$Order(@Param("colName") String colName);
Mapper文件:
<select id="selectUser$Order" resultType="com.bipt.domain.Student">
select * from student order by ${colName}
</select>
测试代码:
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
List<Student> students = dao.selectUser$Order("id");
for (Student student : students) {
System.out.println("student="+student);
}
sqlSession.close();
结果:
$ 与 # 的区别:
- #使用 ? 在SQL语句中做站位,使用PreparedStatement对象执行SQL,效率高
- #能够避免SQL注入,更安全
- $不适用占位符,是字符串链接方式,使用Statement对象执行sql,效率低
- $有SQL注入的风险,缺乏安全性
- $可以替代表明或列名