MyBatis基础知识点总结

news2024/11/15 8:38:03

MyBatis了解



MyBatis 是什么?

  1. MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架

  2. MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集

  3. MyBatis 可以使用简单的XML或注解用于配置和原始映射,将接口和Java的 POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录

  4. MyBatis 是一个半自动的ORM(Object Relation Mapping)框架

MyBatis 优点(与 JDBC,Hibernate 和 JPA 相比):

  • 轻量级,性能出色

  • SQL 和 Java 编码分开,功能边界清晰。Java 代码专注业务、SQL 语句专注数据

  • 开发效率稍逊于HIbernate,但是完全能够接受

JDBC

  • SQL 夹杂在 Java 代码中耦合度高,导致硬编码内伤

  • 维护不易且实际开发需求中 SQL 有变化,频繁修改的情况多见

  • 代码冗长,开发效率低

Hibernate 和 JPA

  • 操作简便,开发效率高

  • 程序中的复杂 SQL 需要绕过框架

  • 内部自动生产的 SQL,不容易做特殊优化

  • 基于全映射的全自动框架,大量字段的 POJO 进行部分映射时比较困难

  • 反射操作太多,导致数据库性能下降

搭建 MyBatis


①创建 maven 工程

  1. 打包方式:jar

  2. 引入依赖

<dependencies>
	<!-- Mybatis核心 -->
	<dependency>
		<groupId>org.mybatis</groupId>
		<artifactId>mybatis</artifactId>
		<version>3.5.7</version>
	</dependency>
	<!-- junit测试 -->
	<dependency>
		<groupId>junit</groupId>
		<version>4.12</version>
		<scope>test</scope>
	</dependency>
	<!-- MySQL驱动 -->
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<version>8.0.32</version>
	</dependency>
</dependencies>

②创建MyBatis的核心配置文件

  • 一般命名为 mybatis-config.xml ,但仅仅只是建议,并非强制要求。以后整合Spring时,这个配置文件可以省略

  • 核心配置文件主要用于配置连接数据库的环境以及MyBatis的全局配置信息

  • 核心配置文件存放的位置是 maven 工程的 src/main/resources 目录下

<?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>
	<!--设置连接数据库的环境-->
	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC"/>
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
				<property name="url" value="jdbc:mysql://localhost:3306/db1"/>
				<property name="username" value="root"/>
				<property name="password" value="root"/>
			</dataSource>
		</environment>
	</environments>
	<!--引入映射文件-->
	<mappers>
		<package name="mappers/UserMapper.xml"/>
	</mappers>
</configuration>

③创建mapper接口

  • MyBatis中的mapper接口相当于以前的dao。但是区别在于,mapper仅仅是接口,我们不需要提供实现类。
public interface UserMapper {
	/**
	* 添加用户信息
	*/
	void insertUser();
}

④创建MyBatis的映射文件

相关概念:ORM(Object Relationship Mapping)对象关系映射。

  • 对象:Java的实体类对象

  • 关系:关系型数据库

  • 映射:二者之间的对应关系

Java与数据库中一些存在对应关系的概念

Java概念数据库概念
属性字段/列
对象记录/行

映射文件的命名规则:

  • 表所对应的 实体类的类名 + Mapper.xml

    • 例如:表 t_user ,映射的实体类为 User ,所对应的映射文件为 UserMapper.xml

    • 因此一个映射文件对应一个实体类,对应一张表的操作

  • MyBatis 映射文件用于编写 SQL ,访问以及操作表中的数据

  • MyBatis 映射文件存放的位置是 src/main/resources/mappers 目录下

注意:MyBatis 中可以面向接口操作数据,要保证两个一致:

  • mapper 接口的全类名和映射文件的命名空间(namespace)保持一致

  • mapper 接口中方法的方法名和映射文件中编写 SQL 的标签的id属性保持一致

<?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.zrb.mapper.UserMapper">
	<!--int insertUser();-->
	<insert id="insertUser">
	insert into t_user values(null,'admin','123456',23,'男','12345@qq.com')
	</insert>
</mapper>

⑤通过junit测试功能

 @Test
   public void test() throws IOException {
	//读取MyBatis的核心配置文件
	InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
	//创建SqlSessionFactoryBuilder对象
	SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
	//通过核心配置文件所对应的字节输入流创建工厂类SqlSessionFactory,生产SqlSession对象
	SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
	//创建SqlSession对象,此时通过SqlSession对象所操作的sql都必须手动提交或回滚事务
	//SqlSession sqlSession = sqlSessionFactory.openSession();
	//创建SqlSession对象,此时通过SqlSession对象所操作的sql都会自动提交
	SqlSession sqlSession = sqlSessionFactory.openSession(true);
	//通过代理模式创建UserMapper接口的代理实现类对象
	UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
	//调用UserMapper接口中的方法,就可以根据UserMapper的全类名匹配元素文件,通过调用的方法名匹配映射文件中的SQL标签,并执行标签中的SQL语句
	int result = userMapper.insertUser();
	//sqlSession.commit();
	System.out.println("结果:"+result);
   }
  • SqlSession:代表Java程序和数据库之间的会话。(HttpSession是Java程序和浏览器之间的会话)

  • SqlSessionFactory:是生产 SqlSession 的工厂

    • 工厂模式:如果创建某一个对象,使用的过程基本固定,那么我们就可以把创建这个对象的相关代码封装到一个工厂类中,以后都使用这个工厂类来生产我们需要的对象。

⑥加入log4j日志功能(用于查看查询信息,可不要)

  1. 加入依赖
<!-- log4j日志 -->
<dependency>
	<groupId>log4j</groupId>
	<artifactId>log4j</artifactId>
	<version>1.2.17</version>
</dependency>
  1. 加入log4j的配置文件

    • log4j的配置文件名为log4j.xml,存放的位置是src/main/resources目录下
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
	<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
		<param name="Encoding" value="UTF-8" />
		<layout class="org.apache.log4j.PatternLayout">
			<param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS}%m (%F:%L) \n" />
		</layout>
	</appender>
	<logger name="java.sql">
		<level value="debug" />
	</logger>
	<logger name="org.apache.ibatis">
		<level value="info" />
	</logger>
	<root>
		<level value="debug" />
		<appender-ref ref="STDOUT" />
	</root>
</log4j:configuration>

日志的级别

  • FATAL(致命)>ERROR(错误)>WARN(警告)>INFO(信息)>DEBUG(调试)

  • 从左到右打印的内容越来越详细

核心配置文件详解

核心配置文件中的标签必须按照固定的顺序:

properties?,settings?,typeAliases?,typeHandlers?,
objectFactory?,objectWrapperFactory?,reflectorFactory?,
plugins?,environments?,databaseIdProvider?,mappers?

<?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>

    <!--
        MyBatis核心配置文件中的标签必须要按照指定的顺序配置:
        properties?,settings?,typeAliases?,typeHandlers?,
        objectFactory?,objectWrapperFactory?,reflectorFactory?,
        plugins?,environments?,databaseIdProvider?,mappers?
    -->

    <!--引入properties文件,此后就可以在当前文件中使用${key}的方式访问value-->
    <properties resource="jdbc.properties" />

    <!--
        typeAliases:设置类型别名,即为某个具体的类型设置一个别名
        在MyBatis的范围中,就可以使用别名表示一个具体的类型
    -->
    <typeAliases>
        <!--
            type:设置需要起别名的类型
            alias:设置某个类型的别名
        -->
        <!--<typeAlias type="com.zrb.pojo.User" alias="abc"></typeAlias>-->
        <!--若不设置alias,当前的类型拥有默认的别名,即类名且不区分大小写-->
        <!--<typeAlias type="com.zrb.pojo.User"></typeAlias>-->
        <!--通过包设置类型别名,指定包下所有的类型将全部拥有默认的别名,即类名且不区分大小写-->
        <package name="com.zrb.pojo"/>
    </typeAliases>

    <!--
        environments:配置连接数据库的环境
        属性:
        default:设置默认使用的环境的id
    -->
    <environments default="development">
        <!--
            environment:设置一个具体的连接数据库的环境
            属性:
            id:设置环境的唯一标识,不能重复
        -->
        <environment id="development">
            <!--
                transactionManager:设置事务管理器
                属性:
                type:设置事务管理的方式
                type="JDBC|MANAGED"
                JDBC:表示使用JDBC中原生的事务管理方式
                MANAGED:被管理,例如Spring
            -->
            <transactionManager type="JDBC"/>
            <!--
                dataSource:设置数据源
                属性:
                type:设置数据源的类型
                type="POOLED|UNPOOLED|JNDI"
                POOLED:表示使用数据库连接池
                UNPOOLED:表示不使用数据库连接池
                JNDI:表示使用上下文中的数据源
            -->
            <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>

        <environment id="test">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/db1"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>

    <!--引入mybatis的映射文件-->
    <mappers>
        <!--<mapper resource="mappers/UserMapper.xml"/>-->
        <!--
            以包的方式引入映射文件,但是必须满足两个条件:
            1、mapper接口和映射文件所在的包必须一致
            2、mapper接口的名字和映射文件的名字必须一致
        -->
        <package name="com.zrb.mapper"/>
    </mappers>
</configuration>

MyBatis获取参数值的两种方式



MyBatis获取参数值的两种方式:${}#{}

  • ${} 的本质就是字符串拼接,#{} 的本质就是占位符赋值

  • ${} 使用字符串拼接的方式拼接 sql ,若为字符串类型或日期类型的字段进行赋值时,需要手动加单引号;但是 #{} 使用占位符赋值的方式拼接 sql ,此时为字符串类型或日期类型的字段进行赋值时,可以自动添加单引号

单个字面量类型的参数

若mapper接口中的方法参数为单个的字面量类型,此时可以使用 ${}#{} 以任意的名称获取参数的值,注意 ${} 需要手动加单引号

多个字面量类型的参数

若 mapper 接口中的方法参数为多个时

此时 MyBatis 会自动将这些参数放在一个 map 集合中,以arg0,arg1...为键,以参数为值;以 param1,param2... 为键,以参数为值;因此只需要通过 ${}#{} 访问 map 集合的键就可以获取相对应的值,注意 ${} 需要手动加单引号

map 集合类型的参数

若 mapper 接口中的方法需要的参数为多个时,此时可以手动创建 map 集合,将这些数据放在 map 中只需要通过 ${}#{} 访问 map 集合的键就可以获取相对应的值,注意 ${} 需要手动加单引号

实体类类型的参数

若mapper接口中的方法参数为实体类对象时,此时可以使用 ${}#{} ,通过访问实体类对象中的属性名获取属性值,注意 ${} 需要手动加单引号

使用@Param标识参数

可以通过 @Param 注解标识mapper接口中的方法参数
此时,会将这些参数放在 map 集合中,以 @Param 注解的 value 属性值为键,以参数为值;以 param1,param2...为键,以参数为值;只需要通过 ${}#{} 访问 map 集合的键就可以获取相对应的值,注意 ${} 需要手动加单引号

特殊SQL的执行

①模糊查询

三种方式

//1.用${},${}只进行字符串拼接,直接写入字符串中
select * from t_user where username like '%${like}%'
//2.用concat函数进行拼接
select * from t_user where username like concat('%',#{like},'%')
//3.用#{},#{}不能字节写字符串中,否则会变成?拼接到字符串,
//并不会对其进行正确赋值,可以用"%"#{}"%",前后的%用双引号括起
select * from t_user where username like "%"#{like}"%"

②批量删除

批量删除时可以用 ${}

delete from t_user where id in (${ids})

③动态设置表名

动态查询表是可以用 ${}

select * from ${tableName}

④添加功能获取自增的主键

场景模拟:

t_clazz(clazz_id,clazz_name) //班级表
t_student(student_id,student_name,clazz_id) //学生表

1、添加班级信息

2、获取新添加的班级的id

3、为班级分配学生,即将某学的班级id修改为新添加的班级的id


简单事例,获取主键自增表 t_user 的新增id

/**
* 添加用户信息
*/
int insertUser(User user);
# useGeneratedKeys:设置使用自增的主键
# keyProperty:因为增删改有统一的返回值是受影响的行数,因此只能将获取的自增的主键放在传输的参数user对象的某个属性中
<!--int insertUser(User user);-->
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
	insert into t_user values(null,#{username},#{password},#{age},#{sex})
</insert>

自定义映射resultMap


resultType和resultMap


  • 查询的标签 select 必须设置属性 resultType 或 resultMap ,用于设置实体类和数据库表的映射关系

    • resultType:自动映射,用于属性名和表中字段名一致的情况

    • resultMap:自定义映射,用于一对多或多对一或字段名和属性名不一致的情况

resultMap处理字段和属性的映射关系


若字段名和实体类中的属性名不一致,则可以通过resultMap设置自定义映射

<!--
	resultMap:设置自定义映射
	属性:
		id:表示自定义映射的唯一标识
		type:查询的数据要映射的实体类的类型
	子标签:
		id:设置主键的映射关系
		result:设置普通字段的映射关系
		association:设置多对一的映射关系
		collection:设置一对多的映射关系
	属性:
		property:设置映射关系中实体类中的属性名
		column:设置映射关系中表中的字段名
-->
<resultMap id="userMap" type="User">
	<id property="id" column="id"></id>
	<result property="userName" column="user_name"></result>
	<result property="password" column="password"></result>
	<result property="age" column="age"></result>
	<result property="sex" column="sex"></result>
</resultMap>
<!--List<User> testMohu(@Param("mohu") String mohu);-->
<select id="test" resultMap="userMap">
	<!--select * from t_user where username like '%${mohu}%'-->
	select id,user_name,password,age,sex from t_user where user_name like concat('%',#{mohu},'%')
</select>

若字段名和实体类中的属性名不一致,但是字段名符合数据库的规则(使用_),实体类中的属性名符合Java的规则(使用驼峰),此时也可通过以下两种方式处理字段名和实体类中的属性的映射关系

  1. 可以通过为字段起别名的方式,保证和实体类中的属性名保持一致

  2. 可以在MyBatis的核心配置文件中设置一个全局配置信息mapUnderscoreToCamelCase,可以在查询表中数据时,自动将_类型的字段名转换为驼峰

    • 例如:字段名user_name,设置了mapUnderscoreToCamelCase,此时字段名就会转换为userName

多对一映射处理


场景模拟:

  • 查询员工信息以及员工所对应的部门信息

级联方式处理映射关系

<resultMap id="empDeptMap" type="Emp">
	<id column="eid" property="eid"></id>
	<result column="ename" property="ename"></result>
	<result column="age" property="age"></result>
	<result column="sex" property="sex"></result>
	<result column="did" property="dept.did"></result>
	<result column="dname" property="dept.dname"></result>
</resultMap>
<!--Emp getEmpAndDeptByEid(@Param("eid") int eid);-->
<select id="getEmpAndDeptByEid" resultMap="empDeptMap">
	select emp.*,dept.* from t_emp emp left join t_dept dept on emp.did = dept.did where emp.eid = #{eid}
</select>

即这一步操作,在员工表中定义了一个部门类型的成员变量,通过数据库中查询的字段与部门类型的成员变量中的部门属性进行映射
在这里插入图片描述

使用association处理映射关系

<resultMap id="empDeptMap" type="Emp">
	<id column="eid" property="eid"></id>
	<result column="ename" property="ename"></result>
	<result column="age" property="age"></result>
	<result column="sex" property="sex"></result>
	<!-- association:设置多对一的映射关系 -->
	<association property="dept" javaType="Dept">
		<id column="did" property="did"></id>
		<result column="dname" property="dname"></result>
	</association>
</resultMap>
<!--Emp getEmpAndDeptByEid(@Param("eid") int eid);-->
<select id="getEmpAndDeptByEid" resultMap="empDeptMap">
	select emp.*,dept.* from t_emp emp left join t_dept dept on emp.did = dept.did where emp.eid = #{eid}
</select>

分步查询

①查询员工信息

/**
* 通过分步查询查询员工信息
* @param eid
* @return
*/
Emp getEmpByStep(@Param("eid") int eid);
<resultMap id="empDeptStepMap" type="Emp">
	<id column="eid" property="eid"></id>
	<result column="ename" property="ename"></result>
	<result column="age" property="age"></result>
	<result column="sex" property="sex"></result>
	<!--
	select:设置分步查询,查询某个属性的值的sql的标识(namespace.sqlId)
	column:将sql以及查询结果中的某个字段设置为分步查询的条件
	-->
	<association property="dept"
		select="com.zrb.mapper.DeptMapper.getEmpDeptByStep" column="did">
		<!-- 此处colum的作用为把当前查询出来的结果的某一字段作为下一步查询的条件使用 -->
	</association>
</resultMap>
<!--Emp getEmpByStep(@Param("eid") int eid);-->
<select id="getEmpByStep" resultMap="empDeptStepMap">
	select * from t_emp where eid = #{eid}
</select>

②根据员工所对应的部门id查询部门信息

/**
* 分步查询的第二步: 根据员工所对应的did查询部门信息
* @param did
* @return
*/
Dept getEmpDeptByStep(@Param("did") int did);
<!--Dept getEmpDeptByStep(@Param("did") int did);-->
<select id="getEmpDeptByStep" resultType="Dept">
	select * from t_dept where did = #{did}
</select>

一对多映射处理

collection

/**
* 根据部门id查新部门以及部门中的员工信息
* @param did
* @return
*/
Dept getDeptEmpByDid(@Param("did") int did);
<resultMap id="deptEmpMap" type="Dept">
	<id property="did" column="did"></id>
	<result property="dname" column="dname"></result>
	<!--
	ofType:设置collection标签所处理的集合属性中存储数据的类型
	-->
	<collection property="emps" ofType="Emp">
		<id property="eid" column="eid"></id>
		<result property="ename" column="ename"></result>
		<result property="age" column="age"></result>
		<result property="sex" column="sex"></result>
	</collection>
</resultMap>
<!--Dept getDeptEmpByDid(@Param("did") int did);-->
<select id="getDeptEmpByDid" resultMap="deptEmpMap">
	select dept.*,emp.* from t_dept dept left join t_emp emp on dept.did = emp.did where dept.did = #{did}
</select>

分步查询

①查询部门信息

/**
* 分步查询部门和部门中的员工
* @param did
* @return
*/
Dept getDeptByStep(@Param("did") int did);
<resultMap id="deptEmpStep" type="Dept">
	<id property="did" column="did"></id>
	<result property="dname" column="dname"></result>
	<collection property="emps" fetchType="eager"
		select="com.atguigu.MyBatis.mapper.EmpMapper.getEmpListByDid" column="did">
	</collection>
</resultMap>
<!--Dept getDeptByStep(@Param("did") int did);-->
<select id="getDeptByStep" resultMap="deptEmpStep">
	select * from t_dept where did = #{did}
</select>

②根据部门id查询部门中的所有员工

/**
* 根据部门id查询员工信息
* @param did
* @return
*/
List<Emp> getEmpListByDid(@Param("did") int did);
<!--List<Emp> getEmpListByDid(@Param("did") int did);-->
<select id="getEmpListByDid" resultType="Emp">
	select * from t_emp where did = #{did}
</select>

分步查询的优点

  • 可以实现延迟加载,但是必须在核心配置文件中设置全局配置信息:
    • lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载
    • aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载,此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。
    • 此时可通过 association 和 collection 中的 fetchType 属性设置当前的分步查询是否使用延迟加载, fetchType= lazy (延迟加载)|eager(立即加载)

动态SQL


Mybatis框架的动态SQL技术是一种根据特定条件动态拼装SQL语句的功能,它存在的意义是为了解决拼接SQL语句字符串时的痛点问题。

if

if 标签可通过 test 属性的表达式进行判断,若表达式的结果为 true ,则标签中的内容会执行;反之标签中的内容不会执行

<!--List<Emp> getEmpListByCondition(Emp emp);-->
<select id="getEmpListByMoreTJ" resultType="Emp">
	select * from t_emp where 1=1
	<if test="ename != '' and ename != null">
		and ename = #{ename}
	</if>
	<if test="age != '' and age != null">
		and age = #{age}
	</if>
	<if test="sex != '' and sex != null">
		and sex = #{sex}
	</if>
</select>

where

where 和 if 一般结合使用:

  • 若 where 标签中的 if 条件都不满足,则 where 标签没有任何功能,即不会添加 where 关键字
  • 若 where 标签中的if条件满足,则 where 标签会自动添加 where 关键字,并将条件最前方多余的 and 去掉

注意:where 标签不能去掉条件最后多余的 and。

trim

trim用于去掉或添加标签中的内容

常用属性:

  • prefix:在trim标签中的内容的前面添加某些内容

  • prefixOverrides:在trim标签中的内容的前面去掉某些内容

  • suffix:在trim标签中的内容的后面添加某些内容

  • suffixOverrides:在trim标签中的内容的后面去掉某些内容

<select id="getEmpListByMoreTJ" resultType="Emp">
	select * from t_emp
	<trim prefix="where" suffixOverrides="and">
		<if test="ename != '' and ename != null">
			ename = #{ename} and
		</if>
		<if test="age != '' and age != null">
			age = #{age} and
		</if>
		<if test="sex != '' and sex != null">
			sex = #{sex}
		</if>
	</trim>
</select>

choose、when、otherwise

choose、when、 otherwise相当于if…else if…else

<!--List<Emp> getEmpListByChoose(Emp emp);-->
<select id="getEmpListByChoose" resultType="Emp">
	select <include refid="empColumns"></include> from t_emp
	<where>
		<choose>
			<when test="ename != '' and ename != null">
				ename = #{ename}
			</when>
			<when test="age != '' and age != null">
				age = #{age}
			</when>
			<when test="sex != '' and sex != null">
				sex = #{sex}
			</when>
			<when test="email != '' and email != null">
				email = #{email}
			</when>
		</choose>
	</where>
</select>

foreach

<!-- 添加多条数据 -->
<!--int insertMoreEmp(List<Emp> emps);-->
<insert id="insertMoreEmp">
	insert into t_emp values
	<foreach collection="emps" item="emp" separator=",">
		(null,#{emp.ename},#{emp.age},#{emp.sex},#{emp.email},null)
	</foreach>
</insert>
<!-- 删除多条数据 -->
<!--int deleteMoreByArray(int[] eids);-->
<delete id="deleteMoreByArray">
	delete from t_emp where
	<foreach collection="eids" item="eid" separator="or">
		eid = #{eid}
	</foreach>
</delete>
<!--int deleteMoreByArray(int[] eids);-->
<delete id="deleteMoreByArray">
		delete from t_emp where eid in
	<foreach collection="eids" item="eid" separator="," open="(" close=")">
		#{eid}
	</foreach>
</delete>

SQL片段

sql片段,可以记录一段公共sql片段,在使用的地方通过include标签进行引入

<sql id="empColumns">
	eid,ename,age,sex,did
</sql>
select <include refid="empColumns"></include> from t_emp

分页插件


分页插件的使用步骤

①添加依赖

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

②配置分页插件

在MyBatis的核心配置文件中配置插件

<plugins>
	<!--设置分页插件-->
	<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>

分页插件的使用

(1)在查询功能之前使用PageHelper.startPage(int pageNum, int pageSize)开启分页功能

  • pageNum:当前页的页码

  • pageSize:每页显示的条数

(2)在查询获取 list 集合之后,使用PageInfo<T> pageInfo = new PageInfo<>(List<T> list, int navigatePages)获取分页相关数据

  • list:分页之后的数据

  • navigatePages:导航分页的页码数

(3)分页相关数据

PageInfo{
pageNum=8, pageSize=4, size=2, startRow=29, endRow=30, total=30, pages=8,
list=Page{count=true, pageNum=8, pageSize=4, startRow=28, endRow=32, total=30,
pages=8, reasonable=false, pageSizeZero=false},
prePage=7, nextPage=0, isFirstPage=false, isLastPage=true, hasPreviousPage=true,
hasNextPage=false, navigatePages=5, navigateFirstPage4, navigateLastPage8,
navigatepageNums=[4, 5, 6, 7, 8]
}
pageNum:当前页的页码
pageSize:每页显示的条数
size:当前页显示的真实条数
total:总记录数
pages:总页数
prePage:上一页的页码
nextPage:下一页的页码
isFirstPage/isLastPage:是否为第一页/最后一页
hasPreviousPage/hasNextPage:是否存在上一页/下一页
navigatePages:导航分页的页码数
navigatepageNums:导航分页的页码,[1,2,3,4,5]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/505654.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Canvas 2D详解

在我书的第六章中有一个关于MNIST手写数字的例子&#xff0c;当数据集加载完成之后&#xff0c;用户可以在<canvas/>上输入手写数字&#xff0c;点击「预测」按钮之后&#xff0c;浏览器会弹出经模型预测之后的结果&#xff1b;在我书的第九章和第十章中&#xff0c;分别…

2023年宜昌市中等职业学校技能大赛 “网络搭建与应用”竞赛题-2

2023年宜昌市中等职业学校技能大赛 “网络搭建与应用”竞赛题 一、竞赛内容分布 “网络搭建及应用”竞赛共分二个部分&#xff0c;其中&#xff1a; 第一部分&#xff1a;企业网络搭建部署项目&#xff0c;占总分的比例为50%&#xff1b; 第二部分&#xff1a;企业网络服…

第十四届蓝桥杯大赛软件赛省赛(Java 大学A组)

蓝桥杯 2023年省赛真题 Java 大学A组 试题 A: 特殊日期  试题 B: 与或异或 把填空挂上跟大伙对对答案&#xff0c;先把C/C B组的做了。 试题 A: 特殊日期 本题总分&#xff1a;5 分 【问题描述】 记一个日期为 y y \small yy yy 年 m m \small mm mm 月 d d \small dd dd 日…

链表的初步认识

什么是链表&#xff1f;链表是一种物理存储结构上非连续存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。 就如现实中的火车或铁链一般&#xff0c;环环相扣。当我们到达一个节点时&#xff0c;就可以通过这个节点找到下一个节点。链表与顺序表一样…

【服务器数据恢复】EXT4文件系统下KVM虚拟机数据恢复案例

服务器数据恢复环境&#xff1a; 服务器采用的Linux操作系统EXT4文件系统&#xff1b; 服务器中有3台KVM虚拟机&#xff1a;一台运行Mysql数据库&#xff0c;一台存放数据库备份&#xff0c;一台存放程序代码文件&#xff1b; 每台虚拟机包含一个qcow2格式的磁盘文件和一个raw格…

联合发版+主题演讲|GBASE南大通用亮相鲲鹏开发者峰会2023

5月6-7日&#xff0c;以“创未来 享非凡”为主题的鲲鹏开发者峰会2023在东莞松山湖举办&#xff0c;旨在打造生态伙伴和开发者学习、共享、交流的平台&#xff0c;帮助开发者深入了解鲲鹏、昇腾全栈技术&#xff0c;加速行业技术、产品和解决方案的创新。行业技术领袖、产业技术…

Apache FtpServer在Windows上使用以及SpringBoot中集成apache ftpserver实现Ftp 服务端搭建

场景 Apache Ftpserver Apache FtpServer是100&#xff05;纯Java FTP服务器。它被设计为基于当前可用的开放协议的完整且 可移植的FTP服务器引擎解决方案。FtpServer可以作为Windows服务或Unix / Linux守护程序独立运行&#xff0c; 也可以嵌入Java应用程序中。我们还提供…

【图】邻接表

目录 无向图的邻接表 链表&#xff08;存相邻顶点下标&#xff09;的类 数组里放的顶点 邻接表&#xff08;操作&#xff09; 构造和析构&#xff08;创建销毁邻接表&#xff09; 插入顶点 插入边 获取下标 插v1、v2之间的边 删除顶点 删除边 输出&#xff1a; 其他…

多种采购方式下,数智化招采系统解决方案(实例)

广发证券成立于1991年&#xff0c;是国内首批综合类证券公司&#xff0c;先后于2010年和2015年在深圳证券交易所及香港联合交易所主板上市。 多年来&#xff0c;广发证券在竞争激烈、复杂多变的行业环境中努力开拓、锐意进取&#xff0c;以卓越的经营业绩、持续完善的全面风险…

Node.js对ES6 及更高版本的支持

目录 1、简介 2、默认情况下什么特性随着 Node.js 一起发布&#xff1f; 3、有哪些特性在开发中&#xff1f; 4、移除这个标记&#xff08;--harmony&#xff09;吗 5、Node.js 对应 V8 引擎 1、简介 Node.js 是针对 V8 引擎构建的。通过与此引擎的最新版本保持同步&…

PMP课堂模拟题目及解析(第5期)

41. 项目的混凝土供应商通知项目经理&#xff0c;材料将比预定时间晚三个星期交付。项目经理更新了进度计划并通知项目团队。在这种情况下&#xff0c;哪种合同类型承担的风 险最小&#xff1f; A. 总价加激励费用合同。 B. 总价加经济价格调整合同。 C. 工料合同。 D. 固…

matlab学习笔记

一、序言 1. 图像的输入输出和显示 fimread("test.png"); frgb2gray(f);%rgb图像转化为灰度图像 imshow(f); imwrite(f,"result.jpg","quality",50);%50代表jpg形式压缩质量0-1002. matlab支持的四种图像类别 灰度级图像(Gray-scale images) …

类和对象【C++】【中篇】

目录 一、类的6个默认成员函数 1、构造函数 2、析构函数 3、拷贝构造函数 4、赋值重载函数 二、赋值运算符重载 一、类的6个默认成员函数 注意&#xff1a;默认成员函数不能在类外面定义成全局函数。因为类里没有的话会自动生成&#xff0c;就会产生冲突。 1、构造函数…

k8s采用ansible安装

一、准备工作 测试服务器 服务器配置进程功能备注192.168.0.189CPU:4核 内存32Gansibleansible一键安装k8s192.168.0.141CPU&#xff1a;12核 内存&#xff1a;10Gdocker&#xff0c;kube-apiserver&#xff0c;etcd&#xff0c;kube-scheduler&#xff0c;kube-controller-m…

产品经理 - 原型图设计软件

原型图设计软件哪个好用&#xff1f;6款好用软件推荐&#xff01; - 知乎 摩客, 墨刀 2014 即时设计是一款支持在线协作的专业级 UI 设计工具&#xff0c;用户数已突破230万&#xff1b; 2021年 5,000万(美元) 国外 axure 老牌 如果有进一步模拟的必要&#xff0c;再换用Ad…

JetPack之lifecycle原理分析

Lifecycle是什么 Lifecycle可以有效的避免内存泄漏和解决android生命周期的常见难题Livecycle 是一个表示android生命周期及状态的对象LivecycleOwner 用于连接有生命周期的对象&#xff0c;如activity,fragmentLivecycleObserver 用于观察查LifecycleOwnerLifecycle框架使用观…

关于SSL证书有效期缩短,看这一篇就够了

在TLS/SSL证书有效期不断被缩短的大趋势下&#xff0c;我们在前文和大家聊了聊企业面临的困境、应对策略及证书自动化管理&#xff0c;今天想和大家继续探讨的是TLS/SSL证书自动化管理切实可行的解决方案。 01 自动化证书管理的重要性 TLS/SSL证书是保障网络连接安全的重要手…

图片位深度以及转换办法

位图文件的格式&#xff1a; ① 位图文件头&#xff0c;所用结构体&#xff1a;BITMAPFILEHEADER&#xff0c;占14个字节 ② 位图信息头&#xff0c;所用结构体&#xff1a;BITMAPINFOHEADER&#xff0c;占40个字节 ③ 颜色表项&#xff0c;所用结构体&#xff1a;RGBQUAD&…

Qt5.14版本通用环境配置安装——最详细教学(看不懂,你怪我)

✨✨✨大家好&#xff0c;我是会飞的鱼-blog&#xff0c;今天我来给大家介绍一下Qt5.14.1安装&#xff0c;有不足之处&#xff0c;请大家多多指教。感谢大家支持&#xff01;&#xff01;&#xff01; 目录 前言 安装文件下载&#xff1a; 安装&#xff1a; 设置 QtCreator…

测试相关记录

1、提测计划、需求拆分、颗粒度 2、线上bug回顾 3、提测流水线 4、测试业绩合同指定