MyBatis的逆向工程,分页工具pageHelper以及注解开发
1. 逆向工程
1.1. 什么是逆向工程?
逆向工程就是根据数据库表逆向的生成Java的bean,SqlMapper.xml,以及Mapper接口类等等
1.2. 回顾编写一个mybatis的必要步骤
- 需要在mybatis的配置文件中的指定连接数据库的各种参数
- 根据数据库表创建SqlMapper.xml文件并指定namespace为Mapper接口全限定类名
- 编写Java类
因此,当只有数据库表需要生成其他文件(使用逆向工程)的时候需要指定好:
- 各个文件的生成路径(包括bean类位置,SqlMapper.xml的位置,Mapper接口的位置)
- Java类的类名
- Mapper接口名
- 参与逆向工程的数据库表
- 连接数据库的参数
1.3. 逆向工程使用
- 第一步:配置Maven的配置文件,新增模块
<!--定制构建过程-->
<build>
<!--可配置多个插件-->
<plugins>
<!--其中的一个插件:mybatis逆向工程插件-->
<plugin>
<!--插件的GAV坐标-->
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.1</version>
<!--允许覆盖-->
<!--当使用这个组件生成了一个Java类之后,之后每次使用会先清空然后在生成-->
<configuration>
<overwrite>true</overwrite>
</configuration>
<!--插件的依赖-->
<dependencies>
<!--mysql驱动依赖-->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.1.0</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
- 第二步:配置generatorConfig.xml
注意:该文件名必须是这个,而且必须在类的根路径下,即resources目录下面
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--
targetRuntime有两个值:
MyBatis3Simple:生成的是基础版,只有基本的增删改查。
MyBatis3:生成的是增强版,除了基本的增删改查之外还有复杂的增删改查。
-->
<context id="DB2Tables" targetRuntime="MyBatis3">
<!--防止生成重复代码-->
<plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin"/>
<commentGenerator>
<!--是否去掉生成日期-->
<property name="suppressDate" value="true"/>
<!--是否去除注释-->
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!--连接数据库信息-->
<!--注意:这一块需要根据自己的数据库进行配置-->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3307/xxx"
userId="root"
password="123123">
</jdbcConnection>
<!-- 生成pojo包名和位置 -->
<javaModelGenerator targetPackage="com.xxx.mybatis.pojo" targetProject="src/main/java">
<!--是否开启子包-->
<property name="enableSubPackages" value="true"/>
<!--是否去除字段名的前后空白-->
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!-- 生成SQL映射文件的包名和位置 -->
<sqlMapGenerator targetPackage="com.xxx.mybatis.mapper" targetProject="src/main/resources">
<!--是否开启子包-->
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!-- 生成Mapper接口的包名和位置 -->
<javaClientGenerator
type="xmlMapper"
targetPackage="com.xxx.mybatis.mapper"
targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!-- 表名和对应的实体类名-->
<table tableName="t_car" domainObjectName="Car"/>
</context>
</generatorConfiguration>
- 第三步:点击插件运行即可(没有的话刷新一下即可)
- 测试逆向工程(编写Maven测试类)
工具类:
package com.powernode.mybatis.utils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
public class SqlSessionUtil {
private SqlSessionUtil(){}
private static SqlSessionFactory sqlSessionFactory;
static {
try {
sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static ThreadLocal<SqlSession> local = new ThreadLocal<>();
public static SqlSession openSession(){
SqlSession sqlSession = local.get();
if (sqlSession == null) {
sqlSession = sqlSessionFactory.openSession();
// 将sqlSession对象绑定到当前的线程上
local.set(sqlSession);
}
return sqlSession;
}
// 关闭sqlSession对象
public static void close(SqlSession sqlSession){
if (sqlSession != null) {
sqlSession.close();
// 从当前线程中移除sqlSession对象和当前线程的绑定关系
local.remove();
}
}
}
测试类(Maven):
package com.bjpowernode.mybatis.test;
import com.powernode.mybatis.mapper.CarMapper;
import com.powernode.mybatis.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.io.IOException;
public class GeneratorTest {
@Test
public void testDeleteByPrimaryKey(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
int count = mapper.deleteByPrimaryKey(24L);
System.out.println(count);
sqlSession.commit();
sqlSession.close();
}
// CarExample是用来封装查询条件的
@Test
public void testSelect(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
// 查询一个
Car car = mapper.selectByPrimaryKey(23L);
//System.out.println(car);
// 查询所有,根据条件查询,没有条件就是查询所有
List<Car> cars = mapper.selectByExample(null);
//cars.forEach(System.out::println);
// 按照条件查询
// QBC风格,query by criteria 一种查询方式,比较面向对象,看不到sql语句
// 封装条件
CarExample carExample = new CarExample();
// 通过createCriteria()方法来创建条件
carExample.createCriteria()
.andBrandLike("宝马")
.andGuidePriceLessThan(new BigDecimal(50.0));
// 再添加or条件,前面和后面都加小括号
carExample.or().andCarTypeEqualTo("燃油车");
// select * from t_car where (brand like '%宝马%' and guide_price <= 50) or (car_type='燃油车');
mapper.selectByExample(carExample).forEach(System.out::println);
sqlSession.close();
}
}
2.分页工具
2.1. 分页原理
页码:第几页 pageNum
每一页显示的记录条数:pageSize
因此,实际上每一次在进行分页请求发送的时候,都是发送两个数据,一个是页码pageNum,一个是pageSize
数据格式为:uri?pageNum=1&pageSize=15
MySQL中的limit关键字:
select * from xxx limit 2; 表示显示查询结果的前2条数据。
select * from xxx limit 1,2; 表示从下标为1的数据开始(下标从0开始),显示两条数据。
因此通用的分页sql语句为:(只在MySQL中可以使用limit关键字)
select * from xxx limit (pageNum-1)*pageSize, pageSize
2.2. pageHelper使用
- 第一步:引入依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.3.1</version>
</dependency>
- 第二步:在mybatis的配置文件中配置
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
- 第三步:测试pageHelper
CarMapper.xml文件中不必需要写limit语句:
<select id="selectAll" resultType="car">
select * from t_car
</select>
Maven的测试方法:(需要工具类)注意开启分页的时机
import java.util.List;
public class CarMapperTest {
@Test
public void testSelectAll(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
// 在DQL语句执行之前,开启分页功能
int pageNum = 2;
int pageSize = 3;
PageHelper.startPage(pageNum, pageSize);
List<Car> cars = mapper.selectAll();
// 封装分页信息对象, 第二个参数表示页的按钮个数
PageInfo<Car> carPageInfo = new PageInfo<>(cars, 3);
/**
* startRow: 数据库中的开始下标
* endRow: 数据库中的结束下标
* total:总记录条数
* pages:总页数
* prePage:上一页页码
* nextPage:下一页页码
* isFirstPage:是否是第一页
* isLastPage:是否是最后一页
* hasPreviousPage:有没有上一页
* hasNextPage:有没有下一页
* navigatePages:页面的导航数
* navigateFirstPage:导航条的第一页是第几页
* navigateLastPage:导航条的最后一页是第几页
* navigatepageNums:当前的导航的页码
*/
//PageInfo{pageNum=2, pageSize=3, size=3, startRow=4, endRow=6, total=7, pages=3,
// list=Page{count=true, pageNum=2, pageSize=3, startRow=3, endRow=6, total=7, pages=3, reasonable=false, pageSizeZero=false}
// [Car{id=13, carNum='1000', brand='比亚迪汉', guidePrice=50.2, produceTime='2023-02-09', carType='新能源'},
// Car{id=16, carNum='8888', brand='丰田零度', guidePrice=20.0, produceTime='2023-09-12', carType='混动'},
// Car{id=20, carNum='6666', brand='沃尔沃s90', guidePrice=39.0, produceTime='2015-06-04', carType='燃油车'}],
// prePage=1, nextPage=3, isFirstPage=false, isLastPage=false,
// hasPreviousPage=true, hasNextPage=true, navigatePages=3, navigateFirstPage=1,
// navigateLastPage=3, navigatepageNums=[1, 2, 3]}
System.out.println(carPageInfo);
sqlSession.close();
}
}
3. MyBatis注解式开发
一般简单的SQL的语句,例如单表的CRUD,使用注解会是代码更加简练。
但是复杂的待条件的语句不建议使用注解开发,会让代码更加混乱。
CarMapper接口:
public interface CarMapper {
@Insert("insert into t_car values(null, #{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})")
int insert(Car car);
@Delete("delete from t_car where id=#{id}")
int delete(Long id);
@Update("update t_car set " +
"car_num = #{carNum}, brand=#{brand}, guide_price=#{guidePrice}, produce_time=#{produceTime}, car_type=#{carType} " +
"where id = #{id}")
int update(Car car);
@Select("select * from t_car")
List<Car> select();
// 开启了驼峰自动匹配就不用写result注解
@Select("select * from t_car where id= #{id}")
@Results({
@Result(property = "id",column = "id"),
@Result(property = "brand",column = "brand"),
@Result(property = "carNum",column = "car_num"),
@Result(property = "guidePrice",column = "guide_price"),
@Result(property = "produceTime",column = "produce_time"),
@Result(property = "carType",column = "car_type"),
})
Car selectById(Long id);
}
Maven测试类:
public class CarMapperTest {
@Test
public void testInsert(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
Car car = new Car(null, "1233", "帕萨特300TSL", 28.8, "2019-01-04", "燃油车");
int count = mapper.insert(car);
sqlSession.commit();
sqlSession.close();
}
@Test
public void testDelete(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
mapper.delete(25L);
sqlSession.commit();
sqlSession.close();
}
@Test
public void testUpdate(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
Car car = new Car(26L, "1244", "帕萨特300TSL", 30.2, "2019-01-04", "燃油车");
mapper.update(car);
sqlSession.commit();
sqlSession.close();
}
@Test
public void testSelect(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
List<Car> cars = mapper.select();
cars.forEach(System.out::println);
sqlSession.commit();
sqlSession.close();
}
@Test
public void testSelectById(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
Car car = mapper.selectById(26L);
System.out.println(car);
sqlSession.commit();
sqlSession.close();
}
}