5月1日
一、MyBatis特性
- MyBatis是支持定制化SQL、存储过程以及高级映射的优秀的持久层框架
- MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集
- MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和java的POJO映射成数据库中的记录
- MyBatis是一个半自动的ORM框架
二、MyBatis环境搭建
1、加入依赖
mysql-connector-java、mybatis
2、创建MyBatis核心配置文件加入配置。
一般命名为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>
<!-- 配置连接数据库的环境-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="136011760"/>
</dataSource>
</environment>
</environments>
<!-- 引入映射文件-->
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
3、创建表所对应的POJO类
4、创建Mapper接口
MyBatis中的mapper接口相当于以前的dao,但区别在于,mapper仅仅是接口,我们不需要提供实现类。命名规则:POJO类名+Mapper
5、创建MyBatis映射文件
1)映射文件的命名规则
-
表所对应的实体类的类名+Mapper.xml
-
例如:表t_user,映射的实体类为User,Mapper接口为UserMapper,MyBatis映射文件为UserMapper.xml
2)MyBatis中可以面向接口操作数据,要保持两个一致
-
mapper接口的全类名和映射文件的命名空间(namepace)保持一致
-
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.cjy.mapper.UserMapper">
<insert id="insertUser">
INSERT INTO t_user VALUES (null, 'cjy', '136011760')
</insert>
</mapper>
6、在MyBatis核心配置文件引入MyBatis映射文件
<!-- 引入映射文件-->
<mappers>
<mapper resource="mappers/UserMapper.xml"/>
</mappers>
三、MyBatis的使用
1、加载MyBatis的核心配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
2、创建SqlSessinonFactoryBuilder对象
SqlSessinon工厂的制造对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
3、获取SqlSessionFactory对象
根据核心配置文件的输入流获取
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
4、获取SqlSession对象
SqlSession:代表java程序和数据库之间的会话。(HttpSession是java程序和浏览器之间的会话)
SqlSession sqlSession = sqlSessionFactory.openSession();
1)获取可以自动提交事务的SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession(true);
2)获取SqlSeesion对象的主要过程
-
从配置中获取Environment
-
从Environment获取DataSource
-
从Environment中获取TransactionFactory
-
从DataSource里获取数据库连接对象Connection
-
在取得的数据库连接上创建事务对象Transaction
-
创建执行器Executor(该对象非常重要,事实上SqlSession的所有操作都是通过它完成的)
-
创建SqlSession对象
5、获取Mapp接口
原理是通过动态代理,增强的功能是帮我们创建接口实现类。
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
6、功能实现
执行流程
- 调用接口的方法时会先找到与接口对应的映射文件
- 将方法名与编写SQL的标签的id匹配
- 执行sql语句
- 返回结果(如果返回的一条或多条记录则返回的是POJO对象)
int insertUser = mapper.insertUser();
7、提交事务
默认会设置事务,需要自己手动提交
sqlSession.commit();
8、添加日志框架(可选)
日志的级别:FATAL(致命)>ERROR(错误)>WARN(警告)>INFO(信息)>DEBUG(调试) 从左到右打印的内容越来越详细
1)添加依赖
log4j
2)配置log4j.xml
-
文件名必须为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> <!-- 执行sql输出debug日志--> <logger name="java.sql"> <level value="debug" /> </logger> <!-- 执行mybatis输出警告信息--> <logger name="org.apache.ibatis"> <level value="info" /> </logger> <root> <level value="debug" /> <appender-ref ref="STDOUT" /> </root> </log4j:configuration>
四、MyBatis的查询功能
1、在映射文件的SQL标签必须加入resultType属性
- 如果查询的是某个字段,则resultType设置为相应的属性,例如:resultType="java.lang.String"
- 如果查询的是一条或多条记录,则resultType设置为对应的POJO类,例如:resultType="com.cjy.pojo.User"
五、MyBatis核心配置文件
1、configuration标签下各个标签的顺序
properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?
2、environments标签
配置多个连接数据库的环境
-
default属性
default=“具体的某一个数据库环境的id”,设置默认的数据库环境。
-
environment标签
-
id属性
数据库环境的id
-
transaction标签的type属性
type="JDBC|MANAGED" ,设置事务管理的方式
- JDBC:表示当前环境中,执行SQL时,使用JDBC原生的事务管理方式。事务的提交和回滚需要手动设置
- MANAGED:被管理,例如Spring
-
dataSorce标签的type属性
type="POOLED|UNPOOLED|JNDI", 设置数据源的类型
- POOLED:表示使用数据库连接池缓存数据库连接
- UNPOOLED:表示不适用数据库连接池
- JNDI:表示使用上下文中的数据源
-
3、引入properties文件
-
在src/main/resources目录下建立properties文件
jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC jdbc.username=root jdbc.password=136011760 -
在configuration标签下加入properties标签
<properties resource="jdbc.properties"/> -
在dataSource下的property标签的value属性设置对应的值
<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>
4、typeAliases标签
写在configuration标签下,用于给全类名起别名,方便在映射文件中使用
-
使用typeAlias标签
用于给某一个全类名起别名,别名不区分大小写。
<typeAliases> <typeAlias type="com.cjy.pojo.User" alias="User"/> </typeAliases>- type=“某个类的全类名”
- alias="别名",别名不区分大小写。如果没有alise属性则默认属性为简单类名,也不区分大小写
-
使用package标签
以包为单位,给包中的所有类的全类名起别名,别名为简单类名,且不区分大小写。
<typeAliases> <package name="com.cjy.pojo"/> </typeAliases>
5、mappers标签
用于引入映射文件
-
使用mapper
引入单个映射文件
<mappers> <mapper resource="mappers/UserMapper.xml"/> </mappers> -
使用package
引入包中的所有映射文件
- 在src/main/resources目录下创建多级包需要以/分割(在java目录中创建多级包用.)
- 映射文件所在的全包名要和mapper接口所在的全包名一致
- 映射文件名字要和mapper接口名字一致
<mappers> <package name="com.cjy.mapper"/> </mappers>
5月2日
一、MyBatis获取参数值
1、使用#{}
相当于占位符?
<select id="checkLogin" resultType="User">
SELECT * FROM t_user WHERE uname=#{arg0} AND pawd=#{arg1}
</select>
-
当只传入一个参数时,#{}里面可以不填或者填任意字符
-
当传入多个参数时,且使用默认的键,#{}里面要根据Mapper接口的参数顺序填写
Mapper接口中的参数在执行过程中会被放入map中
- Mapper接口里的第一个参数是arg0或param0
- Mapper接口里的第二个参数是arg1或param1
-
当传入多个参数时,且使用自定义的map,#{}里面要根据Mapper接口的参数填写自定义的键
- Mapper接口中的方法,直接把map作为参数
User checkLogin3(Map<String, Object> map);-
在映射文件中
<select id="checkLogin3" resultType="User"> SELECT * FROM t_user WHERE uname=#{uname} AND pawd=#{pawd} </select> -
在使用时
HashMap<String, Object> hashMap = new HashMap<>(); hashMap.put("uname", "陈金雨"); hashMap.put("pawd", "136011760"); User user = mapper.checkLogin3(hashMap);
-
当传入多个参数时,直接在Mpper接口参数加入@Param注解
User checkLogin4(@Param("uname") String uname, @Param("pawd") String pawd); -
当传入的参数为对象时,可以直接在#{}里填属性
2、使用${}
相当于字符串拼接,因为是字符串拼接,所以要注意单引号的使用。
<select id="checkLogin2" resultType="User">
SELECT * FROM t_user WHERE uname='${arg0}' AND pawd='${arg1}'
</select>
-
当只传入一个参数时,${}里面可以不填或者填任意字符
-
当传入多个参数时,且使用默认的键,${}里面要根据Mapper接口的参数顺序填写
Mapper接口中的参数在执行过程中会被放入map中
- Mapper接口里的第一个参数是arg0或param0
- Mapper接口里的第二个参数是arg1或param1
-
当传入多个参数时,且使用自定义的map,${}里面要根据Mapper接口的参数填写自定义的键
-
Mapper接口中的方法,直接把map作为参数
User checkLogin3(Map<String, Object> map); -
在映射文件中
<select id="checkLogin3" resultType="User"> SELECT * FROM t_user WHERE uname='${uname}' AND pawd='${pawd}' </select> -
在使用时
HashMap<String, Object> hashMap = new HashMap<>(); hashMap.put("uname", "陈金雨"); hashMap.put("pawd", "136011760"); User user = mapper.checkLogin3(hashMap);
-
-
当传入多个参数时,直接在Mpper接口参数加入@Param注解
User checkLogin4(@Param("uname") String uname, @Param("pawd") String pawd); -
当传入的参数为对象时,可以直接在${}里填属性
二、MyBatis默认的类型别名
| Alias (别名) | Mapped Type |
|---|---|
| _byte | byte |
| _long | long |
| _short | short |
| _int | int |
| _integer | int |
| _double | double |
| _float | float |
| _boolean | boolean |
| string | String |
| byte | Byte |
| long | Long |
| short | Short |
| int | Integer |
| integer | Integer |
| double | Double |
| float | Float |
| boolean | Boolean |
| date | Date |
| decimal | BigDecimal |
| bigdecimal | BigDecimal |
| object | Object |
| map | Map |
| hashmap | HashMap |
| list | List |
| arraylist | ArrayList |
| collection | Collection |
| iterator | Iterator |
三、查询记录以map形式返回
1、查询一条记录
返回的map,以字段名为键。
-
mapper接口
Map<String, Object> selectOne(@Param("id") Integer id); -
映射文件
<select id="selectOne" resultType="map"> SELECT * FROM t_user WHERE id=#{id} </select>
2、查询多条记录
-
用List<Map<String, Object>>作为返回类型
返回的是以map为单位的集合,map中的键任然是字段名
-
加入参数@MapKey()
@MapKey()里面填字段名,且该字段的值不会重复出现,例如@MapKey("id")。
返回的map,以该字段的值为键,值就是每一条记录。
mapper接口
@MapKey("id") Map<String, Object> selectMul2();
四、模糊查询
1、直接使用字符串拼接
只能用${},不能用#{}
SELECT * FROM t_user WHERE uname LIKE '%${name}%'
2、使用concat
${}和#{}都能用
SELECT * FROM t_user WHERE uname LIKE CONCAT('%',#{name},'%')
五、批量删除
用IN
DELETE FROM t_user WHERE id IN (${ids})
这里只能用${},因为这里ids是以逗号为分割的有多个id的字符串如“1,2,3”,如果用#{}会自动加上单引号,
就会变成IN (‘1,2,3’)不能被解析。所以应该用${},就变成了IN (1,2,3)可以被解析
六、动态设置表名
只能用${},因为#{}会自动加上单引号
SELECT * FROM ${tableName}
七、插入数据时获取自动递增的主键的值
-
在SQL标签,设置属性useGeneratedKeys="true",设置keyProperty="传输到映射文件的对象的某个属性"
useGeneratedKeys:设置当前标签中的sql使用了自增的主键
keyProperty:将自增的主键的值赋值给传输到映射文件的对象的某个属性
<insert id="insertUser2" useGeneratedKeys="true" keyProperty="id"> INSERT INTO t_user values (null, #{uname}, #{pawd}) </insert> -
使用
public void insertUser2(){ SqlSession sqlSession = SqlSessionUtil.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user = new User(null, "cjj", "151151"); mapper.insertUser2(user); System.out.println(user.getId()); }
八、数据库字段名和POJO属性名不一致
1、给字段名起别名
SELECT id,dep_name depName FROM t_dep WHERE id=#{id}
2、在核心配置文件添加settings标签
写在configuration标签下
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
给带下划线的字段名起驼峰别名,全局有效。
3、使用resultMap
<resultMap id="depMap" type="Dep">
<id property="id" column="id"></id>
<result property="depName" column="dep_name"></result>
</resultMap>
<select id="getDep" resultMap="depMap">
SELECT * FROM t_dep
</select>
select标签中的resultMap属性中,填resultMap标签的id。
resultMap标签中,type属性填表所对应的POJO,id标签只能用与映射表的主键,result标签用于普通字段,property属性填POJO的属性,column填表的字段名。(使用resultMap需要把所有的POJO属性与表的字段映射起来,即使有些属性与字段名一致)
5月3日
一、处理多对一关系
在多的一方的POJO设置一的属性
public class Emp { private Integer empId; private String empName; private Integer empSex; private Dep dep;
1、通过级联赋值
SQL语句要连表查询,然后再通过resultMap给属性赋值
<resultMap id="EmpMap" type="Emp">
<id property="empId" column="emp_id"></id>
<result property="empName" column="emp_name"></result>
<result property="empSex" column="emp_sex"></result>
<result property="dep.depId" column="dep_id"></result>
<result property="dep.depName" column="dep_name"></result>
</resultMap>
<select id="selectEmpInfo" resultMap="EmpMap">
SELECT * FROM t_emp LEFT OUTER JOIN t_dep td on td.dep_id = t_emp.dep_id
</select>
2、通过association标签
association标签专门用来处理多对一映射关系,javaType里填写该属性的类型
<resultMap id="EmpMap" type="Emp">
<id property="empId" column="emp_id"></id>
<result property="empName" column="emp_name"></result>
<result property="empSex" column="emp_sex"></result>
<association property="dep" javaType="Dep">
<id property="depId" column="dep_id"></id>
<result property="depName" column="dep_name"></result>
</association>
</resultMap>
<select id="selectEmpInfo" resultMap="EmpMap">
SELECT * FROM t_emp LEFT OUTER JOIN t_dep td on td.dep_id = t_emp.dep_id
</select>
3、分步查询
<resultMap id="EmpMap2" type="Emp">
<id property="empId" column="emp_id"></id>
<result property="empName" column="emp_name"></result>
<result property="empSex" column="emp_sex"></result>
<association property="dep" column="dep_id" select="com.cjy.mapper.DepMapper.getDepNameById" ></association>
</resultMap>
<select id="selectEmpInfoByStep" resultMap="EmpMap2">
SELECT * FROM t_emp
</select>
column="dep_id"的dep_id会传入第二个SQL中,第二个SQL的查询结果再赋值给dep
分布查询的优点
-
可以实现延迟加载
延迟加载:第二步sql只会在需要的时候才调用
比如你只使用了查询结果中第一步SQL获得的属性,那么它只会执行第一步,第二步不会执行
默认是不会开启延迟加载的。需要在核心配置文件中配置。
开启lazyLoadingEnabled:延迟加载的全局开关,当开启是所有关联对象都会延迟加载
关闭aggressiveLazyLoading:当开启时任何方法调用都会加载该对象的所有属性。关闭则每个属性会按需加载。
<settings> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/> </settings>开启了延迟加载后,也可在association标签使用fetchType关闭延迟加载
<association property="dep" column="dep_id" select="com.cjy.mapper.DepMapper.getDepNameById" fetchType="eager"></association>
5月4日
一、处理一对多关系
在一的POJO设置多的集合
1、级联查询使用collection标签
<resultMap id="DepInfoMap" type="Dep">
<id property="depId" column="dep_id"></id>
<result property="depName" column="dep_name"></result>
<collection property="emps" ofType="Emp">
<id property="empId" column="emp_id"></id>
<result property="empName" column="emp_name"></result>
<result property="empSex" column="emp_sex"></result>
</collection>
</resultMap>
<select id="getDepInfoById" resultMap="DepInfoMap">
SELECT * FROM t_dep LEFT JOIN t_emp ON t_dep.dep_id=t_emp.dep_id WHERE t_dep.dep_id=#{depId}
</select>
collection标签的ofType属性中填集合中元素的类型
不能在emp中又查询dep
2、分布查询
<resultMap id="DepAndEmpByStep" type="Dep">
<id property="depId" column="dep_id"></id>
<result property="depName" column="dep_name"></result>
<collection property="emps" column="dep_id" select="com.cjy.mapper.EmpMapper.selectEmpByDepId"></collection>
</resultMap>
<select id="getDepAndEmpByStep" resultMap="DepAndEmpByStep">
SELECT * FROM t_dep WHERE dep_id=#{depId}
</select>
分布查询可以实现延迟加载
二、动态SQL
1、if标签
使用if标签必须搭配test属性
<select id="getEmpByCondition" resultMap="EmpByCondition">
SELECT * FROM t_emp WHERE 1=1
<if test="empName != null and empName != ''">
AND emp_name=#{empName}
</if>
<if test="empSex != null">
AND emp_sex=#{empSex}
</if>
<if test="dep.depId != null">
AND dep_id=#{dep.depId}
</if>
</select>
-
在if标签的test属性中,获取传入的参数不需要#{}或${},直接写参数名就行了。
-
在if标签的test属性中,并且用and,或者用or。
-
只有if条件成立才会把if标签中的sql语句拼接上去。
-
1=1是为了解决AND的拼接问题
2、where标签
SELECT * FROM t_emp
<where>
<if test="empName != null and empName != ''">
AND emp_name LIKE concat('%',#{empName},'%')
</if>
<if test="empSex != null">
AND emp_sex #{empSex}
</if>
<if test="dep.depId != null">
AND dep_id=#{dep.depId}
</if>
</where>
- 如果where标签的if有一个成立则在执行sql时自动生成一个WHERE
- where标签可以自动去掉内容前,多余的AND或者OR
- where标签不可以自动去掉内容后的,多余的AND或者OR
3、trim标签
SELECT * FROM t_emp
<trim prefix="WHERE" prefixOverrides="AND">
<if test="empName != null and empName != ''">
AND emp_name LIKE concat('%',#{empName},'%')
</if>
<if test="empSex != null">
AND emp_sex=#{empSex}
</if>
<if test="dep.depId != null">
AND dep_id=#{dep.depId}
</if>
</trim>
- 只要trim标签中有一个if成立,则prefix和suffix属性的值,会被加到trim标签整个SQL的首部或尾部
- prefixOverrides,去除sql语句前面的关键字或者字符
- suffixOverrides,去除sql语句后面的关键字或者字符
4、foreach标签实现批量操作
<insert id="insertEmp">
INSERT INTO t_emp VALUES
<foreach collection="emps" item="emp" separator=",">
(#{emp.empId},#{emp.empName},#{emp.empSex},#{emp.dep.depId})
</foreach>
</insert>
<delete id="deleteEmp">
DELETE FROM t_emp WHERE emp_id IN
<foreach collection="empIdS" item="empId" separator="," open="(" close=")">
#{empId}
</foreach>
</delete>
- collection属性:填写传入的集合或者数组对象,不用加#{}或${}
- item:代表每次循环取出的集合或者数组的元素
- separator:填写循环体之间的分隔符
- open:foreach标签循环的整个所有内容的开始符
- close:foreach标签循环的整个所有内容的结束符
5、sql标签
用于设置sql片段
-
设置sql片段
<sql id="empColumns">emp_id,emp_name,emp_sex,dep_id</sql> -
引用sql片段
SELECT <include refid="empColumns"></include> FROM t_emp
5月5日
一、MyBatis缓存
1、一级缓存
一级缓存缓存是默认开启的
一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问。
使一级缓存失效的四种情况
-
不同的SqlSession对应不用的一级缓存
-
同一个SqlSession但是查询条件不同
-
同一个SqlSession两次查询期间执行了任何一次增删改操作
-
同一个SqlSeesion两次查询期间手动清空了缓存
sqlSession.clearCache();
2、二级缓存
二级缓存是SqlSessionFactory级别,通过一个SqlSessionFactory创建的SqlSession查询的结果会被缓存。若再次执行相同的查询语句,结果就会从缓存中获取
1)二级缓存开启条件
-
在核心配置文件中,设置全局属性(setting标签中设置)cacheEnabled="true",默认就是为true,所以不需手动设置
-
在映射文件中设置标签
-
二级缓存必须在SqlSession关闭或提交之后才有效
sqlSession.commit() 或 sqlSession.close()
就算在生成sqlSession时开启了自动提交事务,也要使用二级缓存还需使用commit或close,因为自动提交事务只是提交事务,一级缓存中的数据不会写入二级缓存。commit或close才能将一级缓存数据写入二级缓存。
-
查询的数据所转换的实体类型必须实现序列化接口Serializable
2)二级缓存失效的情况
两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效
3)二级缓存的相关配置
在mapper配置文件中添加的cache标签可以设置一些属性
- eviction属性:缓存回收策略
- LRU(Least Recently Used)- 最近最少使用的:移除最长时间不被使用的对象
- FIFO(Fist In First Out) - 先进先出:按对象进入缓存的顺序来移除它们
- SOFT - 软引用:移除基于垃圾回收器状态和软引用规则的对象
- WEAK - 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
- 默认是LRU
- flushInterval属性:刷新缓存的间隔,单位毫秒
- 默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用增删改语句时刷新
- size属性:引用数目,正整数
- 代表缓存最多可以存储多少个对象,太大容易导致内存溢出。
- readOnly属性:只读,true/false
- true:只能读缓存,会给所有调用者返回缓存对象实例。因此这些对象不能被修改(返回的是缓存对象实例本身,如果被修改,下次读取的就是被修改后的值)。这提供了很重要的性能优势。
- false:能读能写缓存,会返回缓存对象的拷贝(通过序列化)。这回慢一些,但是安全。
- 默认false
4)缓存查询的顺序
- 先查询二级缓存
- 如果二级缓存没有命中,再查询一级缓存
- 如果一级缓存也没有命中,则查询数据库
- sqlSession提交(commit)或关闭(close)之后,一级缓存中的数据会写入二级缓存。
3、整个第三方缓存EHCache
第三方二级缓存,只有二级缓存才能用第三方的,一级缓存只能用默认的。
-
添加依赖
<!-- Mybatis EHCache整合包 --> <dependency> <groupId>org.mybatis.caches</groupId> <artifactId>mybatis-ehcache</artifactId> <version>1.2.1</version> </dependency> <!-- slf4j日志门面的一个具体实现 --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency> -
创建EHCache的配置文件ehcache.xml
文件名必须为ehcache.xml
<?xml version="1.0" encoding="utf-8" ?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <!-- 磁盘保存路径 --> <diskStore path="C:\Users\73577\Desktop"/> <defaultCache maxElementsInMemory="1000" maxElementsOnDisk="10000000" eternal="false" overflowToDisk="true" timeToIdleSeconds="120" timeToLiveSeconds="120" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> </defaultCache> </ehcache> -
在cache标签设置使用第三方二级缓存
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/> -
创建logback.xml,名字不可变
<?xml version="1.0" encoding="UTF-8"?> <configuration debug="true"> <!-- 指定日志输出的位置 --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <!-- 日志输出的格式 --> <!-- 按照顺序分别是:时间、日志级别、线程名称、打印日志的类、日志主体内容、换行 --> <pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n</pattern> </encoder> </appender> <!-- 设置全局日志级别。日志级别按顺序分别是:DEBUG、INFO、WARN、ERROR --> <!-- 指定任何一个日志级别都只打印当前级别和后面级别的日志。 --> <root level="DEBUG"> <!-- 指定打印日志的appender,这里通过“STDOUT”引用了前面配置的appender --> <appender-ref ref="STDOUT" /> </root> <!-- 根据特殊需求指定局部日志级别 --> <logger name="com.atguigu.crowd.mapper" level="DEBUG"/> </configuration>
二、MyBatis逆向工程
帮我们生成POJO,MAPPER,映射文件
-
在pom中加入插件
插件中所需的依赖要先下载好才能使用
不能写在标签里
<!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 --> <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.0</version> <!-- 插件的依赖 --> <dependencies> <!-- 逆向工程的核心依赖 --> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.4.0</version> </dependency> <!-- 数据库连接池 --> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.5.5</version> </dependency> <!-- MySQL驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.27</version> </dependency> </dependencies> </plugin> -
创建逆向工程的配置文件
文件名必须是:
generatorConfig.xml<?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> <!-- targetRuntime: 执行生成的逆向工程的版本 MyBatis3Simple: 生成基本的CRUD(清新简洁版) MyBatis3: 生成带条件的CRUD(奢华尊享版) --> <context id="DB2Tables" targetRuntime="MyBatis3Simple"> <!-- <properties resource="jdbc.properties"/>--> <!-- 数据库的连接信息 --> <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC" userId="root" password="136011760"> </jdbcConnection> <!-- javaBean的生成策略--> <javaModelGenerator targetPackage="com.cjy.mybatis.pojo" targetProject=".\src\main\java"> <property name="enableSubPackages" value="true" /> <property name="trimStrings" value="true" /> </javaModelGenerator> <!-- SQL映射文件的生成策略 --> <sqlMapGenerator targetPackage="com.cjy.mybatis.mapper" targetProject=".\src\main\resources"> <property name="enableSubPackages" value="true" /> </sqlMapGenerator> <!-- Mapper接口的生成策略 --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.cjy.mybatis.mapper" targetProject=".\src\main\java"> <property name="enableSubPackages" value="true" /> </javaClientGenerator> <!-- 逆向分析的表 --> <!-- tableName设置为*号,可以对应所有表,此时不写domainObjectName --> <!-- domainObjectName属性指定生成出来的实体类的类名 --> <table tableName="t_emp" domainObjectName="Emp"/> <table tableName="t_dep" domainObjectName="Dep"/> </context> </generatorConfiguration>- 数据库的连接信息不能引入外部的properties
- 如果包或者目录不存在会帮我们自动创建
-
点击mybatis-generator自动帮我们生成POJP,MAPPER,映射文件
重新生成时,最好把以前生成的文件删除了,再重新生成
-
使用
public void test(){ SqlSession sqlSession = SqlSessionUtil.getSqlSession(); EmpMapper mapper = sqlSession.getMapper(EmpMapper.class); EmpExample empExample = new EmpExample(); empExample.createCriteria().andEmpNameLike("%王%"); empExample.or().andEmpNameEqualTo("李四"); List<Emp> emps = mapper.selectByExample(empExample); for ( Emp emp : emps ){ System.out.println(emp); } } }- selectByExample:按条件查询,需要传入一个example对象或者null;如果传入一个null,则表示没有条件,也就是查询所有数据
- example.createCriteria().xxx:创建条件对象,通过andXXX方法为SQL添加查询添加,每个条件之间是and关系
- example.or().xxx:将之前添加的条件通过or拼接其他条件
updateByPrimaryKey:通过主键进行数据修改,如果某一个值为null,也会将对应的字段改为nullupdateByPrimaryKeySelective():通过主键进行选择性数据修改,如果某个值为null,则不修改这个字段
三、分页插件
1、配置分页插件
-
添加依赖
<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.3.0</version> </dependency> -
在MyBatis核心配置文件中配置插件
<plugins> <!--设置分页插件--> <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin> </plugins>
2、使用分页插件
-
在查询功能之前使用
PageHelper.startPage(int pageNum, int pageSize)开启分页功能- pageNum:当前页的页码
- pageSize:每页显示的条数
-
获取与当前页相关的数据
- 在查询获取list集合之后,使用
PageInfo<T> pageInfo = new PageInfo<>(List<T> list, intnavigatePages)获取分页相关数据- list:分页之后的数据,查询结果得到的list
- navigatePages:导航分页的页码数
- 其中泛型填查询结果list中元素的属性
- 在查询获取list集合之后,使用
-
常用数据
-
pageNum:当前页的页码
-
pageSize:每页显示的条数
-
size:当前页显示的真实条数
-
total:总记录数
-
pages:总页数
-
prePage:上一页的页码
-
nextPage:下一页的页码
-
isFirstPage/isLastPage:是否为第一页/最后一页
-
hasPreviousPage/hasNextPage:是否存在上一页/下一页
-
navigatePages:导航分页的页码数
-
navigatepageNums:导航分页的页码,[1,2,3,4,5]
-