5.2.1 MyBatis简介和优势
代码:
dbutils:
测试代码:
5.2.2 手写MyBatis
JAR包引入:
代码:
5.2.3 MyBatis核心源码分析
mybatis使用的设计模式:
5.2.4 高级应用-分页插件
1.写一个mybatis的拦截器用来拦截sql请求
2.设置拦截类型
3.重写plugin setProperties intercept 方法
4.把pagesql赋给元BoundSql
import com.study.mybatis.utils.PageInfo;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Map;
import java.util.Properties;
/**
* @ClassName AllenPagePlugin
* @Description TODO
* @Author 网易云课堂微专业-java高级开发工程师
* @Date 2020/4/1 21:03
* @Version 1.0
*/
@Intercepts(@Signature(
type = StatementHandler.class,
method = "prepare",
args = {Connection.class, Integer.class}
))
public class AllenPagePlugin implements Interceptor {
// 插件的核心业务
@Override
public Object intercept(Invocation invocation) throws Throwable {
/**
* 1、拿到原始的sql语句
* 2、修改原始sql,增加分页 select * from t_user limit 0,3
* 3、执行jdbc去查询总数
*/
// 从invocation拿到我们StatementHandler对象
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
// 拿到原始的sql语句
BoundSql boundSql = statementHandler.getBoundSql();
String sql = boundSql.getSql();
System.out.println("原始sql:" + sql);
// 分页参数
Object paramObj = boundSql.getParameterObject();
// statementHandler 转成 metaObject
MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
// spring context.getBean("userBean")
MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
// 获取mapper接口中的方法名称 selectUserByPage
String mapperMethodName = mappedStatement.getId();
if (mapperMethodName.matches(".*ByPage$")) {
Map<String, Object> params = (Map<String, Object>) paramObj;
PageInfo pageInfo = (PageInfo) params.get("page"); // map.put("page", PageInfo);
// select * from user;
String countSql = "select count(0) from (" + sql + ") a";
System.out.println("查询总数的sql : " + countSql);
// 执行jdbc操作
Connection connection = (Connection) invocation.getArgs()[0];
PreparedStatement countStatement = connection.prepareStatement(countSql);
ParameterHandler parameterHandler = (ParameterHandler) metaObject.getValue("delegate.parameterHandler");
parameterHandler.setParameters(countStatement);
ResultSet rs = countStatement.executeQuery();
if (rs.next()) {
pageInfo.setTotalNumber(rs.getInt(1));
}
rs.close();
countStatement.close();
// 改造sql limit
String pageSql = this.generaterPageSql(sql, pageInfo);
System.out.println("分页sql:" + pageSql);
metaObject.setValue("delegate.boundSql.sql", pageSql);
}
// 把执行流程交给mybatis
return invocation.proceed();
}
// 把自定义的插件加入到mybatis中去执行
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
// 设置属性
@Override
public void setProperties(Properties properties) {
String type = properties.getProperty("type");
}
// 根据原始sql 生成 带limit sql
public String generaterPageSql(String sql, PageInfo pageInfo) {
StringBuffer sb = new StringBuffer();
sb.append(sql);
if(type.equal("mysql")){
sb.append(" limit " + pageInfo.getStartIndex() + " , " + pageInfo.getTotalSelect());
}else if(type.equal("oracle")){
sb.append("oracle 写法");
}else{
throw new Exception("分页时,未获取到数据库类型!");
}
return sb.toString();
}
}
5.最后在配置文件中添加拦截器配置
5.2.5 高级应用-读写分离插件
2个数据源
5.2.6 高级应用-缓存
mybatis一级缓存和二级缓存实现都是用的hashMap.
作用域不一样,一级缓存作用域sqlSession,二级缓存作用域是namespace
开二级缓存,分2步
1.打开开关
2.xxxMapper.xml打开开关
二级缓存 + Redis
方法一:
5.2.7 高级应用-自定义类型处理器
不是全集
1.自定义TypeHandler
import com.study.mybatis.utils.EncryptUtil;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 自定义敏感字段加解密处理器
*
* @Author 网易云课堂微专业-java高级开发工程师【allen老师】
* @Version 1.0
*/
public class AllenTypeHandle implements TypeHandler {
//private static String KEY = "123456";
/**
* 通过preparedStatement对象设置参数,将T类型的数据存入数据库。
*
* @param ps
* @param i
* @param parameter
* @param jdbcType
* @throws SQLException
*/
@Override
public void setParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
try {
String encrypt = EncryptUtil.encode(((String) parameter).getBytes());
ps.setString(i, encrypt);
} catch (Exception e) {
e.printStackTrace();
}
}
// 通过列名或者下标来获取结果数据,也可以通过CallableStatement获取数据。
@Override
public Object getResult(ResultSet rs, String columnName) throws SQLException {
String result = rs.getString(columnName);
if (result != null && result != "") {
try {
return EncryptUtil.decode(result.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
}
return result;
}
@Override
public Object getResult(ResultSet rs, int columnIndex) throws SQLException {
String result = rs.getString(columnIndex);
if (result != null && result != "") {
try {
return EncryptUtil.decode(result.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
}
return result;
}
@Override
public Object getResult(CallableStatement cs, int columnIndex) throws SQLException {
String result = cs.getString(columnIndex);
if (result != null && result != "") {
try {
return EncryptUtil.decode(result.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
}
return result;
}
}
2.配置注册自定义处理器
3.使用自定义处理器
5.2.8-面试题分析
建议:
mybatis默认支持: