mybatis MyBatis-Generator Interceptor PageHelper
参考资料
一、MyBatis基础
1.1 ORM介绍
- ORM: 对象关系映射(英语:Object Relational Mapping ), 在关系型数据库和业务实体对象之间作一个映射
Hibernate的轻量级 ORM 模型逐步确立了在 JAVA ORM 架构中领导地位
linqToSql:微软为SQLSERVER数据库提供的,是.NET FRAMEWORK 3.5 版的一个组件,提供了用于将关系数据作为对象管理的运行时基础结构 - ORM框架: 就是用于实现ORM技术的程序, 当前ORM框架主要有四种:
- Hibernate(Nhibernate)
- iBATIS
- mybatis
- EclipseLink
1.2 mybatis配置、使用
核心概念:
- mybatis-config.xml:配置数据源、事务等核心配置
- SqlSessionFactoryBuilder:主要作用就是读mybatis-config.xml中配置,创建一个SqlSessionFactory
- SqlSessionFactory:sql会话工厂,用于创建SqlSession
- SqlSession:定义了数据库的增删改查以及事务管理的常用方法,还提供了查找Mapper接口的有关方法,每次收到的 HTTP 请求,就可以打开一个 SqlSession,返回一个响应,就关闭它。
- Mapper:由SqlSession创建, 用于将Java对象和实际的SQL语句映射
使用示例:
- SpringBoot整合mybatis快速入门
- Spring Boot(六):如何优雅的使用 Mybatis
- Spring Boot 2 (十一):如何优雅的使用 MyBatis 之 MyBatis-Plus
- Spring Boot(七):Mybatis 多数据源最简解决方案
- springboot整合Mybatis-plus
- SpringBoot 整合 JPA
- Springboot整合MybatisPlus(超详细)完整教程
- springboot整合mybatis-plus,以及mybatis-plus入门使用
问题总结:
- logback中把mapper包的日志改为debug,可以看到查询sql
- ${}区别#{}:
- $方式无法防止Sql注入,#{}方式能够很大程度防止sql注入
- 动态传入列名时,是非预编译的话,最好使用${}而不是#{}
- 传参方式
1.一个参数直接传
2.多参数,占位符顺序遍历参数:
Public User selectUser(String name,String password);
select * from t_user where name = #{0} and password=#{1}
3.Map传多参数
Public User selectUser(Map paramMap);
select * from t_user where name = #{paramMap.name} and password = #{paramMap.password}
4.@param传多参数
Public User selectUser(@param(“name”)String name, @param(“password”)String password);
select * from t_user where name = #{name} and password = #{password}
5.pojo传多参数
public List<User> getUserByParam(User user);
<select id="getUserByParam" resultType="com.wds.demo.entity.User" parameterType="com.wds.demo.entity.User" >
select * from t_user t
<where>
<if test="{name} != null">
t.name like CONCAT('%',#{name},'%')
</if>
<if test="{password} != null">
and t.password like CONCAT('%',#{password},'%')
</if>
</where>
</select>
二、MyBatis-Generator
SpringBoot整合Mybatis(三)集成Mybatis Generator进行代码自动生成
三、Interceptor拦截器
mybatis Interceptor拦截器实现机制,使用的是JDK的InvocationHandler.
会在程序执行指定sql前后,对请求参数和返回值进行处理的插件.
MyBatis 允许使用插件来拦截的方法调用包括:
// 执行器
Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
// 请求参数处理
ParameterHandler (getParameterObject, setParameters)
// 返回结果集处理
ResultSetHandler (handleResultSets, handleOutputParameters)
// SQL语句构建
StatementHandler (prepare, parameterize, batch, update, query)
如果需要实现自定义的拦截器,需要实现 org.apache.ibatis.plugin.Interceptor 接口,该接口有三个方法:
- Object intercept(Invocation invocation) throws Throwable;
- Object plugin(Object target);
- void setProperties(Properties properties);
应用场景示例
- mybatis拦截器实现数据库字段加密解密: 需要在保存数据前和查询返回结果后对相应数据进行加解密处理,需要针对 Parameter 和 ResultSet这两种类型进行处理
- 统一拦截update语句,更新修改时间update_time字段
@Slf4j
@Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
public class CommonFieldInterceptor implements Interceptor {
// 公共字段值设置
public void setCommonFieldValues(Object bean) {
if(bean == null) {
return;
}
try {
// 创建时间,在为空时写入当前时间
if (BeanUtil.containsProp(bean, "updateTime") && BeanUtil.getPropValue(bean, "updateTime") == null) {
BeanUtil.setPropValue(bean, "updateTime", new Date());
}
// 修改时间,始终写入当前时间
if (BeanUtil.containsProp(bean, "updateTime")) {
BeanUtil.setPropValue(bean, "updateTime", new Date());
}
} catch (Exception e) {
logger.error("设置{}对象公共字段时出错!", new Object[] { bean.getClass().getName() }, e);
}
}
@Override
public Object intercept(Invocation invocation) throws Throwable {
// MappedStatement mappedStatement = (MappedStatement)
// invocation.getArgs()[0];
// String sqlId = mappedStatement.getId();
// String namespace = sqlId.substring(0, sqlId.lastIndexOf('.'));
// Executor exe = (Executor) invocation.getTarget();
String methodName = invocation.getMethod().getName();
if (methodName.equals("update")) {
// 对pojo对象设置公共字段
Object bean = invocation.getArgs()[1];
setCommonFieldValues(bean);
}
return invocation.proceed();
}
@Override
public Object plugin(Object target) { //Object target 被代理的目标对象
return Plugin.wrap(target, this); //wrap把拦截器对象封装成Plugin代理对象.
}
@Override
public void setProperties(Properties properties) {
}
}
四、分页插件PageHelper
无需你自己去封装以及关心sql分页等问题,使用很方便,前端取数据也很方便
- PageHelper
- 1) 对国产数据库支持不足
- 2) 扩展不方便
- 3) 配置复杂
- 4) 性能底下 (不要喷我, 因为它不是用的占位符?,发挥不了PrepareSatement的优势)
- 5) 只支持MyBatis
- Sqlhelper
- 支持MyBatis, JFinal,Ebean,Mango
- 支持 90+ 种数据库, 支持列表参见 here. 包含了几乎所有的国产数据库:
- 同一个应用中支持多种数据库
- 不需要配置dialect,可以自动的获取。
- 比 Mybatis-PageHelper性能更高, 原因是limit , offset等参数使用 PrepareStatement placeholder ‘?’ , Mybatis是硬编码拼接的
- 通过Java SPI的方式支持了插件
- 支持 spring boot 1.x , 2.x
- 支持 mybatis 3.x
- 支持 JDK6+
PageHelper集成使用
五、使用总结
一对多:MyBatis中的collection两种使用方法
MyBatis实现一对多 多层Collection集合嵌套关系实现
//示例:三表级联,两层嵌套
<resultMap id="PerquisiteResultMap" type="com.wds.entity.model.Organization">
<id column="id" property="id" jdbcType="INTEGER"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<collection property="perquisites" ofType="com.wds.entity.model.Perquisite">
<id column="per_id" jdbcType="INTEGER" property="id"/>
<result column="org_id" jdbcType="INTEGER" property="orgId"/>
<result column="per_name" jdbcType="VARCHAR" property="name"/>
<collection property="perquisiteSpans" ofType="com.wds.entity.model.PerquisiteSpan">
<id column="span_id" jdbcType="INTEGER" property="id"/>
<result column="perquisite_id" jdbcType="INTEGER" property="perquisiteId"/>
</collection>
</collection>
</resultMap>
<select id="selectOrgWithPerquisite" resultMap="PerquisiteResultMap">
select org.id as id, org.name as name,
per.id as per_id, per.name as per_name,
span.id span_id, span.perquisite_id
from organization org
left join perquisite per on per.org_id = org.id
left join perquisite_span span on span.perquisite_id = per.id
where org.delete_tate = 'A' and per.delete_state = 'A' and span.delete_state = 'A'
</select>
Post Directory
扫码关注公众号:暂无公众号
发送 290992
即可立即永久解锁本站全部文章