一、摘要
MyBatis是一个优秀的持久层框架,通过XML映射文件定义insert标签或使用注解@Insert来添加数据,使用XML映射文件定义select标签或注解@Select进行查询数据,可以过RowBounds对象进行内存分页或使用分页插件(如PageHelper)来实现数据库层面的分页查询。MyBatis-Flex是MyBatis的增强工具,它提供了一系列的注解来简化数据库操作。本文将介绍如何使用MyBatis的原生功能来实现查询和分页。
1. MyBatis 的特点和优势
- SQL编写灵活
- 映射方式灵活
- 支持动态SQL
- 易于整合
- 缓存机制
- 事务控制
- 简单性
- 减少JDBC编码
- 支持复杂映射
- 支持插件机制,可以通过插件扩展MyBatis的功能,如分页插件
- MyBatis的性能非常接近原生JDBC,因为它只是对JDBC的简单封装
- 跨数据库平台:支持多种数据库,如MySQL、Oracle、SQL Server、PostgreSQL等
- 拥有活跃的社区和丰富的文档,方便开发者学习和解决问题
二、 MyBatis 查询基础
1.配置 MyBatis
前提:创建Spring Boot项目(mybatis-flex-demo),在pom.xml文件中添加Maven依赖和在resources文件项目下的application.properties文件改为application.yml配置数据源。可以参考:MyBatis-Flex的创建与使用_mvn配置mybatis-flex-CSDN博客
(1)第一步:给数据表添加数据 (没有数据表先创建)
创建数据表代码:
CREATE TABLE IF NOT EXISTS `tb_account`
(
`id` INTEGER PRIMARY KEY auto_increment,
`user_name` VARCHAR(100),
`age` INTEGER,
`birthday` DATETIME);
INSERT INTO tb_account(id, user_name, age, birthday)
VALUES (1, '张三', 18, '2020-01-11'),
(2, '李四', 19, '2021-03-21'),
(3, '王五', 20, '2021-04-21');
效果如下:
给数据表添加一下数据:
INSERT INTO tb_account(id, user_name, age, birthday)
VALUES (null, '小张', 22, '2002-03-28'),
(null, '小许', 21, '2020-05-16'),
(null, '小沈', 20, '2023-08-21'),
(null, '小吴', 18, '2022-07-16');
效果如下:
(2)第二步:在resources中新建mapper文件夹创建xml文件 ,创建和接口名一样的xml
2.定义 Mapper 接口
在MyBatis中,提供了@Insert、@Delete、@Update、@Select4个注解,用于对Mapper的方法进行配置,用于原生编写原生SQL进行增删改查,在MyBatis-Flex我们一样可以使用这些注解。Mapper接口是与数据库交互的入口。通过定义接口方法,可以映射到相应的SQL语句。
(1)在AccountMapper接口中使用@Select等MyBatis原生注解,代码如下:
public interface AccountMapper extends BaseMapper<Account> {
//@Select原生注解
@Select("select * from tb_account where id = #{id}")
Account selectById(@Param("id") int id);
}
效果如下:
(2)在开始使用xml之前,我们需要添加如下配置,告知mybatis的xml存放路径。 在application.yml口中添加,代码如下:
mybatis-flex:
mapper-locations:
- classpath*:/mapper/*.xml
效果如下:
配置完成后,我们就可以编写自己的xml和mapper代码了。
3.编写 XML 映射文件
XML映射文件用于定义SQL语句和接口方法的映射关系。
(1)在Java文件mapper中AccountMapper接口中编写代码:
//@Insert原生注解
@Insert("insert into user values (null,#{user_name},#{age},#{birthday})")
int insertUser(@Param("user_name")String user_name,@Param("age") int age,@Param("birthday") String birthday);
Account selectByName(@Param("user_name") String user_name);
效果如下:
(2)AccountMapper接口对应的xml代码:
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!--java包下存放映射文件的接口文件的路径-->
<mapper namespace="com.mybatisflex.demo.mapper.AccountMapper">
<!-- selectByName -->
<!-- bean包中Account的路径 -->
<select id="selectByName" resultType="com.mybatisflex.demo.entity.Account">
select * from `tb_account` ${qwSql} limit ${pageOffset}, ${pageSize};
</select>
</mapper>
效果如下:
三、 实现查询
1. 简单查询
获取单条数据,代码如下:
@Test
void test1(){
Account a=accountMapper.selectById(2);
System.out.println(a);
}
效果如下:
四、 分页查询
1. 分页原理
分页查询的基本原理是限制查询结果的数量,在数据库中获取数据时,并不一次性返回所有的数据,而是根据指定的参数返回数据的一部分。通常通过SQL的LIMIT和OFFSET子句实现,它们可以限制返回的记录数和跳过记录的开始位置。
2. 在XMl里定义select
xml代码如下:
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<!--java包下存放映射文件的接口文件的路径-->
<mapper namespace="com.mybatisflex.demo.mapper.AccountMapper">
<!--分页查询-->
<select id="selectAll" resultType="com.mybatisflex.demo.entity.Account">
select * from `tb_account` ${qwSql} limit ${pageOffset}, ${pageSize}
</select>
<!--需要写对应的count查询-->
<select id="selectByName_COUNT" resultType="long">
select count(*) from `tb_account` ${qwSql}
</select>
</mapper>
效果如下:
其SQL语句代码:
-- 查询数据量
select count(*) from `tb_account` WHERE `age` = 18 AND `id` >= 0
-- 查询数据
select * from `tb_account` WHERE `age` = 18 AND `id` >= 0 limit 0, 10
测试语句:
@Test
void test2() {
QueryWrapper zw = QueryWrapper.create()
.where(Account::getId).gt(0);
Page<Account> accountPage = accountMapper
.xmlPaginate("selectByName", Page.of(1, 4), zw);
System.out.println(accountPage);
}
效果如下:
五、 注意事项
1.性能考虑
在进行分页查询时,应考虑查询性能。对于大量数据,使用数据库层面的分页(如 LIMIT)比内存分页更高效。
2.SQL 注入防护
使用参数化查询可以有效防止SQL注入攻击。
六、 结论
MyBatis提供了灵活的数据库操作方式,无论是通过注解还是XML配置,都能有效地支持CRUD操作和分页查询。通过合理的设计和优化,可以提高应用的性能和安全性。