- 浏览: 534341 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
gaolegao2008:
如果报 is_volum 列名找不到之类的,我是从新部署了一个 ...
spring quartz 定时器报错 -
gaolegao2008:
部署到linux上时,还有一种情况就是mysql数据库区分大小 ...
spring quartz 定时器报错 -
qq123zhz:
yahier 写道 对我有帮助,但我看的一个demo程序,却没 ...
spring quartz 定时器报错 -
qq123zhz:
这个要在eclipse的插件环境下运行的,你不懂eclipse ...
GEF 自动布局 -
qq123zhz:
这个很久了,不记得啥时候写的了
json转为Map
页面输入:男,数据库保存male,女,数据库保存为female。
使用interceptor,typeHandler
package cn.dcr.mybatis.util; import java.util.Properties; import org.apache.ibatis.executor.Executor; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.plugin.Intercepts; import org.apache.ibatis.plugin.Invocation; import org.apache.ibatis.plugin.Plugin; import org.apache.ibatis.plugin.Signature; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.RowBounds; import com.test.pojos.User; @Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }), @Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class }) }) public class MyInterceptor implements Interceptor { private static final String R_FEMALE = "女"; private static final String R_MALE = "男"; private static final String FEMALE = "female"; private static final String MALE = "male"; private Properties properties; /* * (non-Javadoc) * * @see * org.apache.ibatis.plugin.Interceptor#intercept(org.apache.ibatis.plugin * .Invocation) */ public Object intercept(Invocation invocation) throws Throwable { MappedStatement mappedStatement = (MappedStatement) invocation .getArgs()[0]; String sqlId = mappedStatement.getId(); String namespace = sqlId.substring(0, sqlId.indexOf('.')); Executor exe = (Executor) invocation.getTarget(); String methodName = invocation.getMethod().getName(); if (methodName.equals("query")) { Object parameter = invocation.getArgs()[1]; RowBounds rowBounds = (RowBounds) invocation.getArgs()[2]; } else if(methodName.equals("update")){ Object parameter = invocation.getArgs()[1]; if(parameter instanceof User) ((User)parameter).setGender(saveValueToDb(((User)parameter).getGender())); } return invocation.proceed(); } /* * (non-Javadoc) * * @see org.apache.ibatis.plugin.Interceptor#plugin(java.lang.Object) */ public Object plugin(Object target) { return Plugin.wrap(target, this); } /* * (non-Javadoc) * * @see * org.apache.ibatis.plugin.Interceptor#setProperties(java.util.Properties) */ public void setProperties(Properties properties) { this.properties = properties; } /**插入数据库 * @param value * @return */ private String saveValueToDb(String value) { if (value.equals(R_FEMALE)) { return FEMALE; } else if (value.equals(R_MALE)) { return MALE; } else { throw new IllegalArgumentException("数据库异常!" + value); } } }
@Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }), @Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class }) })
mybatis 拦截器好像只能使用注解,而且对于接口Executor,method只定义了update,query,flushStatements,commit,rollback,createCacheKey,isCached,clearLocalCache,deferLoad,getTransaction,close,isClosed这几个方法,没有delete和insert方法。
具体详见:
package org.apache.ibatis.executor; import org.apache.ibatis.cache.CacheKey; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.RowBounds; import org.apache.ibatis.transaction.Transaction; import java.sql.SQLException; import java.util.List; public interface Executor { ResultHandler NO_RESULT_HANDLER = null; int update(MappedStatement ms, Object parameter) throws SQLException; List query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException; List<BatchResult> flushStatements() throws SQLException; void commit(boolean required) throws SQLException; void rollback(boolean required) throws SQLException; CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds); boolean isCached(MappedStatement ms, CacheKey key); void clearLocalCache(); void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key); Transaction getTransaction(); void close(boolean forceRollback); boolean isClosed(); }
当我疑惑为什么mybatis没有在insert和delete的时候拦截呢?
看到了mybatis googleCode上的issue16。
Issue 16: | Update interceptor (plugin) fires for inserts |
Reporter: Eli Kizhnerman The iBatis plugin does not seem to be resolving the target methods to intercept properly. An interceptor that is defined to intercept only updates is also executed on inserts. I have the following definition: @Intercepts({@Signature( type=Executor.class, method="update", args={MappedStatement.class,Object.class})}) public class UpdateInterceptor implements Interceptor { ... } In Plugin.invoke you have the following code: Set<Method> methods = signatureMap.get(method.getDeclaringClass()); if (methods != null && methods.contains(method)) { return interceptor.intercept(new Invocation(target, method, args)); } DefaultSqlSession.insert internally calls an update method: public int insert(String statement, Object parameter) { return update(statement, parameter); } I suspect that the Method that is being passed to plugin.invoke is actually the update method and therefore the interceptor is executed.
原来在DefaultSqlSession的insert,delete方法也是调用了update方法。
public int insert(String statement, Object parameter) { return update(statement, parameter); }
public int delete(String statement, Object parameter) { return update(statement, wrapCollection(parameter)); }
mybatis太不厚道了,它的文档也没有具体的说明。
有人提出这是个bug,不过mybatis没有承认。
Clinton Begin added a comment - 10/Dec/09 03:58 PM Executor only has update and query methods. Thus inserts and deletes are also considered updates. It sounds like to do what you want, we need another interception point, at the session level. You can do so right now with a proxy class between the SqlSession interface and the default implementation. [ Show » ] Clinton Begin added a comment - 10/Dec/09 03:58 PM Executor only has update and query methods. Thus inserts and deletes are also considered updates. It sounds like to do what you want, we need another interception point, at the session level. You can do so right now with a proxy class between the SqlSession interface and the default implementation. [ Permalink | Delete | « Hide ] Eli Kizhnerman added a comment - 11/Dec/09 12:28 PM This is not working the way I expected it but that it is not a bug. I can get what I need from the MappedStatement SqlCommandType.
package cn.dcr.mybatis.util; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; /**自定义typeHandler<br/> * 1 插入数据库,男转为male * 2 查询,maile转为男 * @author Administrator * */ public class GenderTypeHandlerCallback extends BaseTypeHandler<String> { private static final String R_FEMALE = "女"; private static final String R_MALE = "男"; private static final String FEMALE = "female"; private static final String MALE = "male"; @Override public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { return cs.getString(columnIndex); } @Override public String getNullableResult(ResultSet rs, String columnName) throws SQLException { String t = rs.getString(columnName); return converSex(t); } @Override public void setNonNullParameter(PreparedStatement preparedStatement, int i, String str, JdbcType jdbcType) throws SQLException { preparedStatement.setString(i, saveValueToDb(str)); } /**插入数据库 * @param value * @return */ private String saveValueToDb(String value) { if (value.equals(R_FEMALE)) { return FEMALE; } else if (value.equals(R_MALE)) { return MALE; } else { throw new IllegalArgumentException("数据库异常!" + value); } } /** 从数据库读出 * @param value * @return */ private String converSex(String value){ if (value.equals(FEMALE)) { return R_FEMALE; } else if (value.equals(MALE)) { return R_MALE; } else { throw new IllegalArgumentException("数据库异常!" + value); } } }
在自定义typeHandler的getNullableResult方法中调整自己的结果集,可以说是在sql执行后,IOC的理论叫后置通知,interceptor应该是前置通知。
@Override public String getNullableResult(ResultSet rs, String columnName) throws SQLException { String t = rs.getString(columnName); return converSex(t); }
在typeHandler的setNonNullParameter,应该是参数传入前转换参数的功能,但是实际操作中没有被调用,不知道为什么。
@Override public void setNonNullParameter(PreparedStatement preparedStatement, int i, String str, JdbcType jdbcType) throws SQLException { preparedStatement.setString(i, saveValueToDb(str)); }
以上是对mybatis 的切入点的实践。总体感觉和struts2的拦截器比,还有差距,至少我理解struts2的拦截器比理解它的要快。
发表评论
-
eclipse Resource 资料
2016-11-15 16:51 617IWorkspace/IWorkspaceRoot/IPro ... -
.docker/machine/machines/default/ca.pem: no such file or directory
2016-09-06 15:59 886Was doing adocker-machine env ... -
list.AddAll 去重复
2015-09-11 12:01 5899问题描述: 有List A和B,A、B中元素都是可保证 ... -
eclipse 插件开发 Setting the Java build path
2014-06-04 11:00 1216JDT Plug-in Developer Guide & ... -
xstream 下划线_问题
2013-12-30 10:18 4180最近在使用xtream 1.4.3,出现了如下的问题: ... -
RCP MessageConsole设置显示的最大行数
2013-09-05 11:34 966MessageConsole.setWaterMarks(5 ... -
freemarker 自定义freeMarker标签
2013-08-12 16:09 3886import java.io.IOException; i ... -
xstream javabean设置属性默认值的问题
2013-04-24 09:54 6568在xstream反序列化使用过程中发现,如果xml无该属 ... -
在使用xstream反序列化时遇到的问题
2013-04-24 09:42 1747public abstract class SBase { ... -
RCP 知识点
2013-03-14 15:10 997获得工作区的所有工程: //获得workspace的所有 ... -
RCP FileSystem 文件系统
2013-02-19 10:42 1381public static File toLocalFile ... -
json转为Map
2013-01-19 22:27 32829package digu.pendant.util; ... -
eclipse4.x 去掉quick access
2013-01-11 14:57 4057/** * 去掉quick access * ... -
xstream 的高级用法,自定义输出结构
2012-12-19 14:35 2423public static void main(Stri ... -
jdt 核心知识
2012-11-27 21:39 1277jdt官方核心知识...................... ... -
jdt 创建java工程,生成代码,运行main方法
2012-11-27 10:50 2345public static IJavaProje ... -
两个osgi的例子程序
2012-11-20 10:21 1075osgi的例子....................直接上代 ... -
jfreechart 的官方例子,很全
2012-11-20 10:19 944jfreechart的官方的demon,很全。 -
SWT 隔行换色-自动宽高调整
2012-10-16 17:32 1710** * 创建:ZhengXi 2009-8-4 */ ... -
RCP 为action添加操作进度条
2012-10-16 13:59 1292public class StartAction extend ...
相关推荐
Mybatis Interceptor 拦截器的实现是 Mybatis 框架中的一种重要机制,通过拦截器可以改变 Mybatis 的默认行为,例如 SQL 重写等。拦截器的实现主要基于责任链模式,通过动态代理组织多个拦截器(插件),这些拦截器...
- 默认情况下,MyBatis使用JDBC的默认事务管理,可以通过配置文件切换为其他的事务管理器。 - 事务的隔离级别和传播行为可通过全局配置文件设置。 7. **MyBatis插件**: - MyBatis提供插件机制,可以拦截...
MyBatis插件机制基于Java的动态代理,通过拦截器(Interceptor)来改变MyBatis的默认行为。每个插件都包含一个或多个拦截器,拦截器会在特定的方法执行前后插入自定义的逻辑。例如,我们可以通过插件实现日志记录、...
- **插件机制**:MyBatis支持插件扩展,可以自定义拦截器来增强或改变默认的行为,如日志记录、性能监控等。 #### 十二、环境配置 - **多环境支持**:MyBatis支持多环境配置,可以在同一个配置文件中配置不同的...
如果 PageHelper 的默认行为不能满足需求,可以通过继承 `PageInterceptor` 并重写部分方法来自定义分页逻辑。例如,可以改变 SQL 语句的生成方式,或者在分页前后执行特定操作。 分页源码解析: 在 PageHelper ...
Mybatis插件本质上是一种拦截器,它通过责任链模式组织多个插件,允许开发者在已映射语句执行过程中的特定点进行拦截调用,从而改变Mybatis的默认行为。 #### 二、插件功能概览 Mybatis插件主要功能包括: 1. **...
- **Mybatis 的插件机制**:通过实现 Interceptor 接口,你可以自定义拦截器来改变 Mybatis 的行为,例如性能监控、日志记录等。 学习 Mybatis 需要结合实际项目,动手实践,理解 SQL 映射的原理,熟悉各种标签的...
- **plugins元素**:允许开发者自定义拦截器,以扩展或修改MyBatis的行为。 ```xml ``` - **Environments元素**:定义环境变量,例如不同的数据库配置。 ```xml ${driver}"/> ${url}"/> ...
6. **自定义过滤器**:在Shiro配置中,可以创建自定义过滤器,通过拦截请求并重定向到特定页面来实现默认跳转的改变。 7. **测试与调试**:完成修改后,进行单元测试和集成测试以确保改动无误,并在不同场景下验证...
- 需要在SpringMVC的配置文件中定义相关的配置信息,如视图解析器、拦截器等。 64. **在SSM架构中,如何配置和使用事务管理** - 通常通过Spring的`PlatformTransactionManager`接口来配置事务管理。可以通过`@...
使用Mybatis拦截器实现对所有SQL的拦截,修改默认的Schema,从而实现多租户数据隔离的目的。 并且支持可插拔。 9、二级缓存 采用J2Cache操作缓存,第一级缓存使用内存(Caffeine),第二级缓存使用 Redis。 由于大量的...
13. MyBatis插件编写及原理:通过拦截器拦截接口方法的调用,可以动态改变方法的行为。 ZooKeeper面试题的知识点包括: 1. ZooKeeper提供的功能:分布式协调服务,处理分布式锁、配置维护、集群管理等。 2. ...
Spring AOP中的代理(JDK动态代理或CGLIB代理)就是装饰器模式的应用,可以为Bean添加拦截器来实现事务管理、日志记录等功能。 6. **代理模式**:Spring的AOP代理(JDK或CGLIB)实现了代理模式,允许在调用目标方法...
使用Mybatis拦截器实现对所有SQL的拦截,修改默认的Schema,从而实现多租户数据隔离的目的。 并且支持可插拔。 9、二级缓存 采用J2Cache操作缓存,第一级缓存使用内存(Caffeine),第二级缓存使用 Redis。 由于大量的...
8. **策略模式**:Spring MVC的拦截器和Spring Data的多数据源访问策略是策略模式的例子,可以根据策略选择不同的执行路径。 9. **模板方法模式**:Spring的JdbcTemplate和RestTemplate等提供了模板方法,定义了...
application-mvc.xml文件是SpringMVC的核心配置文件,包含了SpringMVC的各种配置信息,如Bean定义、拦截器配置等。 2.4 **编写Controller类及Handler方法** 在SpringMVC中,Controller类是处理用户请求的主要...
它的主要功能包括表单验证、国际化支持、拦截器、视图层渲染等。 #### 什么是N层架构 N层架构是一种软件架构模式,将应用程序分为多个逻辑层次。常见的有三层架构(表示层、业务逻辑层、数据访问层)。这种架构有...
- **`equals`**: `equals`方法最初定义在`Object`类中,其默认行为是比较两个对象的引用是否相同。然而,在很多情况下,子类会重写`equals`方法以便根据实际的业务需求来比较对象的内容或状态。例如,`String`类就...
- **装饰器模式**:在不改变对象本身的基础上增加额外的功能。 - **观察者模式**:多个对象监听一个主题对象,当主题对象的状态发生改变时,所有依赖的对象都将得到通知并自动更新。 ### 16. MyBatis框架的优缺点 ...