特性
MyBatis提供的持久层框架包括SQL Maps和Data Access Objects(DAO)
MyBatis是支持定制化SQL、存储过程以及高级映射的优秀持久层框架
MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集
MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录
MyBatis是一个半自动的ORM(Object Relation Mapping)框架
和其它持久化层技术对比
JDBC
SQL夹杂在Java代码中,耦合度高,导致硬编码内伤
维护不易且实际开发需要中SQL有变化,频繁修改的情况多见
代码冗长,开发效率低
Hibernate和JPA
操作简便,开发效率高
程序中的长难复杂SQL需要绕过框架
内部自动生产SQL,不容易做特殊优化
基于全映射的全自动框架,大量字段的POJO进行部分映射时比较困难
反射操作太多,导致数据库性能下降
MyBatis
轻量级,性能出色
SQL和Java编码分开,功能边界清晰。Java代码专注业务、SQL语句专注数据
开发效率稍逊于Hibernate,但是完全能够接受
搭建MyBatis
1、导入依赖
1 2 3 4 5 6 7 8 9 10 11 12 <dependencies > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis</artifactId > <version > 3.5.9</version > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 8.0.29</version > </dependency > </dependencies >
2、创建MyBatis的核心配置文件
习惯上命名为mybatis-config.xml,但只是建议,并非强制要求,整合Spring之后这个配置文件可以省略
核心配置文件主要用于配置连接数据库的环境和MyBatis的全局配置信息
核心配置文件存放位置是src/main/resources目录下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <?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/jdbc_learn?serverTimezone=UTC" /> <property name ="username" value ="root" /> <property name ="password" value ="123456" /> </dataSource > </environment > </environments > <mappers > <mapper resource ="mappers/UserMapper.xml" /> </mappers > </configuration >
3、创建mapper接口
MyBatis中的mapper接口相当于以前的DAO,但区别在于Mapper仅仅是接口,不需要自己提供实现类 1 2 3 4 5 6 7 8 9 10 11 public interface UserMapper { int insertUser () ; int updateUser () ; int deleteUser () ; User getUserById () ; List<User> getAllUser () ; }
4、创建MyBatis映射文件
映射文件命名规则:表所对应的实体类名+Mapper.xml,如UserMapper.xml
MyBatis映射文件用于编写SQL,访问以及操作表中的数据
MyBatis映射文件存放的位置是src/main/resources/mappers目录下
MyBatis中可以面向接口操作数据,要保证两个一致:
mapper接口的全类名和映射文件的命名空间(namespace)保持一致
mapper接口的方法名和映射文件中编写SQL的标签的id属性保持一致 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <?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.zephon.mybatis.mapper.UserMapper" > <insert id ="insertUser" > insert into user values(null, 'admin', '123456', '上海市', '13211223311') </insert > <update id ="updateUser" > update user set name='root',password='123' where id=1 </update > <delete id ="deleteUser" > delete from user where id=1 </delete > <select id ="getUserById" resultType ="com.zephon.mybatis.pojo.User" > select * from user where id=2 </select > <select id ="getAllUser" resultType ="com.zephon.mybatis.pojo.User" > select * from user </select > </mapper >
5、手动测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 InputStream resourceStream = Resources.getResourceAsStream("mybatis-config.xml" ); SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(resourceStream); SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); int result = mapper.insertUser();System.out.println(result); sqlSession.commit(); sqlSession.close();
核心配置文件
:最外层的标签,表示MyBatis的核心配置
:引入外部properties文件,之后可以在当前文件中使用${key}方式访问对应的值
:配置设置
:具体设置,例如:
name:设置名称,如mapUnderscoreToCamelCase表示是否开启下划线与驼峰命名之间的转换
mapUnderscoreToCamelCase:是否开启下划线与驼峰命名转换
lazyLoadingEnabled:延迟加载的全局开关
aggressiveLazyLoading:按需加载,当开启时任何方法的调用都会加载该对象的所有属性,否则每个属性会按需加载
value:设置对应的值
:设置类型别名,即为某个具体类型设置一个别名;在MyBatis范围内再用到对应类型时就可以直接用对应的别名了
:具体的类型别名
type:需要起别名的类型对应的全限定类名
alias:设置类型对应的别名,如果不设置,默认值为全限定类名对应的最后的具体类名(不区分大小)
:以包的方式设置别名,使得对应包下所有类将拥有默认类名
:配置插件,如分页插件
:表示连接数据库的环境,内部可以配置多个具体环境(如开发环境、测试环境等)
default:值为某个环境的id,表示默认使用的环境
:表示具体的连接数据库环境
id:唯一标识
:设置事务管理器
type:表示事务管理的方式,可选值为JDBC 或MANAGED ;
JDBC表示使用JDBC中原生的事务管理方式;
MANAGED:表示被管理,例如Spring
:设置数据源
type:设置数据源类型,可选值为POOLED 或UNPOOLED 或JNDI ,
POOLED表示使用数据库连接池;
UNPOOLED表示不使用数据库连接池;
JNDI:表示使用上下文中的数据源
:数据源中的属性
:引入mybatis的映射文件
:引入单个mybatis映射文件
:以包的方式批量引入映射文件,但必须满足:1. mapper接口和映射文件所在的包必须一致;2. mapper接口名和映射文件名必须一致;例如,UserMapper.java在main/java/com/zephon/mybatis/mapper/下,则UserMapper.xml就必须在main/resources/com/zephon/mybatis/mapper/下
MyBatis获取参数值的两种方式
MyBatis获取参数的两种方式:${}和#{}
${}的本质就是字符串拼接,#{}的本质就是占位符赋值
${}使用字符串拼接的方式拼接SQL,若为字符串类型或日期类型的字段进行赋值,需要手动加单引号;但#{}使用占位符赋值的方式拼接SQL,此时为字符串类型或日期类型的字段进行赋值时,可以自动添加单引号
单个字面量类型的参数
如果mapper接口的方法参数为单个的字面量类型,则可以使用${}或#{}以任意名称获取参数的值,注意${}需要手动添加单引号
如果获取的数据类型是List类型,则对应名称必须是list
如果获取的数据类型是数组类型,则对应名称必须是array
例: 1 2 3 <select id ="getUserById" resultType ="com.zephon.mybatis.pojo.User" > select * from user where id=#{id} </select >
多个字面量类型的参数
若mapper接口中的方法参数为多个时,此时MyBatis会自动将这些参数放在一个map集合中,以arg0 ,arg1...为键,以参数为值;以param1 ,param2,...为键,以参数为值;因此只需要通过${}和#{}访问map集合的键就可以获取相应的值,注:${}需要手动加单引号
例: 1 2 3 <select id ="checkLogin" resultType ="com.zephon.mybatis.pojo.User" > select * from user where name=#{param1} and password=#{param2} </select >
Map集合类型的参数
若mapper接口中的方法需要的参数为多个时,此时可以手动创建map集合,将这些数据放在map中,只需要通过${}或#{}访问map集合的键就可以获取相对应的值,注意${}需要手动加单引号
例: 1 2 3 <select id ="checkLoginByMap" resultType ="com.zephon.mybatis.pojo.User" > select * from user where name=#{name} and password=#{password} </select >
实例类类型的参数
若mapper接口方法的参数为实体类类型的参数,只需要通过${}或#{}访问实体类中的属性名,就可以获取相对应的属性值,一定要注意${}的单引号问题
例: 1 2 3 <insert id ="insertUser" > insert into user values(null, #{name}, #{password}, #{address}, #{phone}) </insert >
使用@Param自定义参数标识
可以在mapper接口方法的参数上设置@Param注解,此时MyBatis会将这些参数放在Map中,以两种方式存储:
以@Param注解的value属性值为键,以参数为值
以param1,param2...为键,以参数为值
例: 1 User checkLogin (@Param("name") String name,@Param("password") String password) ;
1 2 3 <select id ="checkLogin" resultType ="com.zephon.mybatis.pojo.User" > select * from user where name=#{name} and password=#{password} </select >
MyBatis的各种查询功能
查询一个实体类对象
1 User getUserById (Integer id) ;
1 2 3 <select id ="getUserById" resultType ="com.zephon.mybatis.pojo.User" > select * from user where id=#{id} </select >
查询一个List集合
1 List<User> getAllUser () ;
1 2 3 <select id ="getAllUser" resultType ="com.zephon.mybatis.pojo.User" > select * from user </select >
查询单个数据
1 2 3 4 5 6 7 8 9 10 11 12 <select id ="getUserById" resultType ="com.zephon.mybatis.pojo.User" > select * from user where id=#{id} </select > <select id ="getCount" resultType ="int" > select count(*) from user </select >
查询一条数据为Map集合
1 Map<String, Object> getUserByIdToMap (Integer id) ;
1 2 3 <select id ="getUserByIdToMap" resultType ="map" > select * from user where id=#{id} </select >
查询多条数据为Map集合
转换成List 1 List<Map> getAllUserToMap () ;
1 2 3 <select id ="getAllUserToMap" resultType ="map" > select * from user </select >
映射到Map,组成嵌套Map 1 2 3 @MapKey("id") Map<String, Object> getAllUserToMap () ;
1 2 3 <select id ="getAllUserToMap" resultType ="map" > select * from user where name='admin' </select >
特殊SQL的执行
模糊查询
1 List<User> selectByLikeName (String namePattern) ;
1 2 3 4 5 6 7 8 9 10 11 <select id ="selectByLikeName" resultType ="com.zephon.mybatis.pojo.User" > select * from user where name like '%${namePattern}%' </select > <select id ="selectByLikeName" resultType ="com.zephon.mybatis.pojo.User" > select * from user where name like concat('%', #{namePattern}, '%') </select > <select id ="selectByLikeName" resultType ="com.zephon.mybatis.pojo.User" > select * from user where name like "%"#{namePattern}"%" </select >
批量删除
1 int deleteMany (String ids) ;
1 2 3 4 <delete id ="deleteMany" > delete from user where id in(${ids}) </delete >
动态设置表名
1 List<User> getAllUser (@Param("tableName") String tableName) ;
1 2 3 4 <select id ="getAllUser" resultType ="com.zephon.mybatis.pojo.User" > select * from ${tableName} </select >
添加功能时获取自增主键
1 void insertUserReturn (User user) ;
1 2 3 4 5 6 7 <insert id ="insertUserReturn" useGeneratedKeys ="true" keyProperty ="id" > insert into user values(null, #{name}, #{password}, #{address}, #{phone}) </insert >
自定义映射的resultMap
:自定义映射关系
id:唯一标识
type:要处理映射关键的实体类的类型
:处理主键和实体类中属性的映射关系
column:设置映射关系中的字段名,必须是SQL查询出的某个字段
property:设置映射关系中属性的属性名,必须是处理的实体类类型中的属性名
:处理普通字段和实体类中属性的映射关系
:处理多对一的映射关系(处理实体类类型的属性)
property:设置实体类类型属性的属性名
javaType:设置要处理的属性的类型(全限定类名)
select:如果使用分步查询,则设置分配查询的SQL的唯一标识
column:设置分步查询的SQL条件
fetchType:在开启了全局延迟加载的环境中,单独设置对应属性是否进行延迟加载,可选eager/lazy
:处理一对多映射关系(处理集合类型的属性 )
property:设置实体类类型属性的属性名
ofType:集合中保存数据的类型
reslutMap处理字段和属性的映射关系
若字段名称和实体类中的属性名不一致,则可以通过resultMap设置自定义映射
如:表名中使用的下划线,POJO中使用的驼峰命名 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <resultMap id ="empResultMap" type ="Emp" > <id column ="emp_id" property ="empId" /> <result column ="emp_name" property ="empName" /> <result column ="age" property ="age" /> <result column ="gender" property ="gender" /> </resultMap > <select id ="getEmpById" resultMap ="empResultMap" > select * from t_emp where emp_id=#{empId} </select >
多对一映射处理
1、级联映射
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <resultMap id ="empAndDeptResultMap" type ="Emp" > <id column ="emp_id" property ="empId" /> <result column ="emp_name" property ="empName" /> <result column ="age" property ="age" /> <result column ="gender" property ="gender" /> <result column ="dept_id" property ="dept.deptId" /> <result column ="dept_name" property ="dept.deptName" /> </resultMap > <select id ="getEmpAndDept" resultMap ="empAndDeptResultMap" > select t_emp.*, t_dept.* from t_emp left join t_dept on t_emp.dept_id=t_dept.dept_id where t_emp.emp_id=#{empId} </select >
2、使用association处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <resultMap id ="empAndDeptResultMap" type ="Emp" > <id column ="emp_id" property ="empId" /> <result column ="emp_name" property ="empName" /> <result column ="age" property ="age" /> <result column ="gender" property ="gender" /> <association property ="dept" javaType ="Dept" > <id column ="dept_id" property ="deptId" /> <result column ="dept_name" property ="deptName" /> </association > </resultMap > <select id ="getEmpAndDept" resultMap ="empAndDeptResultMap" > select t_emp.*, t_dept.* from t_emp left join t_dept on t_emp.dept_id=t_dept.dept_id where t_emp.emp_id=#{empId} </select >
3、使用分步查询
1 2 3 4 5 6 7 8 9 10 11 12 13 <resultMap id ="empAndDeptByStepResultMap" type ="Emp" > <id column ="emp_id" property ="empId" /> <result column ="emp_name" property ="empName" /> <result column ="age" property ="age" /> <result column ="gender" property ="gender" /> <association property ="dept" fetchType ="eager" select ="com.zephon.mybatis.mappers.DeptMapper.getDeptById" column ="dept_id" /> </resultMap > <select id ="getEmpAndDeptByStep" resultMap ="empAndDeptByStepResultMap" > select * from t_emp where emp_id=#{empId} </select >
优点:可以实现延迟加载 但必须在核心配置文件中设置全局配置信息: lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载 aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载 此时就可以实现按需加载,获取数据是什么,就只会执行相应的SQL。此时可通过association和collection中的fetchType属性设置当前的分步查询是否使用延迟加载,fetchType="lazy(延迟加载)|eager(立即加载)"
一对多映射处理
1、使用collection处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <resultMap id ="deptAndEmpsResultMap" type ="Dept" > <id column ="dept_id" property ="deptId" /> <result column ="dept_name" property ="deptName" /> <collection property ="emps" ofType ="Emp" > <id column ="emp_id" property ="empId" /> <result column ="emp_name" property ="empName" /> <result column ="age" property ="age" /> <result column ="gender" property ="gender" /> </collection > </resultMap > <select id ="getDeptAndEmpsByDeptId" resultMap ="deptAndEmpsResultMap" > select t_dept.*, t_emp.* from t_dept left join t_emp on t_dept.dept_id = t_emp.dept_id where t_dept.dept_id = #{deptId} </select >
2、使用分步查询
1 2 3 <select id ="getEmpListByDeptId" resultType ="Emp" > select * from t_emp where dept_id=#{deptId} </select >
1 2 3 4 5 6 7 8 9 10 11 12 <resultMap id ="deptAndEmpsByStepResultMap" type ="Dept" > <id column ="dept_id" property ="deptId" /> <result column ="dept_name" property ="deptName" /> <collection property ="emps" select ="com.zephon.mybatis.mappers.EmpMapper.getEmpListByDeptId" column ="dept_id" > </collection > </resultMap > <select id ="getDeptAndEmpsByStep" resultMap ="deptAndEmpsByStepResultMap" > select * from t_dept where dept_id = #{deptId} </select >
动态SQL
MyBatis框架的动态SQL技术是一种根据特定条件动态拼装SQL语句的功能,它存在的意义是为了解决拼接SQL语句字符串时的痛点问题
if
标签可通过test属性的表达式进行判断,若表达式结果为true,则标签中内容会执行;反之则不会执行
例: 1 2 3 4 5 6 7 <select id ="getEmpListByCondition" resultType ="Emp" > select * from t_emp where 1=1 <if test ="empName!='' and empName!=null" > and emp_name=#{empName}</if > <if test ="age!='' and age!=null" > and age=#{age}</if > <if test ="gender!='' and gender!=null" > and gender=#{gender}</if > </select >
where
若标签中有条件成立,会自动生成where关键字
会自动将标签中内容前多余的and去除,内容后多余的and无法去掉
若标签中没有任何一个条件成立,则没有任何功能
例: 1 2 3 4 5 6 7 8 9 <select id ="getEmpListByCondition" resultType ="Emp" > select * from t_emp <where > <if test ="empName!='' and empName!=null" > emp_name=#{empName}</if > <if test ="age!='' and age!=null" > and age=#{age}</if > <if test ="gender!='' and gender!=null" > and gender=#{gender}</if > </where > </select >
## trim
prefix属性:在标签中的内容的前面添加指定内容
suffix属性:在标签中的内容的后面添加指定内容
prefixOverrides:在标签中的内容前面去掉指定内容
suffixOverrides:在标签中的内容后面去掉指定内容 1 2 3 4 5 6 7 8 9 <select id ="getEmpListByCondition" resultType ="Emp" > select * from t_emp <trim prefix ="where" suffixOverrides ="and" > <if test ="empName!='' and empName!=null" > emp_name=#{empName} and</if > <if test ="age!='' and age!=null" > age=#{age} and</if > <if test ="gender!='' and gender!=null" > gender=#{gender}</if > </trim > </select >
choose、when、otherwise
与条件语句类似,相当于java中的if...else if...else if... else
:至少设置一个
:最多设置一个 1 2 3 4 5 6 7 8 9 10 11 <select id ="getEmpListByChoose" resultType ="Emp" > select * from t_emp <where > <choose > <when test ="empName!=null and empName!=''" > emp_name = #{empName}</when > <when test ="age!=null and age!=''" > age = #{age}</when > <when test ="gender!=null and gender!=''" > gender = #{gender}</when > </choose > </where > </select >
foreach
foreach:循环
collection:要循环的数组或集合
item:数组或集合中的每一个数据
separator:设置每次循环的数据之间的分割符
open:循环结果字符串以什么开始
close:循环结果字符串以什么结尾
例:批量添加 1 2 3 4 5 6 7 8 <insert id ="insertManyEmp" > insert into t_emp values <foreach collection ="list" item ="emp" separator ="," > (null, #{emp.empName}, #{emp.age}, #{emp.gender}, null) </foreach > </insert >
例:批量删除 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <delete id ="deleteManyEmp" > delete from t_emp where emp_id in ( <foreach collection ="empIds" item ="empId" separator ="," > #{empId} </foreach > ) </delete > <delete id ="deleteManyEmp" > delete from t_emp where emp_id in <foreach collection ="empIds" item ="empId" separator ="," open ="(" close =")" > #{empId} </foreach > </delete > <delete id ="deleteManyEmp" > delete from t_emp where <foreach collection ="empIds" item ="empId" separator ="or" > emp_id = #{empId} </foreach > </delete >
SQL片段
将常用SQL封装在一起,然后在需要时通过标签进行引用
id属性:唯一标识,用于在标签的refid定位 1 2 3 4 5 6 <sql id ="empColumns" > emp_id, emp_name, age, gender, dept_id </sql > <select id ="getEmpById" resultType ="Emp" > select <include refid ="empColumns" /> from t_emp where emp_id=#{empId} </select >
MyBatis的缓存
MyBatis的一级缓存
一级缓存是SqlSession级别 的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问
使一级缓存失效的四种情况:
不同的SqlSession对应不同的一级缓存
同一个SqlSession但查询条件不同
同一个SqlSession两次查询期间执行了任何一次增删改操作
同一个SqlSession再次查询期间手动清空了缓存
MyBatis的二级缓存
二级缓存是SqlSessionFactory级别 ,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取
二级缓存开启的条件:
在核心配置文件中,设置全局配置属性cacheEnabled="true" ,默认为true,不需要设置
在映射文件中设置标签
二级缓存必须在SqlSession关闭或提交之后有效
查询的数据所转换的实体类类型必须实现序列化的接口
使二级缓存失效的情况:
再次查询之间执行了任意的增删改,会使一级和二级缓存同时失效
二级缓存相关配置
在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
添加依赖
1 2 3 4 5 6 <dependency > <groupId > org.mybatis.caches</groupId > <artifactId > mybatis-ehcache</artifactId > <version > 1.2.1</version > </dependency >
创建EHCache的配置文件ehcache.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?xml version="1.0" encoding="utf-8" ?> <ehcache xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation ="../config/ehcache.xsd" > <diskStore path ="D:\ehcache" /> <defaultCache maxElementsInMemory ="1000" maxElementsOnDisk ="10000000" eternal ="false" overflowToDisk ="true" timeToIdleSeconds ="120" timeToLiveSeconds ="120" diskExpiryThreadIntervalSeconds ="120" memoryStoreEvictionPolicy ="LRU" > </defaultCache > </ehcache >
设置二级缓存的类型
1 <cache type ="org.mybatis.caches.ehcache.EhcacheCache" />
EHCache配置文件说明
maxElementsInMemory:必填,表示在内存中缓存的element的最大数目
maxElementsOnDisk :必填,表示在磁盘上缓存的element的最大数目,若是0表示无穷大
eternal:必填,表示 设定缓存的elements是否永远不过期。 如果为 true,则缓存的数据始终有效, 如果为false那么还 要根据timeToIdleSeconds、timeToLiveSeconds 判断
overflowToDisk:必填,表示设定当内存缓存溢出的时候是否将过期的element 缓存到磁盘上
timeToIdleSeconds: 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时, 这些数据便会删除,默认值是0,也就是可闲置时间无穷大
timeToLiveSeconds: 缓存element的有效生命期,默认是0.,也就是 element存活时间无穷大
diskSpoolBufferSizeMB: DiskStore(磁盘缓存)的缓存区大小。默认是 30MB。每个Cache都应该有自己的一个缓冲区
diskPersistent: 在VM重启的时候是否启用磁盘保存EhCache中的数 据,默认是false。
diskExpiryThreadIntervalSeconds: 磁盘缓存的清理线程运行间隔,默认是120秒。每 个120s, 相应的线程会进行一次EhCache中数据的 清理工作
memoryStoreEvictionPolicy: 当内存缓存达到最大,有新的element加入的时 候, 移除缓存中element的策略。 默认是LRU (最 近最少使用),可选的有LFU (最不常使用)和 FIFO (先进先出)
MyBatis的逆向工程
正向工程:先创建Java实体类,由框架负责根据实体类生成数据库表。Hibernate是支持正向工程的。 逆向工程:先创建数据库表,由框架负责根据数据库表,反向生成: - Java实体类 - Mapper接口 - Mapper映射文件
逆向工程步骤
添加插件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <build > <plugins > <plugin > <groupId > org.mybatis.generator</groupId > <artifactId > mybatis-generator-maven-plugin</artifactId > <version > 1.4.0</version > <dependencies > <dependency > <groupId > org.mybatis.generator</groupId > <artifactId > mybatis-generator-core</artifactId > <version > 1.4.0</version > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 8.0.29</version > </dependency > </dependencies > </plugin > </plugins > </build >
创建MyBatis核心配置文件
创建逆向工程的配置文件generatorConfig.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 <?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 > <context id ="DB2Tables" targetRuntime ="MyBatis3Simple" > <jdbcConnection driverClass ="com.mysql.cj.jdbc.Driver" connectionURL ="jdbc:mysql://localhost:3306/jdbc_learn? serverTimezone=UTC" userId ="root" password ="123456" > </jdbcConnection > <javaModelGenerator targetPackage ="com.zephon.mybatis.pojo" targetProject =".\src\main\java" > <property name ="enableSubPackages" value ="true" /> <property name ="trimStrings" value ="true" /> </javaModelGenerator > <sqlMapGenerator targetPackage ="com.zephon.mybatis.mappers" targetProject =".\src\main\resources" > <property name ="enableSubPackages" value ="true" /> </sqlMapGenerator > <javaClientGenerator type ="XMLMAPPER" targetPackage ="com.zephon.mybatis.mappers" targetProject =".\src\main\java" > <property name ="enableSubPackages" value ="true" /> </javaClientGenerator > <table tableName ="t_emp" domainObjectName ="Emp" /> <table tableName ="t_dept" domainObjectName ="Dept" /> </context > </generatorConfiguration >
执行MBG插件的generate目标
在Maven中点击mybatis-generator:generate即可
效果
# MyBatis整合分页插件
添加依赖 1 2 3 4 5 6 <dependency > <groupId > com.github.pagehelper</groupId > <artifactId > pagehelper</artifactId > <version > 5.3.0</version > </dependency >
配置分页插件
在MyBatis的核心配置文件中配置插件: 1 2 3 <plugins > <plugin interceptor ="com.github.pagehelper.PageInterceptor" /> </plugins >
使用
在查询功能之前使用PageHelper.startPage(int pageNum, int pageSize)开启分页功能
pageNum:当前页的页码
pageSize:每页显示的条数 1 2 3 4 5 6 SqlSession sqlSession = SqlSessionUtil.getSqlSession(); EmpMapper mapper = sqlSession.getMapper(EmpMapper.class); PageHelper.startPage(1 , 2 ); List<Emp> emps = mapper.selectByExample(null ); emps.forEach(System.out::println);
在查询获取list集合之后,使用PageInfo pageInfo = new PageInfo<>(List list, int navigatePages)获取分页相关数据
list:分页之后的数据
navigatePages:导航分页的页码数
分页相关数据: > PageInfo{ > pageNum=1, pageSize=2, size=2, startRow=1, endRow=2, total=4, pages=2, > list=Page{count=true, pageNum=1, pageSize=2, startRow=0, endRow=2, total=4, pages=2, reasonable=false, pageSizeZero=false}[com.zephon.mybatis.pojo.Emp@7e057f43, com.zephon.mybatis.pojo.Emp@6c284af], > prePage=0, nextPage=2, isFirstPage=true, isLastPage=false, hasPreviousPage=false, > hasNextPage=true, navigatePages=5, navigateFirstPage=1, navigateLastPage=2, > navigatepageNums=[1, 2] > } > pageNum:当前页的页码 > pageSize:每页显示条数 > size:当前页显示的真实条数 > total:总记录数 > pages:总页数 > prePage:上一页的页码 > nextPage:下一面的页码 > isFirstPage/isLastPage:是否为第一页/最后一页 > hasPreviousPage/hasNextPage:是否存在上一页/下一页 > navigatePages:导航分页的页码数 > navigatepageNums:导航分布的页码,[1,2,3,4,5]
SSM整合
总体流程:
1、添加依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 <?xml version="1.0" encoding="UTF-8"?> <project xmlns ="http://maven.apache.org/POM/4.0.0" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion > 4.0.0</modelVersion > <groupId > com.zephon.ssm</groupId > <artifactId > ssm</artifactId > <version > 1.0-SNAPSHOT</version > <packaging > war</packaging > <properties > <maven.compiler.source > 8</maven.compiler.source > <maven.compiler.target > 8</maven.compiler.target > <project.build.sourceEncoding > UTF-8</project.build.sourceEncoding > <spring.version > 5.3.22</spring.version > </properties > <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-aop</artifactId > <version > 2.7.2</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-test</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-webmvc</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-jdbc</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > javax.servlet</groupId > <artifactId > javax.servlet-api</artifactId > <version > 3.1.0</version > <scope > provided</scope > </dependency > <dependency > <groupId > org.thymeleaf</groupId > <artifactId > thymeleaf-spring5</artifactId > <version > 3.0.15.RELEASE</version > </dependency > <dependency > <groupId > com.fasterxml.jackson.core</groupId > <artifactId > jackson-databind</artifactId > <version > 2.13.3</version > </dependency > <dependency > <groupId > commons-fileupload</groupId > <artifactId > commons-fileupload</artifactId > <version > 1.4</version > </dependency > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis</artifactId > <version > 3.5.9</version > </dependency > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis-spring</artifactId > <version > 2.0.6</version > </dependency > <dependency > <groupId > com.alibaba</groupId > <artifactId > druid</artifactId > <version > 1.2.8</version > </dependency > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.13.2</version > <scope > test</scope > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 8.0.29</version > </dependency > <dependency > <groupId > log4j</groupId > <artifactId > log4j</artifactId > <version > 1.2.17</version > </dependency > <dependency > <groupId > com.github.pagehelper</groupId > <artifactId > pagehelper</artifactId > <version > 5.3.0</version > </dependency > <dependency > <groupId > ch.qos.logback</groupId > <artifactId > logback-classic</artifactId > <version > 1.3.0-alpha16</version > </dependency > </dependencies > </project >
2、配置web.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns ="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version ="4.0" > <filter > <filter-name > characterEncodingFilter</filter-name > <filter-class > org.springframework.web.filter.CharacterEncodingFilter</filter-class > <init-param > <param-name > encoding</param-name > <param-value > UTF-8</param-value > </init-param > <init-param > <param-name > forceEncoding</param-name > <param-value > true</param-value > </init-param > </filter > <filter-mapping > <filter-name > characterEncodingFilter</filter-name > <url-pattern > /*</url-pattern > </filter-mapping > <filter > <filter-name > hiddenHttpMethodFilter</filter-name > <filter-class > org.springframework.web.filter.HiddenHttpMethodFilter</filter-class > </filter > <filter-mapping > <filter-name > hiddenHttpMethodFilter</filter-name > <url-pattern > /*</url-pattern > </filter-mapping > <servlet > <servlet-name > SpringMVC</servlet-name > <servlet-class > org.springframework.web.servlet.DispatcherServlet</servlet-class > <init-param > <param-name > contextConfigLocation</param-name > <param-value > classpath:springmvc.xml</param-value > </init-param > <load-on-startup > 1</load-on-startup > </servlet > <servlet-mapping > <servlet-name > SpringMVC</servlet-name > <url-pattern > /</url-pattern > </servlet-mapping > <listener > <listener-class > org.springframework.web.context.ContextLoaderListener</listener-class > </listener > <context-param > <param-name > contextConfigLocation</param-name > <param-value > classpath:spring.xml</param-value > </context-param > </web-app >
3、配置springmvc.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:context ="http://www.springframework.org/schema/context" xmlns:mvc ="http://www.springframework.org/schema/mvc" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd" > <context:component-scan base-package ="com.zephon.ssm.controller" /> <bean id ="viewResolver" class ="org.thymeleaf.spring5.view.ThymeleafViewResolver" > <property name ="order" value ="1" /> <property name ="characterEncoding" value ="UTF-8" /> <property name ="templateEngine" > <bean class ="org.thymeleaf.spring5.SpringTemplateEngine" > <property name ="templateResolver" > <bean class ="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver" > <property name ="prefix" value ="/WEB-INF/templates/" /> <property name ="suffix" value =".html" /> <property name ="templateMode" value ="HTML5" /> <property name ="characterEncoding" value ="UTF-8" /> </bean > </property > </bean > </property > </bean > <mvc:default-servlet-handler /> <mvc:annotation-driven /> <mvc:view-controller path ="/" view-name ="index" /> <bean id ="multipartResolver" class ="org.springframework.web.multipart.commons.CommonsMultipartResolver" /> </beans >
4、配置spring.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:context ="http://www.springframework.org/schema/context" xmlns:tx ="http://www.springframework.org/schema/tx" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd" > <context:component-scan base-package ="com.zephon.ssm" > <context:exclude-filter type ="annotation" expression ="org.springframework.stereotype.Controller" /> </context:component-scan > <context:property-placeholder location ="classpath:jdbc.properties" /> <bean id ="dataSource" class ="com.alibaba.druid.pool.DruidDataSource" > <property name ="driverClassName" value ="${jdbc.driver}" /> <property name ="url" value ="${jdbc.url}" /> <property name ="username" value ="${jdbc.username}" /> <property name ="password" value ="${jdbc.password}" /> </bean > <bean class ="org.mybatis.spring.SqlSessionFactoryBean" > <property name ="configLocation" value ="classpath:mybatis-config.xml" /> <property name ="dataSource" ref ="dataSource" /> <property name ="typeAliasesPackage" value ="com.zephon.ssm.pojo" /> <property name ="plugins" > <array > <bean class ="com.github.pagehelper.PageInterceptor" /> </array > </property > </bean > <bean class ="org.mybatis.spring.mapper.MapperScannerConfigurer" > <property name ="basePackage" value ="com.zephon.ssm.mappers" /> </bean > <bean id ="transactionManager" class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" > <property name ="dataSource" ref ="dataSource" /> </bean > <tx:annotation-driven transaction-manager ="transactionManager" /> </beans >
5、如果需要,配置mybatis-config.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?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 > <settings > <setting name ="mapUnderscoreToCamelCase" value ="true" /> </settings > </configuration >
6、配置log4j.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <?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 >
7、开始使用
编写Mapper(或使用逆向工程生成)
编写Service 1 2 3 public interface EmpService { List<Emp> selectAll () ; }
1 2 3 4 5 6 7 8 9 10 @Service public class EmpServiceImpl implements EmpService { @Autowired EmpMapper empMapper; @Override public List<Emp> selectAll () { return empMapper.selectAll(); } }
编写Controller 1 2 3 4 5 6 7 8 9 @RestController public class EmpController { @Autowired EmpService empService; @GetMapping("/emp") public List<Emp> selectAll () { return empService.selectAll(); } }