• Mybatis 使用参数时$与#的区别


    之前我们介绍了mybatis中参数的使用,本篇我们在此基础上介绍Mybatis中使用参数时$与#的区别。

    如果您对mybatis中参数的使用不太了解,建议您先进行了解后再阅读本篇,可以参考:

    Mybatis参数(parameterType)icon-default.png?t=N7T8https://blog.csdn.net/m1729339749/article/details/132548838

    一、创建实体类

    在cn.horse.demo下创建UserInfo、UserInfoQuery类

    UserInfo类:

    1. package cn.horse.demo;
    2. public class UserInfo {
    3. private Integer id;
    4. private String name;
    5. private Integer age;
    6. public void setId(Integer id) {
    7. this.id = id;
    8. }
    9. public Integer getId() {
    10. return id;
    11. }
    12. public void setName(String name) {
    13. this.name = name;
    14. }
    15. public String getName() {
    16. return name;
    17. }
    18. public void setAge(Integer age) {
    19. this.age = age;
    20. }
    21. public Integer getAge() {
    22. return age;
    23. }
    24. @Override
    25. public String toString() {
    26. StringBuilder stringBuilder = new StringBuilder();
    27. stringBuilder.append('{');
    28. stringBuilder.append("id: " + this.id);
    29. stringBuilder.append(", ");
    30. stringBuilder.append("name: " + this.name);
    31. stringBuilder.append(", ");
    32. stringBuilder.append("age: " + this.age);
    33. stringBuilder.append('}');
    34. return stringBuilder.toString();
    35. }
    36. }

    UserInfoQuery类:

    1. package cn.horse.demo;
    2. public class UserInfoQuery {
    3. private Integer startAge;
    4. private Integer endAge;
    5. private Integer start;
    6. private Integer limit;
    7. public void setStartAge(Integer startAge) {
    8. this.startAge = startAge;
    9. }
    10. public Integer getStartAge() {
    11. return startAge;
    12. }
    13. public void setEndAge(Integer endAge) {
    14. this.endAge = endAge;
    15. }
    16. public Integer getEndAge() {
    17. return endAge;
    18. }
    19. public void setStart(Integer start) {
    20. this.start = start;
    21. }
    22. public Integer getStart() {
    23. return start;
    24. }
    25. public void setLimit(Integer limit) {
    26. this.limit = limit;
    27. }
    28. public Integer getLimit() {
    29. return limit;
    30. }
    31. }

    二、创建映射器、Mapper配置

    在cn.horse.demo下创建UserInfoMapper接口

    UserInfoMapper接口:

    1. package cn.horse.demo;
    2. import org.apache.ibatis.annotations.*;
    3. import java.util.List;
    4. public interface UserInfoMapper {
    5. List find(@Param("query") UserInfoQuery query);
    6. }

    在resources下创建cn/horse/demo目录,并在此目录下创建UserInfoMapper.xml配置文件

    UserInfoMapper.xml配置:

    1. "1.0" encoding="UTF-8" ?>
    2. mapper
    3. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    4. "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
    5. <mapper namespace="cn.horse.demo.UserInfoMapper">
    6. <resultMap id="userInfoMap" type="cn.horse.demo.UserInfo">
    7. <result column="ID" property="id" />
    8. <result column="USERNAME" property="name"/>
    9. <result column="AGE" property="age"/>
    10. resultMap>
    11. <select id="find" parameterType="cn.horse.demo.UserInfoQuery" resultMap="userInfoMap">
    12. SELECT
    13. ID,
    14. USERNAME,
    15. AGE
    16. FROM ${userTableName}
    17. <where>
    18. <if test="null != query.startAge">
    19. AND AGE >= #{query.startAge}
    20. if>
    21. <if test="null != query.endAge">
    22. AND AGE <= #{query.endAge}
    23. if>
    24. where>
    25. LIMIT ${query.start}, ${query.limit}
    26. select>
    27. mapper>

    配置中我们使用${userTableName}获取用户表名称,使用${query.start}、${query.limit}获取分页信息,使用#{query.startAge}、#{query.endAge}获取查询条件信息

    三、引入配置文件

    在resources下新建mybatis-config.xml配置文件,并引入UserInfoMapper映射器。

    1. "1.0" encoding="UTF-8" ?>
    2. configuration
    3. PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    4. "http://mybatis.org/dtd/mybatis-3-config.dtd">
    5. <configuration>
    6. <properties>
    7. <property name="userTableName" value="T_USER"/>
    8. properties>
    9. <settings>
    10. <setting name="logImpl" value="JDK_LOGGING"/>
    11. settings>
    12. <environments default="development">
    13. <environment id="development">
    14. <transactionManager type="JDBC"/>
    15. <dataSource type="POOLED">
    16. <property name="driver" value="org.gjt.mm.mysql.Driver"/>
    17. <property name="url" value="jdbc:mysql://localhost:3306/demo?useUnicode=true&useSSL=false&characterEncoding=utf8&allowMultiQueries=true"/>
    18. <property name="username" value="root"/>
    19. <property name="password" value="horse"/>
    20. dataSource>
    21. environment>
    22. environments>
    23. <mappers>
    24. <mapper class="cn.horse.demo.UserInfoMapper" />
    25. mappers>
    26. configuration>

    这里,我们在mybatis中定义了属性名为userTableName属性值为T_USER的属性,并使用mapper引入了映射器。

    四、启动程序

    1、数据准备

    这里我们直接使用脚本初始化数据库中的数据

    1. -- 如果数据库不存在则创建数据库
    2. CREATE DATABASE IF NOT EXISTS demo DEFAULT CHARSET utf8;
    3. -- 切换数据库
    4. USE demo;
    5. -- 创建用户表
    6. CREATE TABLE IF NOT EXISTS T_USER(
    7. ID INT PRIMARY KEY,
    8. USERNAME VARCHAR(32) NOT NULL,
    9. AGE INT NOT NULL
    10. );
    11. -- 插入用户数据
    12. INSERT INTO T_USER(ID, USERNAME, AGE)
    13. VALUES(1, '张三', 20),(2, '李四', 22),(3, '王五', 24);

    创建了一个名称为demo的数据库;并在库里创建了名称为T_USER的用户表并向表中插入了数据

    2、会话工具类

    在cn.horse.demo包下新建SqlSessionUtils工具类

    1. package cn.horse.demo;
    2. import org.apache.ibatis.session.SqlSession;
    3. import org.apache.ibatis.session.SqlSessionFactory;
    4. import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    5. import java.io.InputStream;
    6. import java.util.Objects;
    7. public class SqlSessionUtils {
    8. private static final SqlSessionFactory sqlSessionFactory;
    9. static {
    10. // 读取mybatis配置文件
    11. InputStream inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream("mybatis-config.xml");
    12. // 根据配置创建SqlSession工厂
    13. sqlSessionFactory = new SqlSessionFactoryBuilder()
    14. .build(inputStream);
    15. }
    16. /**
    17. * 开启会话
    18. * @return
    19. */
    20. public static SqlSession openSession() {
    21. return sqlSessionFactory.openSession();
    22. }
    23. /**
    24. * 关闭会话
    25. * @param sqlSession
    26. */
    27. public static void closeSession(SqlSession sqlSession) {
    28. if(Objects.nonNull(sqlSession)) {
    29. sqlSession.close();
    30. }
    31. }
    32. }

    3、JDK 日志系统配置

    在resources的目录下新建logging.properties配置文件

    1. handlers=java.util.logging.ConsoleHandler
    2. .level=INFO
    3. cn.horse.demo.level=FINER
    4. java.util.logging.ConsoleHandler.level=ALL
    5. java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
    6. java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-%1$td %1$tT.%1$tL %4$s %3$s - %5$s%6$s%n

    在cn.horse.demo下创建JdkLogConfig类

    JdkLogConfig类:

    1. package cn.horse.demo;
    2. import java.io.IOException;
    3. import java.io.InputStream;
    4. import java.util.logging.LogManager;
    5. public class JdkLogConfig {
    6. public JdkLogConfig() {
    7. try {
    8. InputStream inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream("logging.properties");
    9. LogManager.getLogManager().readConfiguration(inputStream);
    10. } catch (IOException e) {
    11. throw new RuntimeException(e);
    12. }
    13. }
    14. }

    4、启动程序

    1. package cn.horse.demo;
    2. import org.apache.ibatis.session.SqlSession;
    3. import java.util.List;
    4. import java.util.function.Consumer;
    5. import java.util.logging.Logger;
    6. public class Main {
    7. private static final Logger LOGGER;
    8. static {
    9. // 引入JDK日志配置
    10. System.setProperty("java.util.logging.config.class", "cn.horse.demo.JdkLogConfig");
    11. LOGGER = Logger.getLogger("cn.horse.demo.Main");
    12. }
    13. public static void main(String[] args) throws InterruptedException {
    14. execute((UserInfoMapper userInfoMapper) -> {
    15. UserInfoQuery query = new UserInfoQuery();
    16. query.setStartAge(0);
    17. query.setEndAge(24);
    18. query.setStart(0);
    19. query.setLimit(1);
    20. List userInfoList = userInfoMapper.find(query);
    21. for (UserInfo userInfo: userInfoList) {
    22. LOGGER.info(userInfo.toString());
    23. }
    24. });
    25. }
    26. private static void execute(Consumer function) {
    27. SqlSession sqlSession = null;
    28. try {
    29. sqlSession = SqlSessionUtils.openSession();
    30. function.accept(sqlSession.getMapper(UserInfoMapper.class));
    31. sqlSession.commit();
    32. } finally {
    33. SqlSessionUtils.closeSession(sqlSession);
    34. }
    35. }
    36. }

    execute方法用于执行操作,方法中使用sqlSession.getMapper方法获取映射器对象,然后将映射器对象具体的执行操作委托给了Consumer对象。

    执行后的结果如下:

    现象:

    从日志打印的SQL语句中可以看出参数${userTableName}被替换成了T_USER,${query.start}被替换成了0,${query.limit}被替换成了1;而#{query.startAge}、#{query.endAge}被替换成了?;

    结论:

    使用$获取参数时在执行SQL语句时参数会被替换,使用$获取的参数可以是在mybatis中定义的属性。

    使用#获取参数时在执行SQL语句时会进行预处理以避免SQL注入。

  • 相关阅读:
    程序人生 | 与足球共舞的火柴人(致敬格拉利什,赋予足球更深的意义)
    web前端期末大作业——贵州山地旅游介绍网页1页 HTML旅游网站设计与实现
    MYSQL数据库管理与创建
    【玩转腾讯混元大模型】怎么说?我用混元AI大模型开发了个IDEA插件
    【历史上的今天】7 月 5 日:Google 之母出生;同一天诞生的两位图灵奖先驱
    vue+Ts+element组件封装
    LeetCode 461. 汉明距离
    Difference quotient
    C++字符串类 - std::string - 常用总结
    C语言编译过程
  • 原文地址:https://blog.csdn.net/m1729339749/article/details/133632243