Mybatis使用入门,这一篇就够了

mybatis中,封装了一个sqlsession 对象(里面封装有connection对象),由此对象来对数据库进行CRUD操做。php

运行流程

mybatis有一个配置的xml,用于配置数据源、映射Mapping,xml的文件名能够任取,为了方便,咱们仍是起mybatis-config.xmlhtml

咱们读取此配置的xml,得到一个sqlsession,以后由此对象类进行数据库的CRUD操做java

Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = factory.openSession();

入门使用

1. 建立实体类和Dao类

2. 配置mybatis-config.xml文件,配置数据源

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 引入外部资源文件-->
    <properties resource="jdbc.properties"/>

    <!-- 配置数据源环境 -->
    <environments default="development">
        <environment id="development">
            <!-- 数据库事务管理类型 -->
            <transactionManager type="JDBC"/>
			<!-- 数据源,type=pooled 说明是使用链接池方式,能够节省资源 -->
            <dataSource type="POOLED">
				<!-- 调用资源文件里的用户信息-->
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
</configuration>

3. 定义链接数据库工具,能够得到sqlsession对象

Dao类中每次进行CRUD操做,都要执行一次openSession方法来得到SqlSession对象,形成资源的浪费和代码的重复mysql

因此,和以前的JdbcUtil工具类同样,咱们也定义定义一个工具类MyBatisUtil,用来返回SQLSession对象git

static SqlSessionFactory sqlSessionFactory = null;

static {
	try {
		// 加载mybatis配置文件,并建立SqlSessionFactory实例
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		//这个build方法能够接受几种不一样的参数,如Reader/InputSteam等
		sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
	} catch (IOException e) {

	}
}

public static SqlSession getSqlSession() {
	return sqlSessionFactory.openSession();
}

public static void closeSqlSession(SqlSession sqlSession){
	if (sqlSession != null) {
		sqlSession.close();
	}
}

4. sql语句写在mapper中

mapper文件放在了resources下面程序员

Mybatis中,sql语句则是写在了xml文件中,这些xml文件也称为mapper映射文件github

mapper标签若是带有xmln属性,IDEA会报解析xml错误,得把xmln属性删除sql

<?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">
<!--
namespace: 命名空间,用于标识每个Mapper XML文件中的语句,预防在不一样的Mapper XML文件中存在相同的语句ID
-->
<mapper namespace="employeeMapper">
    <!--
        resultType: 也称为自动映射,只有在表的列名与POJO类的属性彻底一致时使用,会比较方便,全类名
    -->
	<select id="selectAll" resultType="com.wan.bean.Employee">
        select * from employee
    </select>
</mapper>

5. 在mybatis-config.xml文件中注册mapper

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 省略数据源配置-->
    <mappers>
        <mapper resource="com/wan/mapping/employeeMapper.xml"/>
		<!--若是还有mapper,则继续添加 -->
    </mappers>
</configuration>

6. dao类经过sqlsession进行查询

SqlSession sqlSession = MybatisUtil.getSqlSession();
// 调用语句,若是有参数,传入参数 
//参数为命名空间namespace+id,执行xml中的sql语句
List<Employee> list = sqlSession.selectList("employeeMapper.selectAll");

PS:若是是插入、更新和删除操做,还须要提交操做,默认是不会自动提交的数据库

sqlSession.commit();

补充

1.typeAliases标签

<select id="selectAll" resultType="com.wan.bean.Employee">
	select * from employee
</select>

resultType属性须要全类名,咱们可使用typeAliases标签来简化输入数组

typeAliases标签须要在mybatis-config.xml文件中进行设置

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <properties resource="jdbc.properties"/>
	<!--指定一个bean包 -->
    <typeAliases>
        <package name="com.wan.bean"/>
    </typeAliases>
    <!--省略配置数据源等-->
</configuration>

以后咱们的mapper文件中就能够这样写

<!--resultType就能够不用写全包名 -->
<select id="selectAll" resultType="Employee">
	select * from employee
</select>

我这里只介绍用法,详解请看下面的参考连接

参考 MyBatis 配置 typeAliases 详解

2.引入mapper的四种方法

1. 文件路径注册

<mappers>
	<mapper resource="com/wan/mapper/EmployeeMapper.xml" />
</mappers>

2. 包名扫描注册

<mappers>
	<package name="com.wan.mapper" />
</mappers>

使用这种,必须保证xxxMapper.java和xxxMapper.xml二者名字如出一辙!并且是要在同一包里

3. 类名注册

<mappers>
	<mapper class="com.shizongger.chapter2.mapper.UserMapper" />
</mappers>

4. url注册

<mappers>
	<mapper url="file:/home/shizongger/workspace/Chapter3/src/com/shizongger/chapter2/mapper/RoleMapper.xml" />
</mappers>

参考:配置MyBatis时报错信息的解决方案

SQLSession方法说明

方法名 说明
insert 插入
delete 删除
update 更新
selectOne 查找单行结果,返回一个Object
selectList 查找多行结果,返回一个List

使用和以前同样,第一个参数传入一个namespce+id,就能够找到指定的mapper文件里面的sql语句,并执行

CRUD

查询

Employee中,属性名和表的列名对应

<select id="selectAll" resultType="Employee">
	select * from employee
</select>

若是属性和表的列名不一致,可使用列名映射resultMap标签,(也就是自动转为别名)

<!--type也是须要全包名,因为以前定义的别名,因此就能够不写-->
<resultMap id="baseResultMap" type="Employee">
	<!--使用映射,把对应的列名映射为对应的属性 -->
	<id property="empno" column="EMPNO" />
	<result property="ename" column="ENAME"/>
	<result property="job" column="JOB"/>
	<result property="mgr" column="MGR"/>
	<result property="hiredate" column="HIREDATE"/>
	<result property="sal" column="SAL"/>
	<result property="comm" column="COMM"/>
	<result property="deptno" column="DEPTNO"/>
</resultMap>
<!--引用上面定义的resultMap-->
<select id="selectAll" resultMap="baseResultMap">
	select * from employee
</select>

带条件查询

<select id="selectById" parameterType="int" resultMap="baseResultMap">
	<!-- 若是参数类型是简单的基本或者包装类型,#{} 里面的能够任取,都是能够得到参数 -->
	select * from EMPLOYEE where EMPNO=#{id}
</select>

//使用
Employee e = sqlsession.selectOne("employeeMapper.selectById",7369);

上面的select语句至关于一个预编译语句

String s = "SELECT * FROM employee WHERE empno=?";
PreparedStatement ps = conn.prepareStatement(s);
ps.setInt(1,empno);

多条件查询

可使用where标签,固然,以前的单条件也可使用where标签,where标签好处是会自动删除多余的and

<select id="selectSelective" parameterType="Employee" resultMap="baseResultMap">
	select * from EMPLOYEE
	<where>
		<!--自动删除多余的and -->
		<!--#至关于从传入的bean对象(Employee)中经过getDeptno方法得到属性值 -->
		and deptno=#{deptno}
		and sal>=2000
	</where>
</select>

大小比较条件

条件中有大小比较,<号得经过CDATA存放条件

<select id="selectSelective" parameterType="Employee" resultMap="baseResultMap">
	select * from EMPLOYEE
	<where>
		<!--loSal为Employee的一个属性,#{loSal}至关因而经过Employee对象的get方法来得到loSal的属性值 -->
		and SAL>=#{loSal}
		<!--CDATA中的数据不会被解析器解析 -->
		<![CDATA[ and SAL<=#{hiSal} ]]>
	</where>
</select>

#与$区别:

${}用在咱们可以肯定值的地方,也就是咱们程序员本身赋值的地方。 而#{}通常用在用户输入值的地方!!

参考: MyBatis中#{}和${}的不一样和${}的妙用

模糊查询:

模糊查询中须要使用%等通配符,咱们能够在xml中定义好,自动拼接通配符

<select id="selectSelective" parameterType="Employee" resultMap="baseResultMap">
	select * from EMPLOYEE
	<where>
		<if test="ename != null">
			<!--使用bind标签,设置格式,自动拼接通配符 -->
			<bind name="pattern" value="'%' + ename + '%'"/>
			and ENAME like #{pattern}
		</if>
	</where>
</select>

动态查询

Mybatis中提供了if标签用来实现动态查询,和JSTL标签库使用相似

<select id="selectSelective" parameterType="Employee" resultMap="baseResultMap">
	select * from EMPLOYEE
	<where>
		<!--#{ename}实际上是经过Employee类中的get方法来得到对象的ename属性值 -->
		<if test="ename != null">
			and ename=#{ename}
		</if>
		<if test="job != null and job.trim().length>0">
			and JOB=#{job}
		</if>
		<if test="deptno != null">
			and DEPTNO=#{deptno}
		</if>
	</where>
</select>

插入

主键为序列

某个主键是由oracle中的序列生成的

<insert id="insert_1" parameterType="Employee">
	<!--
		keyProperty: 表示将从序列得到的值赋予实体的哪一个属性
		order: 表示主键值生成的方式,可取值:BEFORE | AFTER
			 因为不一样的数据库对插入的数据时主键生成方式是不一样,例如:
			 mysql and ms server: 主键生成方式为后生成方式。
			 oracle: 主键生成方式预生成.
	-->
	<!--调用数据库中的序列,并赋值给传入的Employee对象的empno属性 -->
	<selectKey keyProperty="empno" resultType="integer" order="BEFORE">
		select EMP_SEQ.nextval from dual
	</selectKey>
	<!--
		若是使用这种整表插入的方式,那当数据库表的某些列能够为空值时,我将要告诉底层的JDBC驱动如何处理空值的状况,这不是mybatis所须要的,
		而是底层有些JDBC驱动所需的特性,实际上就是让JDBC驱动去调用PrepareStatement.setNull()来设置空值
	 -->
	<!--若是是经常使用的数据类型int,date等,jdbcType能够省略不写 -->
	insert into EMPLOYEE
	values (#{empno},#{ename},#{job},#{mgr,jdbcType=INTEGER},#{hiredate,jdbcType=DATE},#{sal,jdbcType=DOUBLE},#{comm,jdbcType=DOUBLE},#{deptno,jdbcType=INTEGER})

</insert>

复用sql语句

把insert要插入的列名和数值写在sql标签里,以后方便重用,以后重用的时候须要使用include子标签拼接sql语句

<!--insert into employee(ENAME,JOB..) values(xx,xx) -->
<!--(ENAME,JOB..) -->
<sql id="insert_set_column">
	<!-- suffixOverrides属性,会自动把多余的“,”删除 -->
	<trim prefix="(" suffix=")" suffixOverrides=",">
		empno,
		<if test="ename != null">ENAME,</if>
		<if test="job != null">JOB,</if>
		<if test="mgr != null">MGR,</if>
		<if test="hiredate != null">HIREDATE,</if>
		<if test="sal != null">SAL,</if>
		<if test="comm != null">COMM,</if>
		<if test="deptno != null">DEPTNO,</if>
	</trim>
</sql>
<!--(xx,xx,xx) -->
<sql id="insert_values">
	<trim prefix="values(" suffix=")" suffixOverrides=",">
		#{empno},
		<if test="ename != null">#{ename},</if>
		<if test="job != null">#{job},</if>
		<if test="mgr != null">#{mgr},</if>
		<if test="hiredate != null">#{hiredate},</if>
		<if test="sal != null">#{sal},</if>
		<if test="comm != null">#{comm},</if>
		<if test="deptno != null">#{deptno},</if>
	</trim>
</sql>

<insert id="insert_2" parameterType="Employee">
	<selectKey keyProperty="empno" resultType="integer" order="BEFORE">
		select EMP_SEQ.nextval from dual
	</selectKey>
	insert into EMPLOYEE 
	<!--拼接sql -->
	<include refid="insert_set_column"/> 
	<include refid="insert_values"/>
</insert>

更新

<update id="update_1" parameterType="Employee">
	update EMPLOYEE
	<set>
		<if test="ename != null and ename.trim().length>0">ENAME=#{ename},</if>
		<if test="job != null and job.trim().length>0">JOB=#{job},</if>
		<if test="mgr != null">MGR=#{mgr},</if>
		<if test="hiredate != null">HIREDATE=#{hiredate},</if>
		<if test="sal != null">SAL=#{sal},</if>
		<if test="comm != null">COMM=#{comm},</if>
		<if test="deptno != null">DEPTNO=#{deptno},</if>
	</set>
   <!-- <where>若是带多条件的更依然可使<where>元素动态生成where子句</where> -->
   where EMPNO=#{empno}
</update>
<update id="update_2" parameterType="Employee">
	update EMPLOYEE
	<trim prefix="set" suffixOverrides=",">
		<if test="ename != null and ename.trim().length>0">ENAME=#{ename},</if>
		<if test="job != null and job.trim().length>0">JOB=#{job},</if>
		<if test="mgr != null">MGR=#{mgr},</if>
		<if test="hiredate != null">HIREDATE=#{hiredate},</if>
		<if test="sal != null">SAL=#{sal},</if>
		<if test="comm != null">COMM=#{comm},</if>
		<if test="deptno != null">DEPTNO=#{deptno},</if>
	</trim>
   <!-- <where>若是带多条件的更依然可使<where>元素动态生成where子句</where> -->
   where EMPNO=#{empno}
</update>

删除

<delete id="delete" parameterType="Employee">
	delete EMPLOYEE EMPNO=#{empno}
	<!--条件多的话也可使用<where>...</where> -->
</delete>

w3c select标签、delete标签等详解

高级使用

1.动态代理

咱们以前,上面都是在Dao类中写上一段sqlsession.selectOne/selectList,仍是比较麻烦

因此mybatis提供了一种简单的方法,使用动态代理(接口类)能够简化步骤

Mybatis中有这样的约定:

  1. 接口方法名与mapper中的id相同
  2. 接口方法参数与parameterType类型相同
  3. 接口方法的返回值类型与resultType类型相同

知足上面的条件,Mybatis就会将接口类中的方法和mapper中的sql语句一一对应起来,而不须要再次新建一个Dao,在Dao类里面编写方法

具体步骤:

1. 实体类编写

2. 新建接口类

若是方法的返回值为void,则mapper中就不须要定义resultType属性

若是方法返回值是List,mapper中的resultType为泛型T

package com.wan.mapping;

import com.wan.bean.Employee;

import java.util.List;

/**
 * @author StarsOne
 * @date Create in  2019/9/16 0016 20:38
 * @description
 */
public interface EmployeeMapper {
    List<Employee> selectAll();
}

2. 编写mapper.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">
<mapper namespace="com.wan.mapping.EmployeeMapper">
	<!--特例:返回值为list,resultType=bean类-->
    <select id="selectAll" resultType="Employee" >
        select * from employee
    </select>
</mapper>

3. 注册mapper

这里咱们因为使用了package注册mapper,必定保证xxmapper.java和xxmapper.xml两个名字相同,大小写都要同样

保证Mapper.xml和接口的那个Mapper在相同的包路径,在mybatis配置xml文件指定

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--省略数据源配置 -->...
    <!-- 注册SQL映射文件,在这些文件中写SQL语句 -->
    <mappers>
		<!--指定整个包中的所有Mapper -->
        <package name="com.wan.mapper"/>
    </mappers>
</configuration>

4. 使用

使用仍是和以前同样,得到SqlSession对象,此对象有个getMapper方法,把接口类传入,就能够回调接口的方法了

Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = factory.openSession();

EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
List<Employee> employees = mapper.selectAll();

接口类中的方法名与EmployeeMapper.xml中的对应

使用:

EmployeeMapper mapper = sqlsession.getMapper(EmployeeMapper.class);
mapper.selectById(7369);

2.遍历列表

Mybatis中提供了foreach标签,用于遍历

若是方法参数传入了一个List,可使用此标签遍历,例子以下:

<!--至关于select * from employee where job in (...)) -->
<select id="selectByJobs" parameterType="list" resultMap="baseResultMap">
	select * from EMPLOYEE
	<where>
		<foreach item="job" collection="list" open="JOB IN(" close=")" separator=",">
			#{job}
		</foreach>
	</where>
</select>

foreach标签的属性主要有 item,index,collection,open,separator,close,使用和JSTL标签里面的foreach标签差很少

属性名 说明
item 表示集合中每个元素进行迭代时的别名
index 指定一个名字,用于表示在迭代过程当中,每次迭代到的位置,
open 表示该语句以什么开始,
separator 表示在每次进行迭代之间以什么符号做为分隔 符,
close 表示以什么结束。

关键属性:collection

  1. 若是传入的是单参数且参数类型是一个List的时候,collection属性值为list
  2. 若是传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
  3. 若是传入的参数是多个的时候,咱们就须要把它们封装成一个Map了,固然单参数也能够封装成map,map的key就是参数名,因此这个时候collection属性值就是传入的List或array对象在本身封装的map里面的key

参考:mybatis 中 foreach collection的三种用法

3.考虑线程安全

使用ThreadLocal对象,保证每一个线程取出的SqlSession是同一个对象

方法 说明
void set(Object value) 设置当前线程的线程局部变量的值。
public Object get() 该方法返回当前线程所对应的线程局部变量。
public void remove() 将当前线程局部变量的值删除,目的是为了减小内存的占用,该方法是JDK 5.0新增的方法。
protected Object initialValue() 返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的。
static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();
//设置
threadLocal.set(sqlsession);
//取出
SqlSession s = threadLocal.get();

4.嵌套查询

<!-- 结果集映射: 列《》属性名 -->
<resultMap id="baseResultMap" type="Employee">
	<!-- 专门映射主键列 -->
	<id property="empno" column="EMPNO" />
	<result property="ename" column="ENAME"/>
	<result property="job" column="JOB"/>
	<result property="mgr" column="MGR"/>
	<result property="hiredate" column="HIREDATE"/>
	<result property="sal" column="SAL"/>
	<result property="comm" column="COMM"/>
	<result property="deptno" column="DEPTNO"/>
</resultMap>

<!-- 扩展另外一个结果映射 -->
<resultMap id="extendBaseResultMap" type="Employee" extends="baseResultMap">
	<association property="department" javaType="Department">
		<!-- 关联的嵌套结果 -->
		<id property="deptno" column="DEPTNO"/>
		<result property="dname" column="DNAME"/>
		<result property="location" column="LOC"/>
	</association>
</resultMap>


<!--
	1.嵌套结果(推荐使用)
	优势:性能好,一条语句把全部实体的数据彻底查询出来。
	缺点:对SQL编写的要求高了,由于涉及多表链接查询
-->
<select id="selectById" resultMap="extendBaseResultMap" parameterType="int">
	select e.EMPNO,
		  e.ENAME,
		  e.JOB,
		  e.MGR,
		  e.HIREDATE,
		  e.SAL,
		  e.COMM,
		  d.DEPTNO,
		  d.DNAME,
		  d.LOC
	from EMPLOYEE E
	  inner join DEPARTMENT D
		  on E.DEPTNO = D.DEPTNO
	 where E.EMPNO=#{id}
</select>

<!--
	2. 嵌套查询
	优势:编写SQL简单,无需作多表的链接查询;关联的实体经过单独的SQL语句查询并单独封装。
	缺点:执行了N+1条件语句。性能差
-->
<resultMap id="extendBaseResultMap_2" type="Employee" extends="baseResultMap">
	<association property="department" column="DEPTNO" select="selectDepartmentById" />
</resultMap>

<select id="selectDepartmentById" parameterType="int" resultType="Department">
	select deptno,
		   dname,
		   loc as location
	from DEPARTMENT where DEPTNO=#{id}
</select>

<select id="selectById_2" resultMap="extendBaseResultMap_2" parameterType="int">
	select e.EMPNO,
		  e.ENAME,
		  e.JOB,
		  e.MGR,
		  e.HIREDATE,
		  e.SAL,
		  e.COMM,
		  e.DEPTNO
	from EMPLOYEE E
	 where E.EMPNO=#{id}
	  <!-- or e.empno=7902 or e.empno=7844 -->
</select>

5.分页查询

分页的话,像之前那样使用三层嵌套查询也能够实现。

不过,有开发者为Mybatis开了个一个插件PageHelper,能够用来更为简单地使用分页查询

1.添加jar包

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
	<!--自动下载最新版本 -->
    <version>REALSE</version>
</dependency>

2.配置拦截器插件

<!-- 
    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.代码使用

只有在查询以前调用过startPage或者是offsetPage方法,后面的查询出来的List结果就会进行分页查询

下面的两个都是查询第一页,每一页有10条数据

//第二种,Mapper接口方式的调用,推荐这种使用方式。

PageHelper.startPage(1, 10);
List<Employee> employees = employeeMapper.selectAll();

//第三种,Mapper接口方式的调用,推荐这种使用方式。
PageHelper.offsetPage(1, 10);
List<Employee> employees = employeeMapper.selectAll();

这里提一下,这个插件还带有一个PageInfo类,里面有能够记录各类信息

刚开始,我觉得是和我以前本身封装的Page同样,详情请看Jsp学习笔记(4)——分页查询

可是,其实不同的,这个PageInfo就是一个封装而已,只是用来存放数据而已,里面有各类信息

属性 说明
pageNum 当前页号(第几页)
pageSize 每页的显示的数据个数
size 当前页的显示的数据个数
startRow 当前页面第一个元素在数据库中的行号
endRow 当前页面最后一个元素在数据库中的行号
pages 总页数
prePage 上一页的页号
nextPage 下一页页号
isFirstPage 是否为第一页
isLastPage 是否为最后一页
hasPreviousPage 是否有前一页
hasNextPage 是否有下一页
navigatePages 导航页码数
navigatepageNums 全部导航页号
navigatePages 导航条上的第一页
navigateFirstPage 导航条上的第一页
navigateLastPage 导航条上的最后一页

有个getTotal方法,能够得到查询结果的总记录数

PageHelper.startPage(1, 10);
List<Employee> employees = mapper.selectAll();
PageInfo<Employee> pageInfo = new PageInfo<>(employees);

原文出处:https://www.cnblogs.com/stars-one/p/11537439.html

相关文章
相关标签/搜索