当前位置: 首页 > news >正文

MyBatis详解

MyBatis

MyBatis是持久层框架(持久层: 和数据库进行交互的代码;框架: 半成品软件模型)。简化了JDBC开发(使用Java提供的标准Api来操作和访问数据库)。

JDBC缺点

JDBC开发的流程:

  1. 注册驱动(Class.forName(“com.mysql.jdbc.Driver”))
  2. 建立连接
  3. 编写sql
  4. 执行sql,获取数据
  5. 解析数据,封装对象

对应下面的代码:

// 1. 注册数据库驱动
Class.forName("com.mysql.jdbc.Driver");// 2. 建立Connection连接
String url = "jdbc:mysql://db1?useSSL=false";
String uname = "root";
String pwd = "1234";
Connection conn = DriverManager.getConnection(url, uname, pwd);// 3. 设置性别参数为男
String gender = "男";// 4. 定义SQL查询语句
String sql = "select * from tb_user where gender = ?";// 5. 创建预处理语句对象
PreparedStatement pstmt = conn.prepareStatement(sql);// 6. 设置参数值
pstmt.setString(1, gender);// 7. 执行SQL查询
ResultSet rs = pstmt.executeQuery();// 8. 创建用户对象和用户列表
User user = null;
ArrayList<User> users = new ArrayList<>();// 9. 遍历结果集
while (rs.next()) {// 从结果集中获取数据int id = rs.getInt("id");String username = rs.getString("username");String password = rs.getString("password");// 创建User对象并设置属性user = new User();user.setId(id);user.setUsername(username);user.setPassword(password);user.setGender(gender);// 将用户对象添加到列表中users.add(user);
}

硬编码: 配置信息和sql语句写到了代码里,之后如果改动需要改动代码。

操作繁琐: 手动设置sql语句的参数、手动解析结果并封装到对象中。

MyBatis如何简化?

xml配置文件: 对于硬编码问题,MyBatis使用将配置信息和sql语句都写到xml配置文件中来简化的。

配置信息:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><environments default="dev"><environment id="dev"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/test"/><property name="username" value="root"/><property name="password" value="password"/></dataSource></environment></environments><mappers><mapper resource="mapper/UserMapper.xml"/></mappers>
</configuration>

sql语句:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.example.mapper.UserMapper"><select id="findUserById" parameterType="int" resultType="com.example.model.User">SELECT id, name, age FROM user WHERE id = #{id}</select></mapper>

对于操作繁琐问题,mybatis只需要一行代码就能把参数设置和封装结果解决完,让这两个操作实现了自动完成。

// 1. 加载MyBatis配置文件,获取SqlSessionFactory
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);// 2. 获取SqlSession对象,用它来执行sql
SqlSession sqlSession = sqlSessionFactory.openSession();// 3. 执行sql
List<User> users = sqlSession.selectList(statement: "test.selectAll");
System.out.println(users);// 4. 释放资源
sqlSession.close();

SqlSession

MyBatis中的SqlSession类似于JDBC中的Connection,但是提供了更高级别的抽象和封装。

通过xml配置文件获取SqlSessionFactory,然后获取SqlSession,也就类似于JDBC中的Connection

Mapper代理开发

上文使用SqlSession来执行sql,还是会存在硬编码的问题,就是我们要知道sql配置文件中对应的sql语句的id叫什么。写起来还是不太方便。所以还可以使用Mapper代理开发,更加方便。

具体细节就不赘述。简单讲一讲实现。

创建一个mapper接口,用来配合mapper.xml文件,这个接口和mapper.xml要放在同一个路径下(spring可以通过更改扫描路径)。mapper.xml中的namespace要是接口的全限定名,并且mapper接口要有一个与mapper.xml对应sql的id相同名的方法,返回值也要和mapper.xml中对应sql的返回值相同。

然后通过SqlSession获取mapper接口的代理对象,使用代理对象直接调用接口的方法就能直接执行sql语句并且获取到对应的返回值了。

数据库表列名和实体属性名不一致

起别名: sql语句查询的时候可以通过as给不一致的列表起与实体属性名一致的别名。

resultMap: 定义完成不一致的属性名和列名的映射,然后使用resultMap替换 标签中的resultType。

#{}和${}的区别和使用

mapper接口中带参数的方法需要在sql的select语句中搭配一个占位符,而占位符有两种,分别是${}和#{},他们两个是不同的。

${}: 会把参数替换占位符,拼接上原来的sql语句,然后组成一个完整的sql语句去进行sql查询,类似jdbc的Statement做的一样,不会预编译。

#{}: 会进行sql语句的预编译,然后会把参数替换掉预编译的占位符上,可以有效防止sql注入的问题。类似PreparedStatement。

常见标签

1. <select>

用于定义查询语句,执行数据库的SELECT操作,返回结果集。
常用于查询数据,支持动态SQL和映射。


2. @Param

这是MyBatis的注解,用于给Mapper接口方法的参数命名。
当接口方法有多个参数时,使用@Param("name")可以在SQL中通过#{name}引用对应参数。


3. <set>

用于UPDATE语句中,动态拼接SET子句。
会自动处理多余的逗号,避免SQL语法错误。

示例:

xml复制编辑<set><if test="name != null">name = #{name},</if><if test="age != null">age = #{age},</if>
</set>

4. <foreach>

用于遍历集合(List、数组、Map等),动态生成SQL片段,常用于批量操作和IN条件。

示例:

xml复制编辑WHERE id IN
<foreach item="id" collection="idList" open="(" separator="," close=")">#{id}
</foreach>

5. <where>

用于动态生成WHERE子句,会智能处理多余的ANDOR
如果内部没有条件,则不会生成WHERE关键字。


6. <insert>

定义插入语句,对应数据库的INSERT操作。
可以支持动态字段插入。


7. <delete>

定义删除语句,对应数据库的DELETE操作。
用于删除符合条件的数据。


8. <update>

定义更新语句,对应数据库的UPDATE操作。
常配合<set>标签使用,动态更新字段。


9. <choose>

类似Java中的switch-case,用于多个条件分支中选择一个执行。
包含<when><otherwise>子标签。

示例:

xml复制编辑<choose><when test="type == 'A'">...</when><when test="type == 'B'">...</when><otherwise>...</otherwise>
</choose>

参数传递

Mapper接口的方法中可以接收各种参数,可以接收

单个参数:

  1. POJO类型

属性名和参数占位符名称一致。

  1. Map集合

Map集合键名要和参数占位符一致。

  1. Collection

封装为map集合,map.put(“collection”,Collection集合),map.put(“arg0”,Collection集合)

  1. List

封装为map集合,map.put(“arg0”,List集合),map.put(“collection”,List集合),map.put(“list”,List集合)

  1. Array

封装为map集合,map.put(“arg0”,Array数组), map.put(“array”, Array数组)

  1. 其它类型

多个参数:

使用多个参数的时候,要使用@Param注解来定义参数的名称,这个名称要和sql语句的参数占位符一致,才能将这个参数替换到占位符上去。

ParamNameResolver封装参数: mapper接口方法如果有多个参数,那么这些参数就会被封装到一个Map集合中,key就是使用@Param定义的名称(没有@Param注解的话,默认就是arg0、arg1…和param0、param1…作为键值,使用@Param注解的话,替换的键名是argx的,paramx还存在),然后值就是参数传递过来的。

http://www.dtcms.com/a/309831.html

相关文章:

  • 面向对象学习(一)
  • 服务器地域选择指南:深度分析北京/上海/广州节点对网站速度的影响
  • Trice移植(Start with Trice)
  • 网站建设服务器从入门到上手
  • 层次聚类:无需“猜”K值,如何让数据自己画出“家族图谱”?
  • 31. 伪类和伪元素区别
  • PyTorch深度学习快速入门学习总结(四)
  • JS-第十九天-事件(一)
  • safari添加主屏及PWA启动方式
  • 玩转ChatGPT:寻找仪器用户手册
  • TEM在量子点发光材料领域的应用-测试GO
  • 汇川ITS7100E触摸屏交互界面开发(一)调试事项说明
  • BIFU币富探索合规新路径 助力用户玩转RWA
  • 两步走解决家庭路由器无法上网
  • Java 根据多个 MM-dd 日期计算总时长(包含当日和次日)
  • python PIL图片转base64字符串
  • [极客大挑战 2019]RCE ME
  • RockAI 的破壁之战:Yan 架构如何啃下“端侧炼丹”硬骨头?
  • Vue3 setup、ref和reactive函数
  • 元策联盈:深耕金融领域,赋能行业发展​
  • 【Flutter3.8x】flutter从入门到实战基础教程(四):自定义实现一个自增的StatefulWidget组件
  • 磁力搜索+磁力下载!无需解释!直接上车!
  • 工作好用小工具积累
  • EGE 流量开关 LG 518 GSP P11237
  • 异步函数被调用多次,多次处理同一个文件导致占用,如何让异步函数按顺序执行?
  • 书生浦语第五期L0G2
  • 【音视频】WebRTC 中的RTP、RTCP、SDP、Candidate
  • Ubuntu-Server-24.04-LTS版本操作系统如何关闭自动更新,并移除不必要的内核
  • C++在类的构造函数中调用另一个构造函数
  • STM32CubeIDE新建项目过程记录备忘(四)EXTI外部中断