10、MyBatis的自动生成代码、PageHelper分页插件

代码生成

方式一:官方jar

为了简化MyBatis的编写,官方推出了一个工具"mybatis-generator",Java编写的,通过这个工具可以生成数据库表对应的实体类、Mapper接口以及Mapper映射文件。

官网:

http://mybatis.org/generator/

快速入门指南:

http://mybatis.org/generator/quickstart.html

我们这里就是使用从命令提示符运行MyBatis Generator。

您必须创建XML配置文件才能从命令行运行MBG。如果文件名为“ generatorConfig.xml”,则以下任何命令行将运行MBG:

java -jar mybatis-generator-core-xxxjar -configfile generatorConfig.xml
java -jar mybatis-generator-core-xxxjar -configfile generatorConfig.xml -overwrite
参数解释
-configfile 文件名 (必需)指定配置文件的名称。
-overwrite(可选)如果指定,则如果发现现有Java文件的名称与生成的文件的名称相同,则现有Java文件将被覆盖。如果未指定,并且已经存在与生成文件同名的Java文件,则MBG会将新生成的Java文件以唯一名称(例如MyClass.java.1,MyClass.java.2,等等。)。

jar包是一系列class和资源文件的组合包,jar包如果配置了main函数所在的执行类,jar包是可以直接运行在虚拟机上的。

但是通过上面的方式,自动创建的pojo、mapper.java、mapper.xml没有在IDEA环境中,需要将生成的文件拷贝到项目中,不是特别方便。

上面的方式,具有通用的优点,任何IDE开发工具都可以使用。

方式二:IDEA

如果是IDEA,那么Easy Code插件可以解决这个问题。

在这里插入图片描述

首先需要在IDEA中连接数据库,下面是IDEA中连接MySQL数据库的驱动

在这里插入图片描述

1、使用Easy Code:

在这里插入图片描述

效果:如左侧所示。

2、使用mybatis-generate tool;

在这里插入图片描述

使用第二种的效果:

在这里插入图片描述

测试成功。

插件及其应用(PageHelper)

查询数据的时候,会遇到分页的问题(分页就是将满足条件的数据,按照每一页多少条这样的数据限定要求进行显示,程序中的查询大部分都需要使用到分页)。

分页我们分为

前端

前端需要分页的 数据(总条数,总页数,当前第几页[计算有没有上一页,有无下一页...],当前页码的数据[list])
显示分页操作条【栏】
挺麻烦的【前端可以使用分页插件】

后台

后台要编写两条sql
一条是查询全部数据【需要总条数】
一条sql查询当前页码的数据
service 或者 工具类中,计算,通过总条数以及每页条数,计算共有多少页....

数据库

数据库要有分页的sql语句,
mysql limit关键词【最简单的】
oracle rownum伪劣【最麻烦】
sqlserver top【子查询】

通过mybatis的分页插件,大大简化分页的sql以及分页的逻辑封装部分。

类似于Java Web中的过滤器【过滤器就是一个筛子,也就是说客户端请求服务器端资源,比如请求xxxservlet,过滤器就是在访问xxxservlet之前,会拦截客户端请求。相应地,之前servlet中返回数据,到客户端,现在返回数据之后,还要经过过滤器,才会到客户端】;

MyBatis中有一个接口,叫做拦截器Interceptor,允许我们定制更加灵活的程序,比如通过拦截器,可以拦截mybatis执行过程中一些重要的组件和方法。

比如通过编写拦截器,就可以得到程序运行过程中给的sql语句,并且我们可以修改sql语句。mybatis开放了这样的功能。

pageHelper就是利用了mybatis中提供的这个拦截器功能,可以对分页进行大大的简化。

官网:https://pagehelper.github.io/

如果你也在用 MyBatis,建议尝试该分页插件,这一定是最方便使用的分页插件。分页插件支持任何复杂的单表、多表分页。

使用方式:https://pagehelper.github.io/docs/howtouse/

1、引入分页插件

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.2.0</version>
</dependency>

2、配置拦截器插件

特别注意,新版拦截器是 com.github.pagehelper.PageInterceptorcom.github.pagehelper.PageHelper 现在是一个特殊的 dialect 实现类,是分页插件的默认实现类,提供了和以前相同的用法。

2.1、在MyBatis配置文件中配置拦截器

<!--
    plugins在配置文件中的位置必须符合要求,否则会报错,顺序如下:
    properties?, settings?,
    typeAliases?, typeHandlers?,
    objectFactory?,objectWrapperFactory?,
    plugins?,
    environments?, databaseIdProvider?, mappers?
-->
<plugins>
    <!-- com.github.pagehelper为PageHelper类所在包名 -->
    <plugin interceptor="com.github.pagehelper.PageInterceptor">
        <!-- 使用下面的方式配置参数,后面会有所有的参数介绍 -->
        <property name="param1" value="value1"/>
    </plugin>
</plugins>

3、使用

为分页查询新建一张表page,自动生成model、mapper.java、mapper.xml文件,然后添加100条数据。

@Data
public class Page implements Serializable {
    private Integer pid;

    private String pname;

    private Integer pcount;

    private Double pprice;

    private static final long serialVersionUID = 1L;
}

为表中初始化100条数据

@Test
public void initData() {
    try (SqlSession sqlSession = factory.openSession()) {
        PageMapper mapper = sqlSession.getMapper(PageMapper.class);
        for (int i = 1; i <= 100; i++) {
            Page page = new Page();
            page.setPname("java" + i);
            page.setPcount(i);
            page.setPprice(i + 0.1);
            mapper.insertSelective(page);
        }
        sqlSession.commit();
    }
}

全查测试:

//带查询条件的分页的查询方法
List<Page> select(Page page);
<resultMap id="BaseResultMap" type="org.westos.model.Page">
    <id column="pid" jdbcType="INTEGER" property="pid"/>
    <result column="pname" jdbcType="VARCHAR" property="pname"/>
    <result column="pcount" jdbcType="INTEGER" property="pcount"/>
    <result column="pprice" jdbcType="FLOAT" property="pprice"/>
</resultMap>

<sql id="Base_Column_List">
    pid, pname, pcount, pprice
</sql>

<select id="select" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List"/>
    from page
    <where>
        <if test="pid != null">
            and pid = #{pid}
        </if>
        <if test="pname != null">
            and pname like concat('%', #{pname}, '%')
        </if>
        <if test="pcount != null">
            and pcount = #{pcount}
        </if>
        <if test="pprice != null">
            and pprice = #{pprice}
        </if>
    </where>
</select>
//全查测试
@Test
public void select1() {
    try (SqlSession sqlSession = factory.openSession()) {
        PageMapper mapper = sqlSession.getMapper(PageMapper.class);
        List<Page> select = mapper.select(null);
        System.out.println(JSON.toJSONString(select, true));
    }
}

带参数的全查测试:

//全查测试,带参数
@Test
public void select2() {
    try (SqlSession sqlSession = factory.openSession()) {
        PageMapper mapper = sqlSession.getMapper(PageMapper.class);
        Page page = new Page();
        page.setPname("java2");
        List<Page> select = mapper.select(page);
        System.out.println(select.size());
        //11
    }
}

全查测试,带分页:

//全查测试,带分页
@Test
public void select3() {
    try (SqlSession sqlSession = factory.openSession()) {
        PageMapper mapper = sqlSession.getMapper(PageMapper.class);
        //配置分页,需要两个参数:1、pageNum第几页 2、pageSize页的大小
        PageHelper.startPage(2, 10);
        //第二页,查10条
        //limit (pageNum-1)*size, size
        //limit 0,10
        //limit 10,10
        //limit 20,10
        List<Page> select = mapper.select(null);
        System.out.println(select.size());
    }
}
==>  Preparing: SELECT count(0) FROM page 
==> Parameters: 
<==    Columns: count(0)
<==        Row: 100
<==      Total: 1
==>  Preparing: select pid, pname, pcount, pprice from page LIMIT ?, ? 
==> Parameters: 10(Long), 10(Integer)
<==    Columns: pid, pname, pcount, pprice
<==        Row: 11, java11, 11, 11.1
<==        Row: 12, java12, 12, 12.1
<==        Row: 13, java13, 13, 13.1
<==        Row: 14, java14, 14, 14.1
<==        Row: 15, java15, 15, 15.1
<==        Row: 16, java16, 16, 16.1
<==        Row: 17, java17, 17, 17.1
<==        Row: 18, java18, 18, 18.1
<==        Row: 19, java19, 19, 19.1
<==        Row: 20, java20, 20, 20.1
<==      Total: 10
10

全查测试,带条件,带分页

//全查测试,带条件,带分页
@Test
public void select4() {
    try (SqlSession sqlSession = factory.openSession()) {
        PageMapper mapper = sqlSession.getMapper(PageMapper.class);
        PageHelper.startPage(1, 5);
        Page page = new Page();
        page.setPname("java1");
        List<Page> select = mapper.select(page);
        System.out.println(JSON.toJSONString(select, true));

        PageHelper.startPage(2, 5);
        select = mapper.select(page);
        System.out.println(JSON.toJSONString(select, true));
    }
}
==>  Preparing: SELECT count(0) FROM page WHERE pname LIKE concat('%', ?, '%') 
==> Parameters: java1(String)
<==    Columns: count(0)
<==        Row: 12
<==      Total: 1
==>  Preparing: select pid, pname, pcount, pprice from page WHERE pname like concat('%', ?, '%') LIMIT ? 
==> Parameters: java1(String), 5(Integer)
<==    Columns: pid, pname, pcount, pprice
<==        Row: 1, java1, 1, 1.1
<==        Row: 10, java10, 10, 10.1
<==        Row: 11, java11, 11, 11.1
<==        Row: 12, java12, 12, 12.1
<==        Row: 13, java13, 13, 13.1
<==      Total: 5
[
	{
		"pcount":1,
		"pid":1,
		"pname":"java1",
		"pprice":1.1
	},
	{
		"pcount":10,
		"pid":10,
		"pname":"java10",
		"pprice":10.1
	},
	{
		"pcount":11,
		"pid":11,
		"pname":"java11",
		"pprice":11.1
	},
	{
		"pcount":12,
		"pid":12,
		"pname":"java12",
		"pprice":12.1
	},
	{
		"pcount":13,
		"pid":13,
		"pname":"java13",
		"pprice":13.1
	}
]
==>  Preparing: select pid, pname, pcount, pprice from page WHERE pname like concat('%', ?, '%') LIMIT ?, ? 
==> Parameters: java1(String), 5(Long), 5(Integer)
<==    Columns: pid, pname, pcount, pprice
<==        Row: 14, java14, 14, 14.1
<==        Row: 15, java15, 15, 15.1
<==        Row: 16, java16, 16, 16.1
<==        Row: 17, java17, 17, 17.1
<==        Row: 18, java18, 18, 18.1
<==      Total: 5
[
	{
		"pcount":14,
		"pid":14,
		"pname":"java14",
		"pprice":14.1
	},
	{
		"pcount":15,
		"pid":15,
		"pname":"java15",
		"pprice":15.1
	},
	{
		"pcount":16,
		"pid":16,
		"pname":"java16",
		"pprice":16.1
	},
	{
		"pcount":17,
		"pid":17,
		"pname":"java17",
		"pprice":17.1
	},
	{
		"pcount":18,
		"pid":18,
		"pname":"java18",
		"pprice":18.1
	}
]

全查测试,带分页,带分页数据的封装功能

//全查测试,带分页,带分页数据的封装功能
@Test
public void select5() {
    try (SqlSession sqlSession = factory.openSession()) {
        PageMapper mapper = sqlSession.getMapper(PageMapper.class);
        //在查询之前
        PageHelper.startPage(1, 10);
        List<Page> select = mapper.select(null);
        //分页信息封装类,通常写在查询之后
        PageInfo<Page> pageInfo = new PageInfo<>(select);
        System.out.println(JSON.toJSONString(pageInfo, true));
    }
}
{
	"endRow":10, 
	"hasNextPage":true,
	"hasPreviousPage":false,
	"isFirstPage":true,
	"isLastPage":false,
	"list":[
		{
			"pcount":1,
			"pid":1,
			"pname":"java1",
			"pprice":1.1
		},
		{
			"pcount":2,
			"pid":2,
			"pname":"java2",
			"pprice":2.1
		},
		{
			"pcount":3,
			"pid":3,
			"pname":"java3",
			"pprice":3.1
		},
		{
			"pcount":4,
			"pid":4,
			"pname":"java4",
			"pprice":4.1
		},
		{
			"pcount":5,
			"pid":5,
			"pname":"java5",
			"pprice":5.1
		},
		{
			"pcount":6,
			"pid":6,
			"pname":"java6",
			"pprice":6.1
		},
		{
			"pcount":7,
			"pid":7,
			"pname":"java7",
			"pprice":7.1
		},
		{
			"pcount":8,
			"pid":8,
			"pname":"java8",
			"pprice":8.1
		},
		{
			"pcount":9,
			"pid":9,
			"pname":"java9",
			"pprice":9.1
		},
		{
			"pcount":10,
			"pid":10,
			"pname":"java10",
			"pprice":10.1
		}
	],
	"navigateFirstPage":1,
	"navigateLastPage":8,
	"navigatePages":8,
	"navigatepageNums":[1,2,3,4,5,6,7,8],
	"nextPage":2,
	"pageNum":1,
	"pageSize":10,
	"pages":10,
	"prePage":0,
	"size":10,
	"startRow":1,
	"total":100
}

在说详细的原理:

如何自定义mybatis的拦截器【了解,mybatis提供插件这样的功能是为了更加灵活的执行一些操作,允许程序员查看或者操控mybatis运行的细节】

第一步:实现Interceptor接口

public interface Interceptor {    
    //拦截之后需要执行的方法  
    Object intercept(Invocation invocation) throws Throwable;    
    //返回代理对象  
    Object plugin(Object target);    
    //设置拦截器 运行的一些参数  
    void setProperties(Properties properties); 
}
package org.westos.util;

import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;

import java.sql.Connection;
import java.util.Properties;

/**
 * @author lwj
 * @date 2020/9/20 9:17
 */
@Intercepts({
        @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
public class MyBatisInterceptor implements Interceptor {
    /*
    * MyBatis允许拦截
    * 1、Executor执行器(SqlSession持有执行器)
    * 2、SQL语句执行 StatementHandler 拦截sql语句
    * 3、参数
    * 4、结果
    * (1)需要用@Intercepts注解来指定
    * (2)将该拦截器注册到mybatis-config.xml
    * */
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler sh = (StatementHandler) invocation.getTarget();
        MetaObject mo = SystemMetaObject.forObject(sh);
        //获得了运算后的sql
        Object value = mo.getValue("delegate.boundSql.sql");
        System.out.println("MyBatisInterceptor-->>" + value);
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object o) {
        return Plugin.wrap(o,this);
    }

    @Override
    public void setProperties(Properties properties) {

    }
}

第二步:配置拦截器

<plugins>
    <!-- com.github.pagehelper为PageHelper类所在包名 -->
    <!--<plugin interceptor="com.github.pagehelper.PageInterceptor">
        </plugin>-->
    <plugin interceptor="org.westos.util.MyBatisInterceptor"/>
</plugins>

测试,随意测试Mapper中的方法,在控制台中均可以查看到 mybatis运行过程中的sql语句

@Test
public void testSelectByPrimaryKey() {
    try (SqlSession sqlSession = factory.openSession()) {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.selectByPrimaryKey(1);
        System.out.println(JSON.toJSONString(user,true));
    }
}
MyBatisInterceptor-->>select
         
        uid, uname, upassword, u_nickname
     
        from user
        where `uid` = ?
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值