mybatis深入理解参数

深入理解参数

传入参数

传递一个参数

将java代码中把数据传入到Mapper文件的SQL语句中.

  1. parameterType : 写在Mapper文件中的一个属性, 表示dao接口中方法的参数的数据类型的.

    public student selectStudentById(Integer id)

    public interface StudentDao {
        Student selectStudentById(Integer id);
    }
    
  2. 在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>
    
  3. 编写测试类

    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传参的缺点:

  1. #{Key}中的Key参数是在进行方法调用时进行定义的,所以较为随意,不太利于代码的书写
  2. 在进行方法调用的时候无法看见具体参数有几个,可读性差,给的信息太少了
#与$的区别

#: 占位符,告诉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();

结果:
在这里插入图片描述

$ 与 # 的区别:

  1. #使用 ? 在SQL语句中做站位,使用PreparedStatement对象执行SQL,效率高
  2. #能够避免SQL注入,更安全
  3. $不适用占位符,是字符串链接方式,使用Statement对象执行sql,效率低
  4. $有SQL注入的风险,缺乏安全性
  5. $可以替代表明或列名
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值