MyBatis获取参数值

171 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第7天,点击查看活动详情

MyBatis获取参数值的两种方式: ${}#{}

${}的本质就是字符串拼接,#{}的本质就是占位符赋值

${}使用字符串拼接的方式拼接sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单引

号;但是#{}使用占位符赋值的方式拼接sql,此时为字符串类型或日期类型的字段进行赋值时,

可以自动添加单引号

推荐使用#{},避免SQL注入

mapper接口的方法(可能有参数,毕竟是方法)直接对应的是映射文件的SQL语句。我们现在要做的就是在映射文件中,通过指定的方式来获取对应的方法的参数,然后拼接到SQL语句中。这就是本章节的目的。

1.单个字面量类型的参数

若mapper接口中的方法参数为单个的字面量类型

此时可以使用{}和#{}以任意的名称获取参数的值,注意{}需要手动加单引号

字面量和变量是相对应的,如 int a= 1;这里1是字面量,你看到的是什么就是什么,变量a具体值要看字面量。

字符串,基本数据类型以及所对应的包装类都是字面量。

mapper接口

public interface UserMapper {

    //根据用户名查询用户信息
    User getUserByUsername(String username);

}

映射文件

当你写完**select * from t_user where username =**时,你会发现后面不知道怎么写,你可以试着在等于号后面写上#{username},你会发现其实可以运行了。

如果你把#{username}改成#{abc},你会发现程序居然可以运行,所以可知mybatis底层代码它参数值时,并不知道你是用username还是abc还赋值的。我们知道这件事后,建议还是不要用这么随意的名字,你mapper接口方法参数是username,你映射文件还是用#{username},见名知意最好。

时,你要给它带上单引号,不让mybatis拼接SQL语句的时候,会把{}时,你要给它带上单引号,不让mybatis拼接SQL语句的时候,会把{}带来的值当成数据库字段,从而程序报错。你不加单引号就会select * from t_user where username = admin,你加了单引号就会select * from t_user where username = 'admin'

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.mybatis.mapper.UserMapper">

    <!--User getUserByUsername(String username)-->
    <select id="getUserByUsername" resultType="User">
        <!--select * from t_user where username = #{abc}-->
        select * from t_user where username = #{username}
        <!--select * from t_user where username = '${username}'-->
    </select>
</mapper>

测试类(记得复制以前生成sqlsession对象的工具类)

public class ParameterTest {

    @Test
    public void testGetUserByUsername() {
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.getUserByUsername("admin");
        System.out.println(user);
    }

}

2.多个字面量类型的参数

mapper接口

public interface UserMapper {

    //验证登录
    User checkLogin(String username,String password);

}

映射文件

这里和第一个例子不同的地方在于,现在有两个参数,你可以先试着这样写select * from t_user where username = #{user} and password = #{password} ,然后会报错。Mybatis会告诉你多个参数时,正确的写法如下:

Available parameters are [arg1, arg0, param1, param2]

原因是多个参数时,Mybatis会将参数放在map集合,以两种方式存储数据

1.以arg0,arg1,arg2...为键,以参数为值

2.以param1,param2,param3...为键,以参数为值

因此,只需通过#{}和${}访问map集合的键,就可以获取相对应的值。

在本例的mapper接口中方法为User checkLogin(String username,String password),所以param1和arg0这两个键的值为username保存的值,param2和arg1这两个键的值为password保存的值。至于你想用param或者arg来作为键,随便你。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.mybatis.mapper.UserMapper">

    <!--User checkLogin(String username,String password)-->
    <select id="checkLogin" resultType="User">
        <!--select * from t_user where username = #{user} and password = #{password} 参数错误写法-->
        <!--select * from t_user where username = #{arg0} and password = #{arg1}-->
        select * from t_user where username = #{param1} and password = #{param2}
        <!--select * from t_user where username = '${param1}' and password = '${param2}'-->
    </select>
</mapper>

测试类

@Test
public void testcheckLogin() {
    SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    User user = mapper.checkLogin("admin","123456");
    System.out.println(user);
}

3.map集合类型的参数

上面的例子我们知道,多个参数的时候,mybatis会把它们放到一个map集合。

那我们可以自己定义map集合吗? 可以的,自己定义了map集合后,映射文件里面就不用写arg0或者param1之类的mybatis提供的键名,而是用我们自己定义的键名

mapper接口

public interface UserMapper {

    //验证登录
    User checkLogin(String username,String password);

    //验证登录(用map集合作为参数)
    User checkLoginByMap(Map<String,Object> map);
}

映射文件

<!--User checkLoginByMap(Map<String,Object> map);-->
<select id="checkLoginByMap" resultType="User">
    select * from t_user where username = #{username} and password = #{password}
</select>

测试类

@Test
public void testCheckLoginByMap() {
    SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    Map<String,Object> map = new HashMap<>();
    map.put("username","admin");
    map.put("password","123456");
    User user = mapper.checkLoginByMap(map);
    System.out.println(user);
}

4.实体类型的参数

这部分的目的是,怎么将实体类里面的各个属性的值拼接到SQL语句里面。

若mapper接口中的方法参数为实体类对象时

此时可以使用{}和#{},通过访问实体类对象中的**属性名**获取属性值,注意{}需要手动加单引号

注意:属性名和成员变量没有关系,只跟get和set有关系,把get和set去掉,其余部分首字母变小写的结果就是属性名,如getUsername(),去掉get,U变u,得到username,username就是属性名

mapper接口

public interface UserMapper {

    //添加用户信息
    void insertUser(User user);
}

映射文件

<!--void insertUser(User user);-->
<insert id="insertUser">
    insert into t_user values(null,#{username},#{password},#{age},#{gender},#{email})
</insert>

测试类

public void testInsertUser() {
    SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    User user = new User(null,"root","123456",33,"女","123@qq.com");
    mapper.insertUser(user);
}

5.使用@Param标识的参数

可以通过 @Param注解标识mapper接口中的方法参数

此时,会将这些参数放在map集合中,以两种方式存储

1.@Param注解的value属性值为键,以参数为值;

2.param1,param2...为键,以参数为值;

只需要通过${}和#{}访问map集合的键就可以获取相对应的值,

注意${}需要手动加单引号

mapper接口

//验证登录(使用@Param)
User checkLoginByParam(@Param("username") String username, @Param("password") String password);

映射文件

<!--User checkLoginByParam(@Param("username") String username, @Param("password") String password);-->
<select id="checkLoginByParam" resultType="User">
    select * from t_user where username = #{username} and password = #{password}
</select>

测试类

@Test
public void testcheckLoginByParam() {
    SqlSession sqlSession = SqlSessionUtil.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    User user = mapper.checkLogin("admin","123456");
    System.out.println(user);
}

总结

建议大家分成两种方式来记即可,一种是实体类,一种是单个参数或者多个参数。如果传递的是实体类,那么你就获取实体类属性就行,如果是其他参数类型,你就给它们都标注上@Param注解。