MyBatis学习
创始人
2024-05-31 20:45:08
0

MyBatis优点

轻量级,性能出色
SQL 和 Java 编码分开,功能边界清晰。Java代码专注业务、SQL语句专注数据
开发效率稍逊于HIbernate,但是完全能够接受

补充:POJO

一:什么是POJO
POJO的名称有多种,pure old java object 、plain ordinary java object 等。
按照Martin Fowler的解释是“Plain Old Java Object”,从字面上翻译为“纯洁老式的java对象”,但大家都使用“简单java对象”来称呼它。
POJO的内在含义是指那些没有从任何类继承、也没有实现任何接口,更没有被其它框架侵入的java对象。

二:为什么会有POJO?
主要是Java的开发者被EJB的繁杂搞怕了,大家经过反思,又回归“纯洁老式”的JavaBean,即有无参构造函数,每个字段都有getter和setter的java类。

无参构造器必须要有

Mapper接口

MyBatis中的mapper接口相当于以前的dao。但是区别在于,mapper仅仅是接口,我们不需要
提供实现类。

DAO层叫数据访问层,全称为data access object,某个DAO一定是和数据库的某一张表一一对应的,其中封装了CRUD(增加Create、检索Retrieve、更新Update和删除Delete)基本操作,DAO只做原子操作。无论多么复杂的查询,dao只是封装增删改查。至于增删查改如何去实现一个功能,dao是不管的

起名规则:POJO的名字 + Mapper

创建MyBatis的映射文件

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

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

相关概念:ORM(Object Relationship Mapping)对象关系映射。
对象:Java的实体类对象
关系:关系型数据库
映射:二者之间的对应关系

命名规则:表所对应的实体类的类名+Mapper.xml(最好是一个mapper接口及其对应一个配置文件的名字相同,即,有一个Java文件时UserMapper.java,对应一个UserMapper.xml)
因此一个映射文件对应一个实体类,对应一张表的操作,对应一个mapper接口
mapper接口中的一个方法,对应映射文件中的一个SQL语句

MyBatis中可以面向接口操作数据,要保证两个一致:
1、mapper接口的全类名和映射文件的命名空间(namespace)保持一致
在这里插入图片描述

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

Mybatis有两个重要文件:核心文件和映射文件
核心文件用于连接数据库
映射文件用于操作数据库

映射文件中写的是SQL语句

public interface UserMapper {/*** 添加用户信息*/int insertUser();
}



通过junit测试功能

package com.atguigu.mybatis;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 org.junit.Test;
import com.atguigu.mybatis.mapper.UserMapper;import java.io.IOException;
import java.io.InputStream;public class MyBatisTest {@Testpublic void testInsert() throws IOException {// 获取核心配置文件的输入流(核心配置文件中又注入了映射文件,所以获取核心配置文件即可)InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");// 获取SqlSessionFactoryBuilder 对象 -> 工厂构建器SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();// 创建 SqlSessionFactory -> 创建会话SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(resourceAsStream);// 获取sqlSession -> MyBatis 提供的操作数据库的对象(不会自动提交事务)SqlSession sqlSession = sqlSessionFactory.openSession();//获取sqlSession -> MyBatis 提供的操作数据库的对象(可以自动提交事务)//SqlSession sqlSession = sqlSessionFactory.openSession(true);// 获得Mapper接口的代理类 -> 操纵Mapper类执行数据库操作(UserMapper是一个接口,不能直接实例化,所以通过这种方式创建其对象)UserMapper userMapper = sqlSession.getMapper(UserMapper.class);// 执行SQL操作Integer rows = userMapper.insertUser();System.out.println("rows = " + rows);// 提交事务 -> 事务是默认开启的(不然数据库中并没有这条记录)sqlSession.commit();// 关闭资源sqlSession.close();}
}

SqlSession:代表Java程序和数据库之间的会话。(HttpSession是Java程序和浏览器之间的会话)

SqlSessionFactory:是“生产”SqlSession的“工厂”。

工厂模式:如果创建某一个对象,使用的过程基本固定,那么我们就可以把创建这个对象的

日志级别

日志的xml文件名字必须是——log4j.xml

    

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

从左到右打印的内容越来越详细(级别越来越低)

核心配置文件详解

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

properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,refl

ectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?

typeAlias

typeAlias:设置某个类型的别名
属性:
type:设置需要设置别名的类型
alias:设置某个类型的别名,若不设置该属性,那么该类型拥有默认的别名,即类名且不区分大小写

environments

environments:配置多个连接数据库的环境
可以配置多个环境,比如测试环境和开发环境 ; 使用id区分,不能重复。

属性:
default:设置默认使用的环境的id

    

transactionManager

transactionManager:设置事务管理方式
属性:
type=“JDBC|MANAGED”
JDBC:表示当前环境中,执行SQL时,使用的是JDBC中原生的事务管理方式,事务的提交或回滚需要手动处理
MANAGED:被管理,例如Spring

dataSource

dataSource:配置数据源
属性:
type:设置数据源的类型
type=“POOLED|UNPOOLED|JNDI”
POOLED:表示使用数据库连接池缓存数据库连接
UNPOOLED:表示不使用数据库连接池
JNDI:表示使用上下文中的数据源

例子在前面的代码中

总的配置文件:





MyBatis的增删改查

在 Mapper.xml 文件中使用:
添加:


insert into t_user values(null,'admin','123456',23,'男')

删除:


delete from t_user where id = 7

修改:


update t_user set username='ybc',password='123' where id = 6

查询:







注意:
查询的标签select必须设置属性resultType或resultMap,用于设置实体类和数据库表的映射
关系
resultType:自动映射,用于属性名和表中字段名一致的情况,resultType可以直接返回给出的返回值类型(意思是返回值类型)
resultMap:自定义映射,用于一对多或多对一或字段名和属性名不一致的情况,返回值是自定义实体类的情况(意思是自定义映射)

MyBatis获取参数值的两种方式

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

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

${}使用字符串拼接的方式拼接sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单引

号;但是#{}使用占位符赋值的方式拼接sql,此时为字符串类型或日期类型的字段进行赋值时,

可以自动添加单引号

单个字面量类型的参数

若mapper接口中的方法参数为单个的字面量类型

此时可以使用{}和#{}以任意的名称获取参数的值,注意{}需要手动加单引号

  • #{}方式:
    在这里插入图片描述
  • ${}方式:在这里插入图片描述
    这样会报错,因为admin没有加单引号,会被认为是sql’数据表中的一个字段,改成:
    在这里插入图片描述

其实大括号中的名字不一定非得是变量名,任意的名字都可以成功获取,不过建议使用参数名让其变得有意义

多个字面量类型的参数

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

此时MyBatis会自动将这些参数放在一个map集合中,以arg0,arg1…为键,以参数为值;

以param1,param2…为键,以参数为值;

因此只需要通过${}和#{}访问map集合的键就可以获取相对应的值,注意 ${}需要手动加单引号

使用param方式:(使用arg0……就是将大括号中的param1改成arg0,param2改成arg1……即可)
在这里插入图片描述

map集合类型的参数

若mapper接口中的方法需要的参数为多个时,此时可以手动创建map集合,将这些数据放在

map中

只需要通过{}和#{}访问map集合的键就可以获取相对应的值,注意${}需要手动加单引号
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在select中设置的键值是username和password,因为在test方法中,在put时,制定了map集合中两个键值的名字:username和password,和上一种情况相比,就是,这次我们是通过put对map进行手动添加,而且自定义了键值的名称,上一种情况是,机器自动将我们的参数放到map中,所以只能使用机器定义的键值名称:arg0……param1等

实体类类型的参数

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

注意,属性和我们在java中编写的private int age 等内容没有关系,而是和get、set方法有关系,如果一个java类中,没有设置相应的age等成员变量,但是有其对应的get、set方法,不会阻碍我们获取相应的成员变量。属性就是将这两个方法的get、set去掉,剩余部分变成小写。
总结:属性,只和类中的get、set方法有关(取值找get,赋值找set),与成员变量无关!

User类的结构:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

id设置为null是想让他自增

使用@Param标识参数

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

与第二种情况比较,可以自定义键值,与第三种情况比较,可以不需要手动向map中添加

想要访问参数的值,需要先访问他对应的键,所以#{}中的内容是键,也就是@Param括号中的内容

MyBatis的各种查询功能

查询一个实体类对象

/**
* 根据用户id查询用户信息
* @param id
* @return
*/
User getUserById(@Param("id") int id);

这里使用@Param是因为,字面量在查询的时候可以通过任意的内容来查询,所以这里制定用id查询



查询一个list集合

当查询的数据为多条时,不能使用实体类作为返回值,否则会抛出异常TooManyResultsException;
但是若查询的数据只有一条,可以使用实体类或集合作为返回值

/**
* 查询所有用户信息
* @return
*/
List getUserList();


查询单行单列数据

在这里插入图片描述

/**
* 查询用户的总记录数
* @return
* 在MyBatis中,对于Java中常用的类型都设置了类型别名
* 例如: java.lang.Integer的别名:int|integer
* 例如: int的别名:_int|_integer
* 例如: String的别名:string
* 例如: Map的别名:map,List的别名:list
*/
int getCount();


查询一条数据为map集合

举例:加入我们想要查询员工数据表的最高工资、最低工资和平均工资,这时没有其对应的实体类,那应该将返回的数据存放成什么类型呢?

其实实体类和Map都是通过键值对,两者的最大区别就是,实体类中的键值对是固定的,只有设置好的那些,比如name、age、email等,查询为一个实体类必须要字段名和属性名一致,但是Map中没有固定的键,想查啥都行

/**
* 根据用户id查询用户信息为map集合
* @param id
* @return
*/
Map getUserToMap(@Param("id") int id);

password=123456, sex=男 , id=1, age=23, username=admin}-->

注意:如果查询的内容中,有字段的值为空,即null,该字段的内容是不会放在map中的。

查询多条数据为map集合

注意:一条数据对应一个map;若有多条数据,就会产生多个map集合,不能只用一个map接受,否则报错

  • 方式一
/**
* 查询所有用户信息为map集合
* @return
* 将表中的数据以map集合的方式查询,一条数据对应一个map;若有多条数据,就会产生多个map集合,此
时可以将这些map放在一个list集合中获取
*/
List> getAllUserToMap();
  • 方式二
    通过@MapKey注解设置map集合的键,值是每条数据所对应的map集合
    通过@MapKey将查询某个字段的值作为大的Map的键
/**
* 查询所有用户信息为map集合
* @return
* 将表中的数据以map集合的方式查询,一条数据对应一个map;若有多条数据,就会产生多个map集合,并
且最终要以一个map的方式返回数据,此时需要通过@MapKey注解设置map集合的键,值是每条数据所对应的
map集合
*/
@MapKey("id")
Map getAllUserToMap();

1={password=123456, sex=男, id=1, age=23, username=admin},2={password=123456, sex=男, id=2, age=23, username=张三},3={password=123456, sex=男, id=3, age=23, username=张三}
}
-->

特殊SQL的执行

模糊查询

/**
* 测试模糊查询
* @param mohu
* @return
*/
List testMohu(@Param("mohu") String mohu);


1、like '%${mohu}%'中 ${mohu},由于 ${}会解释称占位符?,但是因为?是在单引号中,所以并不会将它作为占位符使用,而是看作字符串的一部分,会报错
2、concat是拼接字符串的函数
3、用双引号的方式使用最多

批量删除

/**
* 批量删除
* @param ids
* @return
*/
int deleteMore(@Param("ids") String ids);

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

这里用到 ${}是因为如果用#{},时会自动添加单引号的,但是在sql语句中:delete from t_user where id in (‘9,10’)是错误的,正确的写法是delete from t_user where id in (9,10)——删除id为9和10的数据。

动态设置表名

/**
* 动态设置表名,查询所有的用户信息
* @param tableName
* @return
*/
List getAllUser(@Param("tableName") String tableName);


同样,表明也是不能加单引号的

添加功能获取自增的主键

场景模拟:

t_clazz(clazz_id,clazz_name)——班级表

t_student(student_id,student_name,clazz_id)——学生表

1、添加班级信息

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

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

/**
* 添加用户信息
* @param user
* @return
* useGeneratedKeys:设置使用自增的主键
* keyProperty:因为增删改有统一的返回值是受影响的行数,因此只能将获取的自增的主键放在传输的参数user对象的某个属性中(将添加的自增的主键为实体类对象的某个属性赋值)
*/
int insertUser(User user);

insert into t_user values(null,#{username},#{password},#{age},#{sex})

自定义映射resultMap

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

若字段名和实体类中的属性名不一致,则可以通过resultMap设置自定义映射(比如数据表中的字段名的命名是是用下划线,而Java中的属性名用的是驼峰的方式命名,两者不能对应上)

处理方法:
1、为表中的每个字段起别名
2、当字段名符合mysql中的命名规则使用下划线,而属性名符合Java的命名规则使用驼峰时,可以在mybatis的配置文件中统一设置一个全局配置,将下划线映射为驼峰。
在这里插入图片描述
3、使用ResultMap自定义映射处理:






多对一映射处理

场景模拟:

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

对一,对应的就是一个对象
对多,对应的就是一个集合

级联方式处理映射关系

Emp实体类中有类型为Dept的属性dept,但是我们想要返回的dept.*里有dept_id和dept_name,这两个字段名并不能和Emp的dept属性进行映射,他们应该和Emp中的dept属性的dept_id和dept_name映射





使用association处理映射关系





分步查询

①查询员工信息

/**
* 通过分步查询查询员工信息
* @param eid
* @return
*/
Emp getEmpByStep(@Param("eid") int eid);





1、这里的association 后面的select跟的是调用的select语句所在的方法的全类名+方法名,可以通过——找到方法——点击右键——Copy Reference就可以获得全类名+方法名
2、column中写的是条件,因为在第二部查询时,用到了一个参数,而这个参数是通过第一部查询获得,column中写的就是这个作为第二部查询的条件的字段

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

/**
* 分步查询的第二步: 根据员工所对应的did查询部门信息
* @param did
* @return
*/
Dept getEmpDeptByStep(@Param("did") int did);


分步查询的优点:可以实现延迟加载

但是必须在核心配置文件中设置全局配置信息:

lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载

aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载

此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。此时可通过association和collection中的fetchType属性设置当前的分步查询是否使用延迟加载, fetchType=“lazy(延迟加
载)|eager(立即加载)”
在这里插入图片描述
fetchType:在开启了延迟加载的环境中,通过设置该属性设置当前分布查询是否使用延迟加载

一对多映射处理

比如在Dept这个类中,就是多个员工对应一个部门
在这里插入图片描述

collection

collection:设置一对多的映射关系

不再使用javaType,因为前面有collection,说明处理的是集合类型,而要用ofType,指明的是集合类型的属性中存储的数据的类型

/**
* 根据部门id查新部门以及部门中的员工信息
* @param did
* @return
*/
Dept getDeptEmpByDid(@Param("did") int did);




分步查询

①查询部门信息

/**
* 分步查询部门和部门中的员工
* @param did
* @return
*/
Dept getDeptByStep(@Param("did") int did);




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

/**
* 根据部门id查询员工信息
* @param did
* @return
*/
List getEmpListByDid(@Param("did") int did);


动态SQL

Mybatis框架的动态SQL技术是一种根据特定条件动态拼装SQL语句的功能,它存在的意义是为了

解决 拼接SQL语句字符串时的痛点问题。

可以通过判断这个字段是否是null或“”(空字符串),如果是这两个值,说明没有设置对应的条件,如果不是,说明设置了条件

if

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

标签中的内容不会执行



可以看出来,我们设置的几个字段都不是null和空字符串,所以应该将这几个条件拼接到select语句中在这里插入图片描述

if 标签中的ename等属性不用#{}也不用${}就可以通过属性名得到

where

if中存在的问题:
1、以上个例子为例,如果在输入参数时,将name设置为null,那么在select语句中就会出现where后面跟了第二个if标签中的and,但是这种select出现了语法错误。
2、如果这几个字段都是null或空字符串,那select语句最后多出来一个where,让然出现语法错误

  • 解决方法一:在where后面添加一个恒成立的条件:
    在这里插入图片描述
  • 解决方法二:where关键字

where和if一般结合使用:

a>若where标签中的if条件都不满足,则where标签没有任何功能,即不会添加where关键字

b>若where标签中的if条件满足,则where标签会自动添加where关键字,并将条件最前方多余的and去掉(但是内容后多余的end无法去掉)

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


trim

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

常用属性:

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

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

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

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


choose、when、otherwise

choose、when、 otherwise相当于if…else if…else
when最少设置一个,otherwise最多设置一个
只要有一个成立,后面的条件就不在判断



foreach

collection:设置要循环的数组或集合
item:用字符串来表示数组或集合中的每一个数据
separator:设置每次循环间数据之间的分隔符
在这里插入图片描述

注意:如果前面没有添加@Param,那MyBatis是默认是这个参数是list


insert into t_emp values(null,#{emp.ename},#{emp.age},#{emp.sex},#{emp.email},null)


delete from t_emp whereeid = #{eid}


delete from t_emp where eid in#{eid}

在这里插入图片描述
在这里插入图片描述

如果参数是list或者数组,MyBatis是默认将参数放在map中
如果前面没有添加@Param,那MyBatis是默认是这个参数是list,如果是数组,那默认是Array
所以简单起见,前面最好都加上@Param
注意:批量添加和批量删除代码中,括号和foreach的位置

不加open和close的批量删除代码:在这里插入图片描述

前面的代码就是因为一个item是一个对象,而我们要去的是对象中的属性,所以写成:#{emp.ename},但是后面的代码只是将id取出来,每一个item就是id值,所以直接写成:#{eid}

open:以……开始
close:以……结束

另外一种方式:
在这里插入图片描述

SQL片段

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

eid,ename,age,sex,did

select  from t_emp

MyBatis的缓存

MyBatis的一级缓存(默认是开启的)

一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问

使一级缓存失效的四种情况:

1、不同的SqlSession对应不同的一级缓存

2、同一个SqlSession但是查询条件不同

3、同一个SqlSession两次查询期间执行了任何一次增删改操作

4、同一个SqlSession两次查询期间手动清空了缓存

创建了两个sql语句完全相同的sqlSession:
在这里插入图片描述
执行结果:(执行了2次sql语句,第二次不是从缓存中获得数据)
在这里插入图片描述

MyBatis的二级缓存

二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取

二级缓存开启的条件:

a>在核心配置文件中,设置全局配置属性cacheEnabled=“true”,默认为true,不需要设置

b>在映射文件中设置标签< cache/>
在这里插入图片描述

c>二级缓存必须在SqlSession关闭或提交之后有效
在这里插入图片描述

d>查询的数据所转换的实体类类型必须实现序列化的接口
在这里插入图片描述

使二级缓存失效的情况:

两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效

二级缓存的相关配置

在mapper配置文件中添加的cache标签可以设置一些属性:

①eviction属性:缓存回收策略,默认的是 LRU。

LRU(Least Recently Used) – 最近最少使用的:移除最长时间不被使用的对象。

FIFO(First in First out) – 先进先出:按对象进入缓存的顺序来移除它们。

SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。

WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

②flushInterval属性:刷新间隔,单位毫秒默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新

③size属性:引用数目,正整数代表缓存最多可以存储多少个对象,太大容易导致内存溢出

④readOnly属性:只读, true/false

true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了 很重要的性能优势。

false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是
false。(如果修改的话,修改的是拷贝过的对象,不会修改原始数据)

MyBatis缓存查询的顺序

先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用。

如果二级缓存没有命中,再查询一级缓存

如果一级缓存也没有命中,则查询数据库

SqlSession关闭之后,一级缓存中的数据会写入二级缓存(所以二级缓存中不一定包含所有一级缓存的)

整合第三方缓存EHCache(了解)

第三方缓存是针对二级缓存的

添加依赖


org.mybatis.cachesmybatis-ehcache1.2.1


ch.qos.logbacklogback-classic1.2.3

各jar包功能

在这里插入图片描述
下面两个,说白了,前面那个是借口,后面那个是前面的实现类

创建EHCache的配置文件ehcache.xml




设置二级缓存的类型


在这里插入图片描述

加入logback日志

存在SLF4J时,作为简易日志的log4j将失效,此时我们需要借助SLF4J的具体实现logback来打印日志。 创建logback的配置文件logback.xml(名字不能改)


[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger][%msg]%n

EHCache配置文件说明

在这里插入图片描述

MyBatis的逆向工程

正向工程:先创建Java实体类,由框架负责根据实体类生成数据库表。 Hibernate是支持正向工程的。

逆向工程:先创建数据库表,由框架负责根据数据库表,反向生成如下资源:

Java实体类
Mapper接口
Mapper映射文件

创建逆向工程的步骤

①添加依赖和插件


org.mybatismybatis3.5.7junitjunit4.12testlog4jlog4j1.2.17mysqlmysql-connector-java8.0.16


org.mybatis.generatormybatis-generator-maven-plugin1.3.0org.mybatis.generatormybatis-generator-core1.3.2mysqlmysql-connector-java8.0.16

②创建MyBatis的核心配置文件
③创建逆向工程的配置文件
文件名必须是:generatorConfig.xml



④执行MBG插件的generate目标
在这里插入图片描述
效果:
在这里插入图片描述

如果逆向工程要重新生成的话,要把上一次生成的东西删除

QBC查询

@Test
public void testMBG(){try {InputStream is = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory sqlSessionFactory = newSqlSessionFactoryBuilder().build(is);SqlSession sqlSession = sqlSessionFactory.openSession(true);EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);//查询所有数据//这里不用创建Example是因为没有用到条件/*List list = mapper.selectByExample(null);list.forEach(emp -> System.out.println(emp));*///根据条件查询/*EmpExample example = new EmpExample();创建一个条件对象Criteria,后面可以直接写条件example.createCriteria().andEmpNameEqualTo("张三").andAgeGreaterThanOrEqualTo(20);example.or().andDidIsNotNull();List list = mapper.selectByExample(example);list.forEach(emp -> System.out.println(emp));*///选择修改修改mapper.updateByPrimaryKeySelective(newEmp(1,"admin",22,null,"456@qq.com",3));} catch (IOException e) {e.printStackTrace();}
}

普通和选择之间的区别,如果是普通的,条件中有属性的值为null或没有设置相关的属性,那在数据表中会将相应的字段值设置为null,但是选择不会修改未设置值或值为null的字段。

分页插件

SQL语句中实现分页:

limit index,pageSize

pageSize:每页显示的条数

pageNum:当前页的页码

index:当前页的起始索引,index=(pageNum-1)*pageSize

count:总记录数

totalPage:总页数

totalPage = count / pageSize;

if(count % pageSize != 0){

totalPage += 1;

}

pageSize=4,pageNum=1,index=0 limit 0,4

pageSize=4,pageNum=3,index=8 limit 8,4

pageSize=4,pageNum=6,index=20 limit 8,4

以最后的语句为例,此时pageNum是6,说明当前页是6,前面一共有5页,又因为pageSize是4,说明前面的5页一共有20条数据,但是第一条数据的索引是0,所以当前的第6页的第一条数据的索引是20.

分页插件的使用步骤

①添加依赖

com.github.pagehelperpagehelper5.2.0

②配置分页插件
在MyBatis的核心配置文件中配置插件




分页插件的使用

@Test
public void testPage() {SqlSession sqlSession = SqlSessionUtil.getSqlSession();DynamicMapperSQLMapper mapper = sqlSession.getMapper(DynamicMapperSQLMapper.class);// 查询功能之前开启分页, 第1页, 每页显示4条, 并且获取部分分页的信息// Page{count=true, pageNum=2, pageSize=4, startRow=4, endRow=8, total=0, pages=0, reasonable=null, pageSizeZero=null}[]Page page = PageHelper.startPage(2, 4);System.out.println(page);// 查询List emps = mapper.getEmpByCondition(null);//输出分页信息// Page{count=true, pageNum=2, pageSize=4, startRow=4, endRow=8, total=25, pages=7, reasonable=false, pageSizeZero=false}[Emp{empId=5, empName='刘三', age=22, gender='男'}, .....]System.out.println(page);// 输出数据emps.forEach(System.out::println);// 生成导航页码信息, 更丰富页面信息PageInfo pageInfo = new PageInfo<>(emps, 5);sqlSession.close();
}
 

在这里插入图片描述

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

pageNum:当前页的页码

pageSize:每页显示的条数

b>在查询获取list集合之后,使用PageInfo pageInfo = new PageInfo<>(List list, int

navigatePages)获取分页相关数据

list:分页之后的数据

navigatePages:导航分页的页码数

比如在例子中navigatePages设置的值为5,说明下方的导航页的起始页码是当前页-2,末尾页码是当前页+2

c>分页相关数据

PageInfo{

pageNum=8, pageSize=4, size=2, startRow=29, endRow=30, total=30, pages=8,

//PageInfo中其实也有Page对象
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]

相关内容

热门资讯

Python|位运算|数组|动... 目录 1、只出现一次的数字(位运算,数组) 示例 选项代...
张岱的人物生平 张岱的人物生平张岱(414年-484年),字景山,吴郡吴县(今江苏苏州)人。南朝齐大臣。祖父张敞,东...
西游西后传演员女人物 西游西后传演员女人物西游西后传演员女人物 孙悟空 六小龄童 唐僧 徐少华 ...
名人故事中贾岛作诗内容简介 名人故事中贾岛作诗内容简介有一次,贾岛骑驴闯了官道.他正琢磨着一句诗,名叫《题李凝幽居》全诗如下:闲...
和男朋友一起优秀的文案? 和男朋友一起优秀的文案?1.希望是惟一所有的人都共同享有的好处;一无所有的人,仍拥有希望。2.生活,...
戴玉手镯的好处 戴玉手镯好还是... 戴玉手镯的好处 戴玉手镯好还是碧玺好 女人戴玉?戴玉好还是碧玺好点佩戴手镯,以和田玉手镯为佳!相嫌滑...
依然什么意思? 依然什么意思?依然(汉语词语)依然,汉语词汇。拼音:yī    rán基本解释:副词,指照往常、依旧...
高尔基的散文诗 高尔基的散文诗《海燕》、《大学》、《母亲》、《童年》这些都是比较出名的一些代表作。
心在飞扬作者简介 心在飞扬作者简介心在飞扬作者简介如下。根据相关公开资料查询,心在飞扬是一位优秀的小说作者,他的小说作...
卡什坦卡的故事赏析? 卡什坦卡的故事赏析?讲了一只小狗的故事, 我也是近来才读到这篇小说. 作家对动物的拟人描写真是惟妙...
林绍涛为简艾拿绿豆糕是哪一集 林绍涛为简艾拿绿豆糕是哪一集第三十二集。 贾宽认为是阎帅间接导致刘映霞住了院,第二天上班,他按捺不...
小爱同学是女生吗小安同学什么意... 小爱同学是女生吗小安同学什么意思 小爱同学,小安同学说你是女生。小安是男的。
内分泌失调导致脸上长斑,怎么调... 内分泌失调导致脸上长斑,怎么调理内分泌失调导致脸上长斑,怎么调理先调理内分泌,去看中医吧,另外用好的...
《魔幻仙境》刺客,骑士人物属性... 《魔幻仙境》刺客,骑士人物属性加点魔幻仙境骑士2功1体质
很喜欢她,该怎么办? 很喜欢她,该怎么办?太冷静了!! 太理智了!爱情是需要冲劲的~不要考虑着考虑那~否则缘...
言情小说作家 言情小说作家我比较喜欢匪我思存的,很虐,很悲,还有梅子黄时雨,笙离,叶萱,还有安宁的《温暖的玄》 小...
两个以名人的名字命名的风景名胜... 两个以名人的名字命名的风景名胜?快太白楼,李白。尚志公园,赵尚志。
幼儿教育的代表人物及其著作 幼儿教育的代表人物及其著作卡尔威特的《卡尔威特的教育》,小卡尔威特,他儿子成了天才后写的《小卡尔威特...
海贼王中为什么说路飞打凯多靠霸... 海贼王中为什么说路飞打凯多靠霸气升级?凯多是靠霸气升级吗?因为之前刚到时确实打不过人家因为路飞的实力...
运气不好拜财神有用吗运气不好拜... 运气不好拜财神有用吗运气不好拜财神有没有用1、运气不好拜财神有用。2、拜财神上香前先点蜡烛,照亮人神...