前言
心中小乱,心情尚好…
一、MyBatis
其实就是感觉在java环境下操作数据库,只不过将SQL语句写到了MyBatis框架提供的注解里面(而且增删改查注解的名称也是和SQL的名称相同)。
//这里放一个通例
@Mapper //表明当前接口是一个MyBatis的Mapper接口,spring会自动的生成该接口的实现类对象并放入到IOC容器中进行管理。
public interface UseMapper{
//@操作类型("SQL语句")
@Delete("delete from tb where id = #{id}") //#{id}这是MyBatis所使用的一种参数占位符,后面会提
public void delete(Integer id);
}
1.基础操作
- 增
@Insert(“…”)
//双引号内部给入正常的SQL增添语句即可
有时候在新增记录后,可能会需要将该记录的主键值进行返回,需要通过**@Options注解**来实现
@Mapper
public interface EmpMapper {
//会自动将生成的主键值,封装到emp对象的id属性中
@Options(useGeneratedKeys = true,keyProperty = "id")
@Insert("insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time) values (#{username}, #{name}, #{gender}, #{image}, #{job}, #{entrydate}, #{deptId}, #{createTime}, #{updateTime})")
public void insert(Emp emp);
}
- 删
@Delete(“…”)
- 改
@Update(“…”)
- 查
@Select(“…”)
tip1: 在查询的过程中,可能会出现实体类的属性名和表格中的字段名不同的情况,如下图,左侧为实体类,右侧为数据库表格:
实体类中的deptId属性和数据库表格中的dept_id是对应的,但是由于名称不同,所以Mybatis不能实现自动封装,deptId值仍然是默认值null。(具体的封装其实也是通过反射来实现的)
解决方案:
- 起别名
在SQL语句中,对不一样的列名起别名,别名和实体类属性名一样
@Select("select id, username, password, name, gender, image, job, entrydate, " +
"dept_id AS deptId, create_time AS createTime, update_time AS updateTime " +
"from emp " +
"where id=#{id}")
public Emp getById(Integer id);
- 结果映射
通过 @Results及@Result 进行手动结果映射
@Results({@Result(column = "dept_id", property = "deptId"),
@Result(column = "create_time", property = "createTime"),
@Result(column = "update_time", property = "updateTime")})
@Select("select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time from emp where id=#{id}")
public Emp getById(Integer id);
- 开启驼峰命名
如果字段名与属性名符合驼峰命名规则,mybatis会自动通过驼峰命名规则映射
驼峰命名映射规则: abc_xyz => abcXyz
表中字段名:abc_xyz
类中属性名:abcXyz
//在application.properties中添加:
mybatis.configuration.map-underscore-to-camel-case=true
要使用驼峰命名前提是 实体类的属性 与 数据库表中的字段名严格遵守驼峰命名。
tip2:如果接口方法中方法的参数名和参数占位符参数名不同时,可以通过@Param注解来指定SQL语句中的参数名
tip3:上图中还提到了一个小点:concat(‘%’,#{name},‘%’),是正确使用模糊查询的方式,因为#{name}是用于参数绑定,并不能直接拼接到SQL语句中(直接拼接的是${…},但是有SQL注入风险),所以需要使用字符串拼接方法:concat()将#{name}拼接进去。
2.SQL注入和预编译SQL
2.1 SQL注入
SQL语句是通过拼接形成的,即用户所输入的参数会被拼接到SQL语句中。而所谓SQL注入其实就是用户通过在输入参数时通过输入特殊的字符来达到欺骗数据库去执行未预期的命令。举个例子:
//假设有一个登录表单,后台SQL查询如下:
SELECT * FROM users WHERE username = 'admin' AND password = 'password';
//如果攻击者在密码字段中输入 1' OR '1'='1,则查询变为:
SELECT * FROM users WHERE username = 'admin' AND password = '1' OR '1'='1';
//由于1==1恒成立,所以攻击者就会被允许进入系统,从而就骗过了认证功能
2.2 预编译SQL
预编译SQL是一种在数据库操作中提高性能和安全性的方法。它通过将SQL语句预先编译并缓存起来,然后在执行时只需绑定参数,从而避免了每次执行都重新编译SQL语句的开销。主要具有两个优势:
- 性能更高:编译一次之后会将编译后的SQL语句放到数据库服务器中缓存起来,后面再次执行这条语句时,不会再次编译,只需要根据给入的参数进行绑定后运行即可。
- 安全性更高:没有采用将参数拼接到SQL中的做法,而是先进行编译,然后采用参数绑定参数占位符的方式来进行参数传递,避免了SQL注入。
tips:参数占位符
例如通例中的#{id}其实就是参数占位符,SQL语句在编译时实际会先使用?代替参数生成预编译SQL,然后再通过绑定参数的方式将参数传递到?进行SQL语句的执行。
在Mybatis中提供的参数占位符有两种:${…} 、#{…}
#{…}
执行SQL时,会将#{…}替换为?,生成预编译SQL,会自动设置参数值
使用时机:参数传递,都使用#{…}。
MyBatis根据#{…}中的参数的名称,通过反射机制从对象中获取对应属性的属性值。
${…}
拼接SQL。直接将参数拼接在SQL语句中,存在SQL注入问题
使用时机:如果对表名、列表进行动态设置时使用
注意事项:在项目开发中,建议使用#{…},生成预编译SQL,防止SQL注入安全。
二、关于MyBatis的XML配置文件
MyBatis共有两种开发方式:注解、XML
注解主要应用于简单的增删改查功能,而更复杂的操作我们会选择使用XML来配置映射语句,即将SQL语句写在XML文件中。
在Mybatis中使用XML映射文件方式开发,需要符合一定的规范:
- XML文件的名称尽可能和Mapper接口一致,并且将XML映射文件和Mapper接口放在同一位置下(同包同名,但是要注意Mapper接口扔在java目录下,xml文件扔在resources目录下)。
tips:1.XML文件名称和Mapper接口并非必须一致,只是一致的话会具有更好的可读性。但是在XML文件中的namespace属性的全限名一定哟啊保证和Mapper接口一致,MyBatis通过namespace属性来实现XML文件和Mapper接口文件之间的映射。
2.(一个有些逆天的小坑,55555,属实深夜破防了,宣泄一下,小菜勿喷(doge))
//在java目录下创建com.it.mapper包会自动的生成一个三级目录文件
-com
-it
-mapper
//但是在resources目录下创建com.it.mapper包只会生成一个单级目录文件
-com.it.mapper
//但是使用Mybatis是要求要拥有同样的目录结构的,此时就需要以/来分隔目录结构从而生成一个三级目录结构
com/it/mapper
上述关于目录的问题可以在idea中创建包后到本地的项目工程文件中验证一下。
- XML映射文件中的namespace属性值必须和Mapper接口文件的全限名保持一致
- XML映射文件中SQL语句的id属性尽可能和Mapper接口文件中相映射的方法名保持一致,如果该方法有返回值,需要保整返回类型一致(java提供类型直接给入类型即可,自定义类型要给入全限名)
//返回java提供类型
<selet id="..." resultType="Integer">
//返回自定义类型
<select id="..." resultType="com.it.pojo.Emp">
tips: XML文件需要包涵dtd约束 (DTD(Document Type Definition,文档类型定义)是一种用于定义 XML 文档结构的约束机制。它规定了 XML 文档中可以出现的元素和属性,以及它们之间的关系和规则。使用 DTD 可以确保 XML 文档的有效性和一致性),可以直接从Mybatis官网复制(Mybatis中文网->入门:从案例中复制即可)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="">
</mapper>
总结
本文主要记录了MyBatis的使用以及XML文件的配置,本文主要供个人学习使用,如果有错误恳请大佬批评指正,如果恰好对你有所帮助,小子深感荣幸。夜深,共勉,晚安。