1、MyBatis 是优秀的持久层框架
2、MyBatis 使用 XML 将 SQL 与程序解耦,便于维护
3、MyBatis 学习简单,执行高效,是 JDBC 的延伸
中文参考网址:https://mybatis.net.cn/
一、mybatis-config.xml
二、初始化工具类 MyBatisUtils
/**
* MyBatis工具类,创建全局唯一的 SqlSessionFactory 对象
*/
public class MyBatisUtils {
// 利用 static(静态) 属于类不属于对象,且全局唯一
private static SqlSessionFactory sqlSessionFactory = null;
// static块用于初始化静态变量
// 利用静态块在初始化类时实例化 sqlSessionFactory 对象
static {
Reader reader = null;
try {
reader = Resources.getResourceAsReader("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
} catch (IOException e) {
e.printStackTrace();
// 初始化错误时,通过抛出 ExceptionInInitializerError 通知调用者
throw new ExceptionInInitializerError(e);
}
}
/**
* 创建一个新的 SqlSession 对象
* @return SqlSession对象
*/
public static SqlSession openSession() {
return sqlSessionFactory.openSession();
}
/**
* 释放一个有效的 SqlSession 对象
* @param session 准备释放的 SqlSession 对象
*/
public static void closeSession(SqlSession session) {
if (session != null) {
session.close();
}
}
}
三、MyBatis 数据操作
- 1、创建实体类(Entity)
- 2、创建Mapper XML
- 3、编写
- 4、开启驼峰命名映射
- 5、新增
- 6、SqlSession执行select语句
(一)数据查询
1、无参数查询
2、单参数查询
// 测试用例
@Test
public void testSelectOne() throws Exception {
SqlSession sqlSession = null;
try {
sqlSession = MyBatisUtils.openSession();
Goods goods = sqlSession.selectOne("goods.selectById", 1602);
System.out.println(goods.getTitle());
} catch (Exception e) {
throw e;
} finally {
MyBatisUtils.closeSession(sqlSession);
}
}
3、多参数查询
// 测试用例
@Test
public void testSelectByPriceRange() throws Exception {
SqlSession sqlSession = null;
try {
sqlSession = MyBatisUtils.openSession();
HashMap map = new HashMap<>();
map.put("min", 100);
map.put("max", 500);
map.put("limit", 10);
List list = sqlSession.selectList("goods.selectByPriceRange", map);
for (Goods g : list) {
System.out.println(g.getTitle() + ":" + g.getCurrentPrice());
}
} catch (Exception e) {
throw e;
} finally {
MyBatisUtils.closeSession(sqlSession);
}
}
4、获取多表关联查询结果
// 测试用例
@Test
public void testSelectGoodsMap() throws Exception {
SqlSession sqlSession = null;
try {
sqlSession = MyBatisUtils.openSession();
List
5、 ResultMap结果映射
// 测试用例
@Test
public void testSelectGoddsDTO() throws Exception {
SqlSession sqlSession = null;
try {
sqlSession = MyBatisUtils.openSession();
List list = sqlSession.selectList("goods.selectGoodsDTO");
for (GoodsDTO g : list) {
System.out.println(g.getGoods().getTitle());
}
} catch (Exception e) {
throw e;
} finally {
MyBatisUtils.closeSession(sqlSession);
}
}
6、 动态SQL查询
// 测试用例
@Test
public void testDynamicSQL() {
SqlSession sqlSession = null;
try {
sqlSession = MyBatisUtils.openSession();
Map map = new HashMap<>();
map.put("category_id", 44);
map.put("currentPrice", 500);
List list = sqlSession.selectList("goods.dynamicSQL", map);
for (Goods g : list) {
System.out.println(g.getTitle());
}
} catch (Exception e) {
if (sqlSession != null) {
sqlSession.rollback();
}
throw e;
} finally {
MyBatisUtils.closeSession(sqlSession);
}
}
7、OneToMany对象关联查询
// 测试用例
@Test
public void testOneToMany() throws Exception {
SqlSession sqlSession = null;
try {
sqlSession = MyBatisUtils.openSession();
List list = sqlSession.selectList("goods.selectOneToMany");
for (Goods g : list) {
System.out.println(g.getTitle() + ":" + g.getGoodsDetails().size());
}
} catch (Exception e) {
throw e;
} finally {
MyBatisUtils.closeSession(sqlSession);
}
}
8、ManyToOne对象关联查询
// 测试用例
@Test
public void testManyToOne() throws Exception {
SqlSession sqlSession = null;
try {
sqlSession = MyBatisUtils.openSession();
List list = sqlSession.selectList("goodsDetail.selectManyToOne");
for (GoodsDetail g : list) {
System.out.println(g.getGdPicUrl() + ":" + g.getGoods().getTitle());
}
} catch (Exception e) {
throw e;
} finally {
MyBatisUtils.closeSession(sqlSession);
}
}
(二)数据插入
insert into t_goods(title, sub_title, original_cost, current_price, discount, is_free_delivery, category_id)
values (#{title}, #{subTitle}, #{originalCost}, #{currentPrice}, #{discount}, #{isFreeDelivery}, #{categoryId})
select last_insert_id();
insert into t_goods(title, sub_title, original_cost, current_price, discount, is_free_delivery, category_id)
values (#{title}, #{subTitle}, #{originalCost}, #{currentPrice}, #{discount}, #{isFreeDelivery}, #{categoryId})
// 测试用例
@Test
public void testInsert() throws Exception {
SqlSession sqlSession = null;
try {
sqlSession = MyBatisUtils.openSession();
Goods goods = new Goods();
goods.setTitle("测试标题");
goods.setSubTitle("测试副标题");
goods.setOriginalCost(12.f);
goods.setCurrentPrice(1231.f);
goods.setDiscount(0.1f);
goods.setIsFreeDelivery(1);
goods.setCategoryId(1);
int num = sqlSession.insert("goods.insert", goods);
sqlSession.commit();
System.out.println(goods.getGoodsId());
} catch (Exception e) {
if (sqlSession != null) {
sqlSession.rollback();
}
throw e;
} finally {
MyBatisUtils.closeSession(sqlSession);
}
}
(三)数据更新
update t_goods
set
title=#{title},
sub_title=#{subTitle},
original_cost=#{originalCost},
current_price=#{currentPrice},
discount=#{discount},
is_free_delivery=#{isFreeDelivery},
category_id=#{categoryId}
where goods_id=#{goodsId};
// 测试用例
@Test
public void testUpdate() throws Exception {
SqlSession sqlSession = null;
try {
sqlSession = MyBatisUtils.openSession();
Goods goods = sqlSession.selectOne("goods.selectById", 740);
goods.setTitle("更新测试商品标题");
int num = sqlSession.update("goods.update", goods);
sqlSession.commit();
} catch (Exception e) {
if (sqlSession != null) {
sqlSession.rollback();
}
throw e;
} finally {
MyBatisUtils.closeSession(sqlSession);
}
}
(四)数据删除
delete from t_goods where goods_id=#{value}
// 测试用例
@Test
public void testDelete() throws Exception {
SqlSession sqlSession = null;
try {
sqlSession = MyBatisUtils.openSession();
int num = sqlSession.delete("goods.delete", 740);
sqlSession.commit();
} catch (Exception e) {
if (sqlSession != null) {
sqlSession.rollback();
}
throw e;
} finally {
MyBatisUtils.closeSession(sqlSession);
}
}
四、MyBatis 预防SQL注入攻击
SQL注入
是指攻击者利用SQL漏洞
,绕过系统约束,越权获取数据的攻击方式
MyBatis两种传值方式
-
${}
文本替换,未经任何处理对SQL
文本替换 -
#{}
预编译传值,使用预编译传值可以预防SQL注入
五、MyBatis工作流程
六、MyBatis日志管理
- 日志文件是用于记录系统操作事件的记录文件或文件集合
- 日志保存历史数据,是诊断问题以及理解系统活动的重要依据
logback官网:https://logback.qos.ch/
1、在 resources
目录下新建logback.xml
文件(文件名为固定写法),文件内容如下
%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
七、MyBatis二级缓存
1、一级缓存默认开启,缓存范围 SqlSession 会话
2、二级缓存手动开启,属于范围 Mapper Namespace
1、二级缓存运行规则
- 1、二级缓存后默认所有查询操作均使用缓存
- 2、写操作
commit
提交时对该namespace
缓存强制清空 - 3、配置
userCache=false
可以不用缓存 - 4、配置
flushCache=true
代表强制清空缓存
@Test
public void testLv1Cache() throws Exception {
// 一级缓存默认开启,缓存范围 SqlSession 会话
SqlSession sqlSession = null;
try {
sqlSession = MyBatisUtils.openSession();
Goods goods = sqlSession.selectOne("goods.selectById", 1603);
Goods goods1 = sqlSession.selectOne("goods.selectById", 1603);
System.out.println(goods.hashCode() + ":" + goods1.hashCode());
} catch (Exception e) {
throw e;
} finally {
MyBatisUtils.closeSession(sqlSession);
}
try {
sqlSession = MyBatisUtils.openSession();
Goods goods = sqlSession.selectOne("goods.selectById", 1603);
// 写操作 commit 提交时对该 namespace 缓存强制清空
sqlSession.commit();
Goods goods1 = sqlSession.selectOne("goods.selectById", 1603);
System.out.println(goods.hashCode() + ":" + goods1.hashCode());
} catch (Exception e) {
throw e;
} finally {
MyBatisUtils.closeSession(sqlSession);
}
}
@Test
public void testLv2Cache() throws Exception {
SqlSession sqlSession = null;
try {
sqlSession = MyBatisUtils.openSession();
Goods goods = sqlSession.selectOne("goods.selectById", 1603);
System.out.println(goods.hashCode());
} catch (Exception e) {
throw e;
} finally {
MyBatisUtils.closeSession(sqlSession);
}
try {
sqlSession = MyBatisUtils.openSession();
Goods goods = sqlSession.selectOne("goods.selectById", 1603);
System.out.println(goods.hashCode());
} catch (Exception e) {
throw e;
} finally {
MyBatisUtils.closeSession(sqlSession);
}
}
八、PageHelper分页插件
官网地址:https://pagehelper.github.io/
1、使用流程
-
1、maven
引入PageHelper
与jssqlparser
com.github.pagehelper
pagehelper
5.3.1
com.github.jsqlparser
jsqlparser
4.4
-
2、mybatis-config.xml
增加Plugin
配置
-
3、
代码中使用PageHelper.startPage()
自动分页
@Test
public void testSelectPage() throws Exception {
SqlSession sqlSession = null;
try {
sqlSession = MyBatisUtils.openSession();
/*startPage方法会自动将下一次查询进行分页*/
PageHelper.startPage(2, 10);
Page page = (Page)sqlSession.selectList("goods.selectPage");
System.out.println("总页数:" + page.getPages());
System.out.println("总记录数:" + page.getTotal());
System.out.println("开始行号:" + page.getStartRow());
System.out.println("结束行号:" + page.getEndRow());
System.out.println("当前页码:" + page.getPageNum());
List list = page.getResult(); // 当前页数据
for (Goods g : list) {
System.out.println(g.getTitle());
}
System.out.println("");
} catch (Exception e) {
throw e;
} finally {
MyBatisUtils.closeSession(sqlSession);
}
}
九、MyBatis批处理
1、批量增加
insert into t_goods(title, sub_title, original_cost, current_price, discount, is_free_delivery, category_id)
values
(#{item.title}, #{item.subTitle}, #{item.originalCost}, #{item.currentPrice}, #{item.discount}, #{item.isFreeDelivery}, #{item.categoryId})
@Test
public void tesBatchInsert() throws Exception {
SqlSession sqlSession = null;
try {
long st = new Date().getTime();
sqlSession = MyBatisUtils.openSession();
List list = new ArrayList();
for (int i = 0; i < 10000; i++) {
Goods goods = new Goods();
goods.setTitle("测试商品哈哈");
goods.setSubTitle("测试子标题");
goods.setOriginalCost(200f);
goods.setCurrentPrice(100f);
goods.setDiscount(0.5f);
goods.setIsFreeDelivery(1);
goods.setCategoryId(43);
list.add(goods);
}
sqlSession.insert("goods.batchInsert", list);
sqlSession.commit();
long et = new Date().getTime();
System.out.println("执行时间:" + (et - st) + "毫秒");
} catch (Exception e) {
throw e;
} finally {
MyBatisUtils.closeSession(sqlSession);
}
}
2、批量删除
delete from t_goods where goods_id in
#{item}
@Test
public void testBatchDelete() throws Exception {
SqlSession sqlSession = null;
try {
long st = new Date().getTime();
sqlSession = MyBatisUtils.openSession();
List list = new ArrayList();
for (int i = 2674; i < 10750; i++) {
list.add(i);
}
sqlSession.delete("goods.batchDelete", list);
sqlSession.commit();
long et = new Date().getTime();
System.out.println("执行时间:" + (et - st) + "毫秒");
} catch (Exception e) {
throw e;
} finally {
MyBatisUtils.closeSession(sqlSession);
}
}