首页 > 其他分享 >Mybatis基础操作

Mybatis基础操作

时间:2024-09-25 15:18:54浏览次数:11  
标签:语句 name 映射 基础 MyBatis SQL Mybatis 操作 id

一、设置日志

mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

在Mybatis当中我们可以借助⽇志, 查看到sql语句的执⾏、执⾏传递的参数以及执⾏结果

二、XML 映射 SQL

在 MyBatis 中,你可以选择两种主要方式来编写 SQL 映射:使用 XML 映射文件或者使用 Java 注解。这两种方法各有优缺点,适用于不同的场景。以下是这两种方法的详细比较:

XML 映射是 MyBatis 最传统也是最灵活的配置方式。它将 SQL 语句和 Java 接口分离,使得 SQL 语句更易于管理和优化。

优点:
  • 集中管理:XML 文件可以集中管理 SQL 语句,易于维护和查阅。
  • 支持动态 SQL:XML 方式支持更为复杂的动态 SQL 语句,如条件语句(<if>)、循环语句(<foreach>)等,这些可以使 SQL 根据不同条件灵活生成。
  • 易于版本控制:作为文件的一部分,XML 映射可以轻松地纳入版本控制系统中。
缺点:
  • 间接性:代码与 SQL 分离,可能导致开发中来回查找对应 SQL 语句,降低开发效率。
  • 冗余:可能需要为每一个 SQL 语句编写大量的 XML 配置代码

三、注解 映射 SQL

注解方式是 MyBatis 在较新版本中引入的,它将 SQL 语句直接写在 Mapper 接口的方法上,减少了配置的复杂性。

优点:
  • 直接性:SQL 语句与 Java 方法紧密绑定,易于阅读和修改。
  • 简洁:减少了 XML 的冗余配置,使得项目结构更为简洁。
缺点:
  • 有限的动态 SQL 支持:虽然注解支持基本的动态 SQL,如 @Select@Insert 等,但对于复杂的动态 SQL,如条件判断、循环等支持不如 XML 方式。
  • 可扩展性有限:对于非常复杂的 SQL,注解方式可能显得力不从心。
    public interface UserMapper {
        @Select("SELECT * FROM users WHERE id = #{id}")
        User selectUserById(int id);
    }
    

四、参数传递 

1)一个参数

如果 SQL 语句只需要一个参数,你可以直接在 mapper 接口的方法中传递这个参数。MyBatis 会自动将它识别为 SQL 语句中的参数。

public interface UserMapper {
    User selectUserById(int id);
}

Mapper XML

<select id="selectUserById" parameterType="int" resultType="com.example.mybatisdemo.model.User">
    SELECT * FROM users WHERE id = #{id}
</select>

在这个例子中,#{id} 是一个占位符,用于在执行时替换成方法 selectUserById(int id) 中的参数。

2)多个参数

当方法中有多个参数时,MyBatis 提供了几种处理方式:

  • @Param 注解:最常用的方式,可以给参数命名,然后在 SQL 语句中引用这些名称、Mapper 接口
    public interface UserMapper {
        User findUserByNameAndEmail(@Param("name") String name, @Param("email") String email);
    }
    

    Mapper XML

    <select id="findUserByNameAndEmail" resultType="com.example.mybatisdemo.model.User">
        SELECT * FROM users WHERE name = #{name} AND email = #{email}
    </select>

    使用 @Param 注解可以明确指定 SQL 语句中参数的名称,这样即使参数的顺序改变,也不会影响 SQL 语句的执行

3) 返回主键

在 MyBatis 中,将操作结果的自动生成的主键(如数据库自增主键)返回到应用程序中是一个常见需求。这通常在执行插入(INSERT)操作时使用。MyBatis 提供了几种方式来处理自动生成的主键,并将其返回。

a) 使用 XML 映射

当你使用 XML 映射文件定义 SQL 语句时,可以通过 useGeneratedKeyskeyProperty 属性来指定如何返回自动生成的主键。

示例:

假设你有一个名为 users 的表,其中 id 字段是自增主键。

<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO users (name, email) VALUES (#{name}, #{email})
</insert>

在这个例子中:

  • useGeneratedKeys="true" 告诉 MyBatis 使用 JDBC 的 getGeneratedKeys() 方法来检索由数据库自动生成的键。
  • keyProperty="id" 指定 MyBatis 应将获取的键值设置到哪个属性上。在本例中,它将设置到 User 对象的 id 属性上。
b) 使用注解

当你使用注解来配置 MyBatis 映射时,可以使用 @Options 注解来指定如何处理自动生成的键。

Mapper 接口方法:

public interface UserMapper {
    @Insert("INSERT INTO users (name, email) VALUES (#{name}, #{email})")
    @Options(useGeneratedKeys = true, keyProperty = "id")
    int insertUser(User user);
}

这里的 @Options 注解具有与 XML 相同的属性:

  • useGeneratedKeys = true 这会令 MyBatis 使⽤ JDBC 的 getGeneratedKeys ⽅法来取出由数据库内 部⽣成的主键(⽐如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的⾃动递增字 段),默认值:false
  • keyProperty = "id" 指定能够唯⼀识别对象的属性,MyBatis 会使⽤ getGeneratedKeys 的返回值或 insert 语句的 selectKey ⼦元素设置它的值,默认值:未设置(unset)

五、SELECT 查找

在 MyBatis 中,字段映射的默认行为是按照属性名和数据库字段名进行匹配。如果 Java 对象的属性名与数据库表的字段名不一致,你需要显式地指定这种映射关系,以确保正确的数据赋值

1. 起别名 (Alias)

在 SQL 查询中直接为字段起别名,使其与 Java 对象的属性名匹配。这是一种非常简单且直接的方式,适用于简单的场景。

示例:

假设数据库字段名为 emp_name,而 Java 对象的属性名为 name,可以在 SQL 语句中直接为 emp_name 起别名为 name

SELECT emp_id as id, emp_name as name, emp_email as email FROM employees

使用这种方法,MyBatis 在映射结果到 Java 对象时会自动将 name 列的值赋给 name 属性。

2. 结果映射 (Result Mapping)

使用 MyBatis 的 resultMap 元素来定义字段映射关系。这种方式提供了高度的灵活性和控制力,适用于复杂的数据结构和关系。

示例:

在 MyBatis 映射文件中使用 resultMap 来定义字段与属性的映射关系:

<mapper namespace="com.example.mapper.EmployeeMapper">
    <resultMap id="EmployeeMap" type="Employee">
        <result property="id" column="emp_id"/>
        <result property="name" column="emp_name"/>
        <result property="email" column="emp_email"/>
    </resultMap>

    <select id="selectEmployee" resultMap="EmployeeMap">
        SELECT emp_id, emp_name, emp_email FROM employees
    </select>
</mapper>

这个 resultMap 显式地告诉 MyBatis 如何将数据库字段映射到 Java 对象的属性。

3. 开启驼峰命名 (Camel Case Mapping)

通常数据库列使⽤蛇形命名法进⾏命名(下划线分割各个单词), ⽽ Java 属性⼀般遵循驼峰命名法约定. 为了在这两种命名⽅式之间启⽤⾃动映射,需要将 mapUnderscoreToCamelCase 设置为 true。

mybatis:
 configuration:
  map-underscore-to-camel-case: true #配置驼峰⾃动转换

开启这个配置后,MyBatis 会自动将诸如 emp_name 的字段名映射为 empName 的 Java 属性。这样,你不需要在每个 SQL 语句中为字段起别名,也不需要在每个映射中定义 resultMap

六、#{} 和 ${}

在 MyBatis 中,#{}${} 是两种基本的参数占位符,用于在 SQL 语句中插入参数值,但它们的工作方式和用途有明显的区别:

1. #{} (Prepared Statement 占位符)

#{} 是用来创建预处理语句 (Prepared Statement) 的参数占位符。当你使用 #{} 时,MyBatis 会使用 JDBC 的 PreparedStatement 功能,这意味着参数值在传递给数据库之前会进行适当的转义,从而防止 SQL 注入攻击。这是处理用户输入或不可信数据时推荐的做法。

示例:
SELECT * FROM users WHERE id = #{id}

在这里,#{id} 会被替换为一个参数标记,如 ?,并且 id 的值会在执行时被安全地绑定到这个问号上。如果 id5,那么实际执行的 SQL 会是:

SELECT * FROM users WHERE id = ?

并且 5 作为参数传递,这样可以防止 SQL 注入。

2. ${} (文本替换占位符)

${} 用于直接将参数值插入 SQL 语句中。这种方式可以用于动态更改表名、列名或者是 SQL 语句的其它部分,而不仅仅是值。使用 ${} 时,必须非常小心,因为它不会对参数值进行任何处理或转义,从而有可能导致 SQL 注入风险。

SELECT * FROM ${tableName} WHERE id = ${id}

如果 tableNameusers,而 id5,那么生成的 SQL 将直接是:

SELECT * FROM users WHERE id = 5

这种方式使得你可以灵活地构建 SQL 语句,但如果 tableNameid 来自于用户输入或其他不可信的来源,则可能会带来安全风险。

选择使用哪一个
  • 当你需要插入安全的、转义后的数据值时,使用 #{}
  • 当你需要在 SQL 语句中动态插入表名、列名或其他不会改变 SQL 逻辑的元素时,可以使用 ${},但必须非常小心确保这些值是安全的,避免 SQL 注入。

通常,除非绝对必要,建议尽量避免使用 ${} 来避免潜在的安全问题。使用 #{} 可以利用 PreparedStatement 的优势,有效防止 SQL 注入,是更安全的选择。

${}的必要性
1.排序
@Select("select id, username, age, gender, phone, delete_flag, create_time, 
update_time " +
 "from userinfo order by id ${sort} ")
List<UserInfo> queryAllUserBySort(String sort);

使⽤ ${sort} 可以实现排序查询, ⽽使⽤ #{sort} 就不能实现排序查询了. 注意: 此处 sort 参数为String类型, 但是SQL语句中, 排序规则是不需要加引号 '' 的, 所以此时的 ${sort} 也不加引号

当使⽤ #{sort} 查询时, asc 前后⾃动给加了引号, 导致 sql 错误 #{} 会根据参数类型判断是否拼接引号 '' 如果参数类型为String, 就会加上 引号

除此之外, 还有表名作为参数时, 也只能使⽤ ${}

2.like 查询

在 MyBatis 中使用 #{} 对于大多数情况都是正常工作的,但在使用 LIKE 语句时,可能会遇到问题。这是因为 #{} 在转换过程中会将输入视为字面值,并且会自动在值周围添加单引号。这在 LIKE 查询中通常不是预期的行为,因为通配符(如 %)需要与字段值直接相连。

当你使用 LIKE 并希望包含通配符时,如下

SELECT * FROM users WHERE name LIKE '%#{name}%'

MyBatis 会处理这个语句并将其转换为: 

SELECT * FROM users WHERE name LIKE '%\'someName\'%'

这里的单引号是自动添加的,导致 SQL 语句错误,因为 SQL 不期望在 %someName 之间有额外的单引号。

为了正确使用 LIKE,你应该让 MyBatis 在不添加额外单引号的情况下处理变量。有两种主要方法可以实现:

使用 CONCAT 函数

你可以使用 SQL 的 CONCAT 函数来确保通配符和变量被正确组合,而不是将它们作为字符串字面值直接插入。这在大多数数据库中都有效。

SELECT * FROM users WHERE name LIKE CONCAT('%', #{name}, '%')
安全性考虑

尽管 ${} 在这种情况下是必要的,但它引入了潜在的 SQL 注入风险。为了安全地使用 ${},你需要确保:

  1. 输入验证:对传入的列名和排序方向进行严格验证,确保它们是预定义的有效值。例如,你可以在应用层或服务层检查 orderByColumn 是否确实是数据库中的列名,orderDir 是否仅为 "ASC" 或 "DESC"。

  2. 使用白名单:仅允许特定的、安全的字段名和排序方向,可以通过在服务层设置一个白名单来实现。

通过这种方式,尽管使用了 ${},但通过严格的输入验证和白名单策略,可以最大程度地减少 SQL 注入的风险,使得动态排序既灵活又安全。这种方法适用于需要高度动态性的 SQL 操作,如动态排序、动态查询字段等场景。

标签:语句,name,映射,基础,MyBatis,SQL,Mybatis,操作,id
From: https://blog.csdn.net/m0_74209411/article/details/142472703

相关文章

  • 【信息论基础第三讲】再谈离散信源的信息测度之熵的性质多符号信源的信息测度
    一、PieceOfCake1、离散信源X的熵是H(X)是一个常数而不是一个变量解释:离散信源的熵也就是自信息I(X)的数学期望,即H(X)=E[I(Xi)],而通过概率论的知识我们知道数学期望是一个常数,故熵也是一个常数。2、八元编码系统,码长为3,第一个符号用于同步,每秒1000个码字,求它的信息速率......
  • 【射频电子线路基础第五讲】射频电路的非线性
    一、无线通信系统与信道二、射频系统非线性1、非线性概念线性是指元件参数与通过元件的电流或者电压无关非线性是指元件参数与通过元件的电流或者电压有关时变线性是指元件参数按照一定规律随着时间变化,但与通过元件的电流或者电压无关射频元器件实际上是非线性的,线性是......
  • Java基础部分-运算符
    算术运算符:+,-,*,/,%,++,--inta=10;intb=20;intc=25;intd=25;System.out.println(a+b);System.out.println(a-b);System.out.println(a*b);System.out.println(a/(double)b);//强制转......
  • 学习JAVA前的基础部分
    常用关键字:1.所有的标识符都应该以字母(A—Zanda-z),美元符($),下划线(_)开始,首字符之后可以是字母,美元符,下划线或者任何数字。2.Java所需要的组成部分都需要名字。类名、变量名以及方法都需要被称为标识符。3.标识符是大小写敏感的数据类型​ 强类型语言:要求变量的使用要严格符合......
  • Java基础部分-变量
    Java是一种强类型语言,每个变量都必须声明其类型Java变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域。typevarName[=value][{,varName[=value]}];//数据类型变量名=值;可以使用逗号隔开来声明多个同类型变量。//类变量staticstaticdoublesal......
  • react之jsx基础(2)高频使用场景
    在React中,JSX的使用是非常广泛和高频的。以下是一些常见的高频使用场景及其示例,帮助你更好地理解JSX的实际应用:1.组件定义JSX最常见的用途之一是定义组件的结构。组件可以是函数组件或类组件,通常会使用JSX来描述组件的UI。函数组件示例:functionGreeting(props){......
  • 蓝队自动化应急响应工具(非常详细)零基础入门到精通,收藏这一篇就够了
    最近在工作中遇到了一个挺不错的工具,特别适合我们这些专注于网络安全的技术人员。你知道我们在日常工作中经常需要面对各种安全事件和威胁,有时候真的会感觉自己像在打游击战。不过,有了这个工具,应对安全事件就轻松多了。我最近开始用一个叫做FindAll的工具,它是为蓝队设计的......
  • nessus快速安装使用指南(非常详细)零基础入门到精通,收藏这一篇就够了
    Nessus是一款功能强大的漏洞扫描工具,用于识别系统、网络和应用中的安全漏洞。本文将提供Nessus的快速安装与使用指南,帮助迅速上手这款工具。一、安装Nessus1.下载Nessus安装包首先,访问Nessus官方网站(https://www.tenable.com/downloads/nessus?loginAttempted=true),根据......
  • 如何修复英雄联盟常见dll错误,操作系统提示缺少英雄联盟dll文件的有效解决办法
    在众多热门游戏中,《英雄联盟》以其精彩的竞技性和丰富的玩法深受玩家喜爱。然而,当玩家准备在召唤师峡谷大显身手时,却可能遭遇因操作系统中缺少DLL文件而导致的游戏无法启动等问题,这无疑令人十分困扰。别担心,下面就为大家介绍一些有效解决操作系统中缺少英雄联盟DLL文件的办......
  • C#|.net core 基础 - 扩展数组添加删除性能最好的方法
    C#|.netcore基础-扩展数组添加删除性能最好的方法 合集-C#|.netcore基础(6)  今天在编码的时候遇到了一个问题,需要对数组变量添加新元素和删除元素,因为数组是固定大小的,因此对新增和删除并不友好,但有时候又会用到,因此想针对数组封装两个扩展方法:新增元素与......