mybatis 细节(${ ..}和#{..},resultType 和 resultMap的区别,别名的使用,Mapper 代理模式)

${..}和#{..} 占位符

#{..}

#{}实现的是向prepareStatement中的预处理语句中设置参数值,sql语句中#{}表示一个占位符即?

<!-- 根据id查询用户信息 -->
<select id="findUserById" parameterType="int" resultType="user">
    select * from user where id = #{id}
</select>

使用占位符#{}可以有效防止sql攻击

  •  使用#{} 防止SQL注入攻击的底层代码如下
  // SQL查询语句,使用占位符 ?
        String query = "SELECT * FROM users WHERE username = ? AND password = ?";

        try (Connection conn = DriverManager.getConnection(dbURL, username, password)) {
            if (conn != null) {
                // 创建PreparedStatement对象
                PreparedStatement pstmt = conn.prepareStatement(query);

                // 设置参数
                pstmt.setString(1, userInputUsername); // 第一个占位符
                pstmt.setString(2, userInputPassword); // 第二个占位符

通过上面的代码可以发现,将 传递的参数 和 sql 语句进行分离。在预编译阶段,sql 语句作为创建 preparedStatement 对象的参数,就已经确定好了。因此即使用户 进行sql 注入攻击 ,无论你输入什么,都当成一般的数据。而不会被拼接到sql 语句去。成为新的sql 语句。

什么是sql 攻击呢?

假设当前是登录界面(不使用#{} 可能会遭受 sql 攻击)

不管你之前输入了,什么,如果你后面添加这种 or 1=1 这种类似的

最后拼接到查询的sql 语句中,即使之前输入错误也可以成功。这就是因为 sql 注入导致的sql 攻击

使用#{..} 的好处

1 预防sql 攻击

2 在 mybatis 框架 映射文件,不需要手动为 传递的数据为字符串 ,添加单引号。最会实现自动添加


${..}

应用场景:${..},占位符 多用于 字符串拼接

${..} 和 #{..} 的区别

${..} 无法预防sql 攻击,当传递参数后,会直接 和 sql 语句 进行拼接,改变原有sql 语句所表达的含义

${..} 在模糊查询中,效果更大


案例

  •  ${..}和#{..} 使用模糊查询,查询数据,在 映射文件中的sql语句,测试类传递的参数 表现不同的形式

项目准备

目的:基于mybatis 框架 基础 使用 模糊查询 查 关于 l 的所有用户信息

使用 #{} 在 映射文件 的sql 语句

   select * from tb_login where username like #{username};

测试类

    List<Login> list = sqlSession.selectList("getLoginByM", "%l%");
        for (Login login : list) {
            System.out.println("id: "+login.getId()+"用户名: "+login.getUsername()+"密码: "+login.getPassword());
        }

 效果展示

使用 ${} 在 映射文件 的sql 语句

  select * from tb_login where username like'%${m}%';

测试类

        List<Login> list = sqlSession.selectList("getLoginByM", "l");
        for (Login login : list) {
            System.out.println("id: "+login.getId()+"用户名: "+login.getUsername()+"密码: "+login.getPassword());
        }

效果展示

发现  在上面使用 #{..} 传递参数 时需要添加,%;而 ${..} 因为在书写 sql 语句就已经拼接好 %,因此传递参数时,就不再需要添加


resultType 和 resultMap

1. resultType 的使用场景

  • 定义resultType 是 MyBatis 中用于指定查询结果映射到的 Java 类型。

  • 特点

    • 简单映射resultType 通常用于简单的情况,比如查询结果直接映射到基本数据类型(如 intStringDate 等)或简单对象(如 UserProduct 等)。

    • 限制:当查询结果的列名与实体类的属性名完全匹配时,可以直接使用 resultType。如果查询结果的列名和实体类的属性名不匹配,或者查询结果包含嵌套对象(如关联对象),则不能直接使用 resultType

    • 不支持复杂映射resultType 不支持复杂的结果映射,比如嵌套对象、多表关联查询等。

2. resultMap 的使用场景

  • 定义resultMap 是 MyBatis 中用于定义复杂的结果映射规则。

  • 特点

    • 复杂映射resultMap 可以处理复杂的情况,比如多表关联查询、嵌套对象、嵌套集合等。

    • 灵活性:通过 resultMap,可以定义列名到属性名的映射规则,支持嵌套结果映射(如一对一、一对多关系)。

    • 适用性resultMap 适用于复杂查询,尤其是当查询结果的列名与实体类的属性名不匹配,或者查询结果包含嵌套对象时。

resultType 和 resultMap 的区别

1resultType 适用于简单查询,要求查询结果的列名与实体类的属性名完全匹配,不支持复杂的结果映射(如嵌套对象)。与之相反,resultMap 可以处理复杂的情况,支持嵌套对象、嵌套集合等,适用于多表关联查询等复杂场景

2 使用 resultType 要求 实体类和 数据库之前 需要存在映射关系,如果不是则无法将数据,传递给实体类的成员变量。而 resultMap 不必遵循这种关系 

 

通过图片,可知 数据库的列名和成员变量要求保持一致,在使用 resultType 


3 resultMap的使用

应用场景:假设是订单和用户的关系。一个用户对应多个订单;一个订单对应一个用户。在实体类 user 类 和 实体类对应的映射文件 描述这种情况

demo(案例)

User 类

Product 类

mapper/dao   UserMapper接口

    // 查询用户 所有商品信息
   List<Product> queryProduct(User user);

UserMapper.xml映射文件

 <resultMap id="order" type="fs.entity.Order">
<!-- id 标签 表示为一个表的主键 column 表示为表中的列名 ,property 表示为 类中的属性名       -->
        <id property="id" column="id"/>
<!-- result 标签 表示一般的字段        -->
        <result property="name" column="name"/>
        <result property="price" column="price"/>
<!--collection 标签  使用 <collection> 处理一对多关系   ,使用 <association> 处理一对一关系    -->
        <collection property="products" ofType="fs.entity.Product">
            <id property="id" column="pid"/>
            <result property="name" column="pname"/>
            <result property="price" column="pprice"/>
<!--            		<!-
			collection:对关联查询到的多条记录映射到集合对象中
			property:将查询到的多条记录映射到User类的那个属性中
			ofType: 指明集合中的元素的类型
		 -->

        </collection>
    </resultMap>

id: 唯一标识此 resultMap。
type: 指定要映射到的 Java 类型(可以是全限定名或别名)。
<id> 和 <result> 子元素分别用于映射主键和普通属性。property 属性对应于 Java Bean 的属性名,column 属性对应于 SQL 查询结果中的列名。

collection 标签  使用 <collection> 处理一对多关系   ,使用 <association> 处理一对一关系

association
association:用于映射关联单个对象信息 
property:关联的属性名,就是将用户对象关联到Order的那个属性
javaType: 属性的类型

collection

collection:对关联查询到的多条记录映射到集合对象中

property:将查询到的多条记录映射到User类的那个属性中

ofType: 指明集合中的元素的类型


使用 resultMap
在查询语句中引用这个 resultMap

    <select id="queryProduct" parameterType="fs.entity.User" resultMap="order">
// sql 语句
    </select>

typeAliases(类型别名) 的使用

mybatis支持别名

别名映射的类型
_bytebyte
_longlong
_shortshort
_intint
_integerint
_doubledouble
_floatfloat
_booleanboolean
stringString
byteByte
longLong
shortShort
intInteger
integerInteger
doubleDouble
floatFloat
booleanBoolean
dateDate
decimalBigDecimal
bigdecimalBigDecimal

自定义别名

在mybatis-config.xml中配置:

<typeAliases>
    <!-- 单个别名定义 -->
    <typeAlias alias="user" type="org.csmf.mybatis.entity.User"/>
    <!-- 批量别名定义,扫描整个包下的类,别名为类名(首字母大写或小写都可以) -->
    <package name=" org.csmf.mybatis.entity "/>
    <package name="其它包"/>
</typeAliases>

使用别名:


Mapper 代理模式

了解 原始Dao开发方法

想要了解 Mapper 代理模式 ,就要先知道 原始Dao开发方法

使用Mybatis开发Dao,通常有两个方法,即原始Dao开发方法Mapper接口开发方法。

传统的DAO开发模式

 dao/mapper 持久层接口中的方法
	/**
  	 * 根据ID查询User
  	 * @param id  用户Id
  	 * @return  用户信息
  	 * @throws Exception
  	 */
  	public User findUserById(int id) throws Exception;
 dao/mapper 持久层 接口实现 类
	//需要往UserDaoImpl注入SQLSessionFactory
  	private SqlSessionFactory sqlSessionFactory;
  	
  	//通过构造方法注入
  	public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
  		this.sqlSessionFactory = sqlSessionFactory;
  	}
  
  	@Override
  	public User findUserById(int id) throws Exception {
  		/**
  		 * 1.得到SqlSession
  		 * 2.调用SqlSession对应的方法(selectOne)来操作数据库
  		 * 3.关闭SqlSession
  		 * 4.返回结果
  		 */
  		SqlSession sqlSession = sqlSessionFactory.openSession();
  		User user = sqlSession.selectOne("test.findUserById", id);
  		sqlSession.close();
  		return user;
  	}

发现如果在接口中写很多关于操作数据库的方法,那么在接口的实现类中,每次都需要创建sqlSession 对象。基于代码的重复,于是使用依靠 Java动态代理技术的mapper 代理模式


mapper 代理模式

mapper 代理模式 ,被mybatis 官方所推崇。因此 很多情况 实现  dao/mapper持久层 的操作 都是使用 mapper 代理模式

mapper 代理模式 的优点

1 mapper 代理模式 省略了 接口的实现类,使用 映射文件 书写需要的sql 语句,具体如何去实现接口的方法有代理对象调用 

2 代理类去实现对应的接口,调用 相关方法,这些操作都已经封装好了。不需要人为创建代理类,完成这些操作,更加简单,方便


mapper 代理模式 的原则

1 在mapper.xml中namespace写的是对应Mapper接口的全限定名

  1. Mapper接口方法名和Mapper.xml中定义的每个标签如select,update等中的id相同

  2. Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/979561.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【无标题】ABP更换MySql数据库

原因&#xff1a;ABP默认使用的数据库是sqlServer&#xff0c;本地没有安装sqlServer&#xff0c;安装的是mysql&#xff0c;需要更换数据库 ABP版本&#xff1a;9.0 此处以官网TodoApp项目为例 打开EntityFrameworkCore程序集&#xff0c;可以看到默认使用的是sqlServer&…

Oracle 查询表空间使用情况及收缩数据文件

本文介绍Oracle收缩数据文件的相关操作&#xff0c;运维工作中有时会需要通过收缩数据文件来释放磁盘空间。 数据文件初始化方式&#xff1a; 1.我们创建表空间一般有两种方式初始化其数据文件&#xff0c;即指定初始大小为32G&#xff08;很大的值&#xff09;或指定初始大小为…

执行yum -y install npt 报错解决

Cannot find a valid baseurl for repo: base/7/x86_64 解决办法 一、检查网络连接 确保你的服务器可以访问互联网。你可以使用 ping 命令来测试&#xff1a; ping www.baidu.com 若能访问外网&#xff0c;则网络没问题&#xff0c;否则检查网络 二、修改CentOS-Base.rep…

java后端开发day23--面向对象进阶(四)--抽象类、接口、内部类

&#xff08;以下内容全部来自上述课程&#xff09; 1.抽象类 父类定义抽象方法后&#xff0c;子类的方法就必须重写&#xff0c;抽象方法在的类就是抽象类。 1.定义 抽象方法 将共性的行为&#xff08;方法&#xff09;抽取到父类之后。由于每一个子类执行的内容是不一样…

歌曲分类和流行度预测

1. 项目介绍 本项目从kaggle平台上下载了数据集&#xff0c;该数据集包含了3万多首来自Spotify API 的歌曲&#xff0c;共有23个特征。首先对数据集进行预处理&#xff0c;如重复行、缺失值、标准化处理等。再对预处理后的数据进行探索性分析&#xff0c;观察各变量的分布情况&…

梳理vite构建vue项目可选的配置和组件

梳理vite构建vue项目可选的配置和组件 &#x1f4a1; 列举通过vite构建vue3项目时可能会使用到的配置和组件&#xff0c;在搭建项目初期可以提前规划&#xff0c;提高开发效率&#xff0c;后续会不断扩展… unplugin-vue-router 可以监听views文件夹中的文件变化&#xff0c…

密码学(哈希函数)

4.1 Hash函数与数据完整性 数据完整性&#xff1a; 检测传输消息&#xff08;加密或未加密&#xff09;的修改。 密码学Hash函数&#xff1a; 构建某些数据的简短“指纹”&#xff1b;如果数据被篡改&#xff0c;则该指纹&#xff08;以高概率&#xff09;不再有效。Hash函数…

ESP32-S3 42引脚 语音控制模块、设备运转展示 GOOUUU TECH 果云科技S3-N16R8 控制舵机 LED开关 直流电机

最近还是想玩了下esp32&#xff0c;基于原来的开发板&#xff0c;看见佬做了一个语音识别的项目&#xff0c;通过这个语音识别可以控制LED开关和直流电机这些&#xff0c;详情可见视频&#xff08;推荐&#xff09;具体硬件就在下方。 信泰微】ESP32-S3 42引脚 语音控制模块、…

《Qt窗口动画实战:Qt实现呼吸灯效果》

Qt窗口动画实战&#xff1a;Qt实现呼吸灯效果 在嵌入式设备或桌面应用中&#xff0c;呼吸灯效果是一种常见且优雅的UI动画&#xff0c;常用于指示系统状态或吸引用户注意。本文将介绍如何使用Qt动画框架实现平滑的呼吸灯效果。 一、实现原理 利用Qt自带的动画框架来实现&…

数据库测试

TPCH 22条SQL语句分析 - xibuhaohao - 博客园 TPCH模型规范、测试说明及22条语句 - zhjh256 - 博客园 TPC-DS 性能比较&#xff1a;TiDB 与 Impala-PingCAP | 平凯星辰 揭秘Oracle TPC-H性能优化&#xff1a;如何提升数据库查询速度&#xff0c;揭秘实战技巧与挑战 引言 T…

《Kafka 理解: Broker、Topic 和 Partition》

Kafka 核心架构解析:从概念到实践 Kafka 是一个分布式流处理平台,广泛应用于日志收集、实时数据分析和事件驱动架构。本文将从 Kafka 的核心组件、工作原理、实际应用场景等方面进行详细解析,帮助读者深入理解 Kafka 的架构设计及其在大数据领域的重要性。 ​1. Kafka 的背…

Day11,Hot100(贪心算法)

贪心 &#xff08;1&#xff09;121. 买卖股票的最佳时机 第 i 天卖出的最大利润&#xff0c;即在前面最低价的时候买入 class Solution:def maxProfit(self, prices: List[int]) -> int:min_price prices[0]ans 0for price in prices:ans max(ans, price - min_price…

STM32呼吸灯实验手册(TIM定时器)

一、实验目标 使用TIM定时器的PWM模式控制LED亮度实现LED渐亮渐灭的呼吸灯效果掌握HAL库的TIM配置方法 二、硬件准备 开发板&#xff1a;STM32F103C8T6LED模块&#xff1a;LED串联220Ω电阻两组USB-TTL调试器硬件连接 三、软件配置&#xff08;STM32CubeMX&#xff09; 打开…

51页精品PPT | 农产品区块链溯源信息化平台整体解决方案

PPT展示了一个基于区块链技术的农产品溯源信息化平台的整体解决方案。它从建设背景和需求分析出发&#xff0c;强调了农产品质量安全溯源的重要性以及国际国内的相关政策要求&#xff0c;指出了食品安全问题在流通环节中的根源。方案提出了全面感知、责任到人、定期考核和追溯反…

python-leetcode-删除并获得点数

740. 删除并获得点数 - 力扣&#xff08;LeetCode&#xff09; 解法 1&#xff1a;动态规划&#xff08;O(n) 时间&#xff0c;O(n) 空间&#xff09; class Solution:def deleteAndEarn(self, nums: List[int]) -> int:if not nums:return 0# 统计每个数的贡献points Cou…

Grafana服务安装并启动

Grafana服务安装并启动 1、介绍2、下载Grafana3、解压缩文件4、启动Grafana服务5、增加数据源,填写Prometheus访问地址6、增加图表 1、介绍 Grafana是一个开源的可视化系统监控和警报工具包。 2、下载Grafana 介绍&#xff1a;Grafana是一个开源的可视化系统监控和警报工具包…

6. grafana的graph简介

1. Settings功能 2. Visualization功能 &#xff08;可视化的方式&#xff0c;后续会写一些&#xff09; 3. Display 功能&#xff08;显示方面的设置&#xff09; bars 柱状图方式显示 lines&#xff08;不选不会出功能&#xff09; line width 线条的粗细 staircase 会让折…

react18自定义hook实现

概念&#xff1a;自定义 hook 是一种将组件逻辑提取到可复用函数中的方式&#xff0c;它允许你在多个组件中共享相同的状态和行为。自定义 hook 的本质上是一个普通的 JavaScript 函数&#xff0c;它可以使用 React 内部的 hook&#xff08;如 useState、useEffect、useContext…

千峰React:函数组件使用(3)

多组态进行正确记忆 首先看这个代码 import { useState } from reactfunction App() {const [count, setCount] useState(0)const [count2, setCount2] useState(0)const [count3, setCount3] useState(0)const handleClick () > {setCount(count 1)}return (<div&…

xss-labs搭建及学习

搭建 搭建过程与一般的网站搭建差不多 参考资料 当出现这个界面就是成功了 学习 学习资料 xss概念理解&#xff1a;XSS跨站脚本攻击 xss常见标签&#xff1a;XSS常见触发标签 level1-直接打 这里提示payload长度为4查看一下源码 发现get传参name的值test插入了html里头&am…