MyBatis - 06 - MyBatis获取参数值的两种方式(重要)

1、回顾JDBC原生的获取参数值的方式

  • 字符串拼接
  • 占位符拼接
    @Test
    public void testJDBC() throws SQLException, ClassNotFoundException {
        String username = "rqs";
        Class.forName("");
        Connection connection = DriverManager.getConnection("", "", "");
        // 1. 字符串拼接 ->获得预编译对象 -》sql注入问题
        PreparedStatement preparedStatement = connection.prepareStatement("select * from t_user where username = '" + username + "'");

        // 2. 占位符 可以避免sql注入问题
        PreparedStatement ps2 = connection.prepareStatement("select * from t_user where username = ?");
        ps2.setString(1, username);
    }

2、MyBatis获取参数值的两种方式

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

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

${}使用字符串拼接的方式拼接sql,可能会造成sql注入,另外为字符串类型或日期类型的字段进行赋值时,需要手动加单引号;
#{}使用占位符赋值的方式拼接sql,不存在sql注入的问题,此时为字符串类型或日期类型的字段进行赋值时,可以自动添加单引号(尽量使用这一种)。

3、MyBatis获取参数值的五种情况

情况1: Mapper接口方法的参数为单个字面量类型的参数

若mapper接口中的方法参数为单个的字面量类型
此时可以使用${}#{}以任意的名称获取参数的值,注意${}需要手动加单引号

ParameterMapper接口代码
package com.rqs.mybatis.mapper;

import com.rqs.mybatis.pojo.User;

import java.util.List;

public interface ParameterMapper {
    /**
     * 单个的字面量类型:
     * 根据用户名查询用户信息
     */
    User getUserByUserName(String username);
}
测试类代码
    /**
     * MyBatis获取参数值的各种情况:
     * 情况1: mapper接口方法的参数为单个字面量的参数
     * 可以通过${} #{}以任意的字符串获得参数值,但需要注意${}的单引号问题
     */
    @Test
    public void testgetUserByUserName(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        ParameterMapper mapper = sqlSession.getMapper(ParameterMapper.class);
        User user = mapper.getUserByUserName("rqs");
        System.out.println(user);
    }
ParameterMapper.xml配置方式1:${}
<!--    User getUserByUserName(String username);-->
    <select id="getUserByUserName" resultType="User">
        <!-- 错误写法:
       select * from t_user where username = ${username}
          如果使用这种方式,得到的sql语句是:
          Preparing: select * from t_user where username = rqs
          而其中username的值‘rqs’没有单引号,语法不正确,会报错。
          因此要手动添加单引号
       -->
        select * from t_user where username = '${username}'
    </select>

方式1错误写法的结果:
会报错
在这里插入图片描述
sql语句的正确写法是:
在这里插入图片描述
方式1正确写法的结果:
在这里插入图片描述

ParameterMapper.xml配置方式2:#{}
<?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.rqs.mybatis.mapper.ParameterMapper">
    <!--User getUserByUserName(String username);-->
    <!--    使用#{},里面内容可以随便写,都是传进来的String username参数的值,该值在测试类中写的mapper.getUserByUserName("rqs"),
    所以这里无论怎么写都会获得“rqs”的值,虽然可以随便写,但建议见闻知意思,写传输过来的参数名的名字,此处为username-->
    <select id="getUserByUserName" resultType="user">
        select * from t_user where username=#{username}
    </select>

</mapper>

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

情况2:Mapper接口方法的参数有多个,利用Mabatis的map参数集合

若mapper接口中的方法参数为多个时
此时MyBatis会自动将这些参数放在一个map集合中,以arg0,arg1…为键,以参数为值;
以 param1,param2…为键,以参数为值;
因此只需要通过${}#{}访问map集合的键就可以获取相对应的 值,注意${}需要手动加单引号

ParameterMapper接口
package com.rqs.mybatis.mapper;
import com.rqs.mybatis.pojo.User;


public interface ParameterMapper {
    /**
     * 验证登录
     */
    User checkLogin(String username, String password);
}
测试类代码
package com.rqs.mybatis.test;

import com.rqs.mybatis.mapper.ParameterMapper;
import com.rqs.mybatis.pojo.User;
import com.rqs.mybatis.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;


public class ParameterMapperTest {

    /**
     * 情况2:mapper接口方法的参数为多个时
     * 此时MyBatis会将这些参数放在一个map集合中,以两种方式进行存储
     * a》以arg0,arg1。。为键,参数为值
     * b》以param0,param1。。为键,参数位置
     * 因此只需要通过#{}和${}以键的方式访问值即可,但需要注意${}的单引号问题
     */
    @Test
    public void testCheckLogin(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        ParameterMapper mapper = sqlSession.getMapper(ParameterMapper.class);
        User user = mapper.checkLogin("rqs","123456");
        System.out.println(user);
    }
    
}
ParameterMapper.xml错误写法
<?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.rqs.mybatis.mapper.ParameterMapper">

    <!--    User checkLogin(String username, String password);-->
    <select id="checkLogin" resultType="User">
        <!--错误写法-->
        <!--会报错:Parameter 'username' not found. Available parameters are [arg1, arg0, param1, param2]
        因为sql语句没有解析成功-->
        select * from t_user where username = #{username} and password = #{password}
    </select>
</mapper>

写法1是错的,测试结果:
在这里插入图片描述
写法1的报错提示username参数没有找到,当前可用的参数是[arg1,arg0,param1,param2],这是什么意思呢?在MyBatis的底层,如果检测到当前Mapper接口中的方法有多个参数,会自动把这些参数放在一个map集合里,并且以两种方式存储数据,第一种:以arg0,arg1为键,以参数为值,第二种:以param1,param2参数为键,以参数为值。所以,如果要获取map中某一个键所对应的值,直接在#{}或者${}里访问map集合的键。本案例中arg0和param1表示的都是User checkLogin(String username, String password);中的参数username,arg1和param2表示的都是User checkLogin(String username, String password);中的参数password。即
arg0、param1 -> username
arg1、param2 -> password

ParameterMapper.xml正确写法

任选一种,解释如上黄色部分
键 -> 值关系如下:
arg0、param1 -> username
arg1、param2 -> password

<?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.rqs.mybatis.mapper.ParameterMapper">
    <select id="checkLogin" resultType="user">
        <!--    User checkLogin(String username, String password);-->
        <!--以map集合形式存储,arg0->param1, arg1->param2,这时直接用键arg访问就好了,用param访问也行。
        arg0、param1 -> username
        arg1、param2 -> password-->
        <!--写法2-->
        select * from t_user where username = #{arg0} and password = #{arg1}
        <!--select * from t_user where username = '${arg0}' and password = '${arg1}' -->
       
    </select>
</mapper>

<?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.rqs.mybatis.mapper.ParameterMapper">
    <select id="checkLogin" resultType="user">
        <!--    User checkLogin(String username, String password);-->
        <!--以map集合形式存储,arg0->param1, arg1->param2,这时直接用键arg访问就好了,用param访问也行。
        arg0、param1 -> username
        arg1、param2 -> password-->

        <!--写法3-->
        select * from t_user where username = '#{arg0}' and password = '#{param2}'
        <!--select * from t_user where username = '${arg0}' and password = '${param2}' -->

    </select>
</mapper>

<?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.rqs.mybatis.mapper.ParameterMapper">
    <select id="checkLogin" resultType="user">
        <!--    User checkLogin(String username, String password);-->
        <!--以map集合形式存储,arg0->param1, arg1->param2,这时直接用键arg访问就好了,用param访问也行。
        arg0、param1 -> username
        arg1、param2 -> password-->

        <!--写法4-->
        select * from t_user where username = '#{param1}' and password = '#{arg1}'
        <!--select * from t_user where username = '${param1}' and password = '${arg1}' -->

    </select>
</mapper>

<?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.rqs.mybatis.mapper.ParameterMapper">
    <select id="checkLogin" resultType="user">
        <!--    User checkLogin(String username, String password);-->
        <!--以map集合形式存储,arg0->param1, arg1->param2,这时直接用键arg访问就好了,用param访问也行。
        arg0、param1 -> username
        arg1、param2 -> password-->
        <!--写法5-->
        select * from t_user where username = '#{param1}' and password = '#{arg1}'
        <!--select * from t_user where username = '${param1}' and password = '${arg1}' -->

    </select>
</mapper>

测试结果均为:
在这里插入图片描述

情况3:Mapper接口方法的参数有多个,利用手动创建的map参数集合

Mybatis可以自动将参数放map中,所以若mapper接口中的方法需要的参数为多个时,我们也可以手动创建map集合,将这些数据放在map中,只需要通过${}#{}访问map集合的键就可以获取相对应的值,注意${}需要手动加单引号

ParameterMapper接口
package com.rqs.mybatis.mapper;
import com.rqs.mybatis.pojo.User;

import java.util.Map;


public interface ParameterMapper {
    /**
     * 验证登录
     */
    User checkLoginByMap(Map<String, Object> map);
}


测试类代码
package com.rqs.mybatis.test;

import com.rqs.mybatis.mapper.ParameterMapper;
import com.rqs.mybatis.pojo.User;
import com.rqs.mybatis.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.HashMap;
import java.util.Map;


public class ParameterMapperTest {

    /**
     * 情况3:若mapper接口方法的参数有多个时,可以手动将这些参数放在一个map中存储
     * 只需要通过#{} ${}以键的方式访问值即可,但是需要注意${}的单引号问题
     */
    @Test
    public void testCheckLoginByMap(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        ParameterMapper mapper = sqlSession.getMapper(ParameterMapper.class);

        Map<String, Object> map = new HashMap<>();
        map.put("username","rqs");
        map.put("password","123456");

        User user = mapper.checkLoginByMap(map);
        System.out.println(user);
    }


}

ParameterMapper.xml写法1
<?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.rqs.mybatis.mapper.ParameterMapper">
    <!--    User checkLoginByMap(Map<String, Object> map);-->
    <select id="checkLoginByMap" resultType="User">
        select * from t_user where username = #{username} and password = #{password}
    </select>
</mapper>
ParameterMapper.xml写法2
<?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.rqs.mybatis.mapper.ParameterMapper">
    <!--    User checkLoginByMap(Map<String, Object> map);-->
    <select id="checkLoginByMap" resultType="User">
        select * from t_user where username = '${username}' and password = '${password}'
    </select>
</mapper>

测试结果均为:
在这里插入图片描述

情况4:Mapper接口方法的参数是一个实体类对象【用的最多的情况之一

从浏览器传输过来的是一个完整的表单数据,可以在控制层中获取这些数据并且放在实体类对象中进行存储,这个时候调用service,service调用mappe,传输过来的是一个实体类对象。此时的访问方式类似于map集合,map集合以键进行访问,实体类对象以属性进行访问,注意这里根据属性进行访问主要是看有没有get、set 方法,把get、set方法的方法名中的get和set去掉,把剩下部分的首字母变成小写的结果就是当前的属性名,也就是成员变量,但要注意有一种情况,会出现没有相对应的成员变量却有相对应的get、set方法,此时就不能说没有这个属性了。

ParameterMapper接口
package com.rqs.mybatis.mapper;
import com.rqs.mybatis.pojo.User;

public interface ParameterMapper {
    /**
     * 添加用户信息
     */
    int insertUser(User user);
}

测试类代码
package com.rqs.mybatis.test;

import com.rqs.mybatis.mapper.ParameterMapper;
import com.rqs.mybatis.pojo.User;
import com.rqs.mybatis.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

public class ParameterMapperTest {
    /**
     * 情况4:mapper接口方法的参数是实体类类型的参数(web从control层传过来的)
     * 只需要通过#{} ${}以属性的方式访问属性值即可,但是需要注意${}的单引号问题
     */
    @Test
    public void testCheckLoginByMap(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        ParameterMapper mapper = sqlSession.getMapper(ParameterMapper.class);
        int result = mapper.insertUser(new User(null,"lzh","123",23,"男","123@qq.com"));
        System.out.println(result);
    }
}

ParameterMapper.xml写法
<?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.rqs.mybatis.mapper.ParameterMapper">
    <!--        int insertUser(User user);-->
    <!--    找到相对应的get方法,如username->找getUsername(),看get/set方法-->
    <insert id="insertUser">
        insert into t_user values(null, #{username}, #{password}, #{age}, #{gender}, #{email})
    </insert>
</mapper>

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

情况5:使用@Param注解来命名参数【很常用的情况】

这种情况适用的场景比较多,是情况2和3的结合。
可以通过@Param注解标识mapper接口中的方法参数,会将这些参数放在map集合中,存储方式有两种。

  • 第一种:以@Param注解的value属性值为键,以参数为值;
  • 第二种:以 param1,param2…为键,以参数为值;

只需要通过${}#{}访问map集合的键就可以获取相对应的值, 注意${}需要手动加单引号

ParameterMapper接口
package com.rqs.mybatis.mapper;
import com.rqs.mybatis.pojo.User;
import org.apache.ibatis.annotations.Param;

public interface ParameterMapper {

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


测试类代码
package com.rqs.mybatis.test;

import com.rqs.mybatis.mapper.ParameterMapper;
import com.rqs.mybatis.pojo.User;
import com.rqs.mybatis.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

public class ParameterMapperTest {
    /**
     * 情况5:使用@Param注解来命名参数
     * 此时MyBatis会将这些参数放在一个map集合中,以两种方式进行存储
     * a》以@Param的值为键,参数为值; @Param(value = "xxx")
     * b》以param1,param2...为键,参数为值
     */
    @Test
    public void testCheckLoginByParam(){
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        ParameterMapper mapper = sqlSession.getMapper(ParameterMapper.class);
        User user = mapper.checkLoginByParam("rqs","123456");
        System.out.println(user);
    }

}
ParameterMapper.xml写法
<?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.rqs.mybatis.mapper.ParameterMapper">
    <!--    以@Param的值为键,参数为值; 或以"param1"/"param2"为键,参数为值-->
    <!--    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>

</mapper>

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

4、建议将5种情况整合为两种情况

  • 情况1:实体类
  • 情况2:@Param

5、@Param源码分析

参考:https://blog.csdn.net/CherryChenieth/article/details/123195302

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
创建和获取 MyBatis-Plus 的 Mapper 对象,可以通过以下两种方式进行: 1. 使用 Spring Boot 自动装配 如果您的项目使用了 Spring Boot,可以直接使用 Spring Boot 提供的自动装配机制来创建和获取 MyBatis-Plus 的 Mapper 对象。具体来说,您需要完成以下两个步骤: 1. 在 `application.properties` 或 `application.yml` 中配置 MyBatis-Plus 的相关参数,包括数据源配置、Mapper 扫描路径等。例如: ```yaml # 数据源配置 spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/mydatabase spring.datasource.username=root spring.datasource.password=123456 # MyBatis-Plus 配置 mybatis-plus.mapper-locations=classpath:mapper/**/*.xml mybatis-plus.type-aliases-package=com.example.entity ``` 2. 在需要使用 Mapper 对象的地方,通过 `@Autowired` 注解注入对应的 Mapper 对象即可。例如: ```java @RestController public class MyController { @Autowired private MyMapper myMapper; @GetMapping("/getVariable") public String getVariable() { return myMapper.getVariable(); } } ``` 在上述代码中,我们使用 `@Autowired` 注解将 `MyMapper` 对象注入到了 `MyController` 控制器中,并在 `getVariable` 方法中使用该对象查询数据库并返回结果。 2. 手动创建 Mapper 对象 如果您的项目没有使用 Spring Boot,或者需要手动创建 Mapper 对象,可以通过以下步骤进行: 1. 在 `pom.xml` 中引入 MyBatis-Plus 的依赖: ```xml <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>${mybatis-plus.version}</version> </dependency> ``` 2. 在需要使用 Mapper 对象的地方,通过 `SqlSessionFactory` 和 `MapperRegistry` 对象手动创建 Mapper 对象。例如: ```java public class MyBatisPlusUtils { // 获取 SqlSessionFactory 对象 private static SqlSessionFactory getSqlSessionFactory() { // 创建数据源对象 DataSource dataSource = new PooledDataSource( "com.mysql.jdbc.Driver", "jdbc:mysql://localhost:3306/mydatabase", "root", "123456" ); // 创建 MyBatis 配置对象 MybatisConfiguration configuration = new MybatisConfiguration(); configuration.setMapUnderscoreToCamelCase(true); // 创建 SqlSessionFactory 对象 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder() .build(configuration, dataSource); return sessionFactory; } // 获取 Mapper 对象 public static <T> T getMapper(Class<T> mapperClass) { // 创建 SqlSessionFactory 对象 SqlSessionFactory sessionFactory = getSqlSessionFactory(); // 创建 MapperRegistry 对象 MapperRegistry mapperRegistry = new MapperRegistry(sessionFactory.getConfiguration()); // 注册 Mapper 对象 mapperRegistry.addMapper(mapperClass); // 获取 Mapper 对象 return sessionFactory.openSession().getMapper(mapperClass); } } ``` 在上述代码中,我们定义了一个 `getSqlSessionFactory` 方法,用于创建 `SqlSessionFactory` 对象;并定义了一个 `getMapper` 方法,用于手动创建 Mapper 对象。在 `getMapper` 方法中,我们首先通过 `getSqlSessionFactory` 方法获取到了 `SqlSessionFactory` 对象,然后创建了一个 `MapperRegistry` 对象,并将需要创建的 Mapper 对象注册到了该对象中;最后通过 `SqlSessionFactory` 对象的 `openSession` 方法获取到了一个 `SqlSession` 对象,并调用该对象的 `getMapper` 方法获取到了需要的 Mapper 对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值