java怎么拦截mapper方法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java怎么拦截mapper方法相关的知识,希望对你有一定的参考价值。

参考技术A 1、使用@Aspect注解
要去使用jdk的代理,否则代理不了mapper(即mybatis代理的mapper没有默认的构造器,cglib无法再给这个代理构造代理,会报如下错误org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class com.sun.proxy.$Proxy13]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class class com.sun.proxy.$Proxy13)
<!-- 启动对@Aspectj的支持 true为cglib,false为jdk代理,为true的话,会导致拦截不了mybatis的mapper-->
<aop:aspectj-autoproxy proxy-target-class="false" />

之后就是使用注解去配置拦截,进行修改记录的操作
@Aspect
@Component
public class DatalogAspect
private static final Logger logger = LoggerFactory.getLogger(DatalogAspect.class);
@Resource
private ActionMapper actionMapper;
@Pointcut("execution(public * com.yami.infrastructure.repository.mapper.*.insert*(..)) && !execution(public * com.yami.infrastructure.repository.mapper.ActionMapper.insert*(..))")
public void insert()

@Pointcut("execution(public * com.yami.infrastructure.repository.mapper.*.update*(..))")
public void update()

@Pointcut("execution(public * com.yami.infrastructure.repository.mapper.*.delete*(..))")
public void delete()

@Around("insert() || update() || delete()")
public Object addOperateLog(ProceedingJoinPoint pjp) throws Throwable
...



2、使用MethodInterceptor
使用aopalliance的MethodInterceptor
(1)配置文件
去掉对@Aspect注解的支持(也可以不去掉,只要不是proxy-target-class = true就可以)。然后配置aop
<bean id="datalogInterceptor" class="com.yami.infrastructure.datalog.DatalogInterceptor" />
<aop:config>
<aop:pointcut id="datalogInsertPointCut" expression="execution(* com.yami.infrastructure.repository.mapper..insert*(..)) && !execution(* com.yami.infrastructure.repository.mapper.ActionMapper.*(..))" />
<aop:pointcut id="datalogUpdatePointCut" expression="execution(* com.yami.infrastructure.repository.mapper..update*(..)) && !execution(* com.yami.infrastructure.repository.mapper.ActionMapper.*(..))" />
<aop:pointcut id="datalogDeletePointCut" expression="execution(* com.yami.infrastructure.repository.mapper..delete*(..)) && !execution(* com.yami.infrastructure.repository.mapper.ActionMapper.*(..))" />
<aop:advisor advice-ref="datalogInterceptor" pointcut-ref="datalogInsertPointCut" />
<aop:advisor advice-ref="datalogInterceptor" pointcut-ref="datalogUpdatePointCut" />
<aop:advisor advice-ref="datalogInterceptor" pointcut-ref="datalogDeletePointCut" />
</aop:config>

(2)实现MethodInterceptor
public class DatalogInterceptor implements MethodInterceptor
private static final Logger logger = LoggerFactory.getLogger(DatalogInterceptor.class);
public DatalogInterceptor()

@Resource
private ActionMapper actionMapper;
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable
Method method = methodInvocation.getMethod();
String methodName = method.getName();
Class<?> cls = method.getDeclaringClass();
Object service = methodInvocation.getThis();
Object[] args = methodInvocation.getArguments();
Integer actionType = -1;
...

本回答被提问者和网友采纳

myBatis mapper 返回任意类型

<select id="select" parameterType="String" resultType="T">
感谢两位的回答,我现在的要求不是说我不会用mybatis,我是会一些基础的东西,我现在想对mybatis 框架进行封装,所以想要一些 相关mybatis 的动态写法,希望朋友们,多多指教!

定义一个MapInterceptor用于拦截对应的结果集返回一个Map。
其代码如下所示:
@Intercepts(@Signature(method="handleResultSets", type=ResultSetHandler.class, args=Statement.class))
public class MapInterceptor implements Interceptor

/* (non-Javadoc)
* @see org.apache.ibatis.plugin.Interceptor#intercept(org.apache.ibatis.plugin.Invocation)
*/
public Object intercept(Invocation invocation) throws Throwable
//通过invocation获取代理的目标对象
Object target = invocation.getTarget();
//暂时ResultSetHandler只有FastResultSetHandler这一种实现
if (target instanceof FastResultSetHandler)
FastResultSetHandler resultSetHandler = (FastResultSetHandler) target;
//利用反射获取到FastResultSetHandler的ParameterHandler属性,从而获取到ParameterObject;
ParameterHandler parameterHandler = ReflectUtil.getFieldValue(resultSetHandler, "parameterHandler");
Object parameterObj = parameterHandler.getParameterObject();
//判断ParameterObj是否是我们定义的MapParam,如果是则进行自己的处理逻辑
if (parameterObj instanceof MapParam) //拦截到了
MapParam mapParam = (MapParam) parameterObj;
//获取到当前的Statement
Statement stmt = (Statement) invocation.getArgs()[0];
//通过Statement获取到当前的结果集,对其进行处理,并返回对应的处理结果
return handleResultSet(stmt.getResultSet(), mapParam);


//如果没有进行拦截处理,则执行默认逻辑
return invocation.proceed();


/**
* 处理结果集
* @param resultSet
* @param mapParam
* @return
*/
private Object handleResultSet(ResultSet resultSet, MapParam mapParam)
// TODO Auto-generated method stub
if (resultSet != null)
//拿到Key对应的字段
String keyField = (String) mapParam.get(MapParam.KEY_FIELD);
//拿到Value对应的字段
String valueField = (String) mapParam.get(MapParam.VALUE_FIELD);
//定义用于存放Key-Value的Map
Map<Object, Object> map = new HashMap<Object, Object>();
//handleResultSets的结果一定是一个List,当我们的对应的Mapper接口定义的是返回一个单一的元素,并且handleResultSets返回的列表
//的size为1时,Mybatis会取返回的第一个元素作为对应Mapper接口方法的返回值。
List<Object> resultList = new ArrayList<Object>();
try
//把每一行对应的Key和Value存放到Map中
while (resultSet.next())
Object key = resultSet.getObject(keyField);
Object value = resultSet.getObject(valueField);
map.put(key, value);

catch (SQLException e)
e.printStackTrace();
finally
closeResultSet(resultSet);

//把封装好的Map存放到List中并进行返回
resultList.add(map);
return resultList;

return null;


/**
* 关闭ResultSet
* @param resultSet 需要关闭的ResultSet
*/
private void closeResultSet(ResultSet resultSet)
try
if (resultSet != null)
resultSet.close();

catch (SQLException e)




/* (non-Javadoc)
* @see org.apache.ibatis.plugin.Interceptor#plugin(java.lang.Object)
*/
public Object plugin(Object obj)
return Plugin.wrap(obj, this);


/* (non-Javadoc)
* @see org.apache.ibatis.plugin.Interceptor#setProperties(java.util.Properties)
*/
public void setProperties(Properties props)



参考技术A 虽然这个问题是N年前的了,但是我最近也用到了类似的功能,刚好也误打误撞碰巧做出来了,所以还是说一下我的解决方案吧,如有可改之处,敬请各位大佬不吝赐教。
首先,需求是,定义一个动态的方法,查询的时候根据查询语句直接查询,所以和楼主说的一样,我的select标签是这样的:
<select id="select" parameterType="java.lang.String" resultType="AllResultMap">
$_parameter
</select>
其中,$_parameter最好和我写的一样,因为我试过_param,发现报错了,我也不知道为什么,但是这么写是可以的。另外AllResultMap的具体实现为:
<resultMap type="java.util.Map" id="AllResultMap">
</resultMap>
这样,在XXXmapper.java文件里面,接口只需要这么写:
public LinkedList<Map> select(String _parameter);
这样最终查询出来的结果就是一个list里面有很多个map对象,而map中的key就是你的列名,value就是数据库一条record对应的值。然后剩下的就是按照你自己的意愿对map进行解析、封装成你自己想要的类的对象就好了。
参考技术B 可以知道resultTyp="map",查询语句类似 SELECT name AS nameKey,age AS ageKey FROM table;返回用一个Hashmap接收,对应的可以map.get(nameKey);map.get(ageKey);就可以获得对应的值,然后再封装吧。追问

我目前的写法是

SELECT
*
FROM
users
WHERE
userId = 'userId'
可是结果,让我无法理解 本来应该是 userId userName 都有值,结果 就只把userId 的值 以字符串的形式给我返回来。

本回答被提问者采纳
参考技术C 不行,myBatis要么你明确返回类型,配置某个类,要么你就返回HashMap。列表就用List<HashMap>追问

那怎么才能让它 根据我传入的类型,做为返回类型
例如 我传入 A 类 查询结果后 返回 A类

追答

http://zhidao.baidu.com/link?url=9NsAMlQyEjBT6Hk9wfLzQXogP4OzncU60LB4QGsiHisZJzJjD9X0yJC6gA-mZlejwPoZItXlcldSDKQYaiV8Eq

参考技术D 你是想提供答案,还是求助,求助的话遇到什么问题追问

你好,刚才着急提交实在不好意思,我想求助
mybatis在查询时可不可以不指定返回类型,用T或Object目前我试过了,不行

以上是关于java怎么拦截mapper方法的主要内容,如果未能解决你的问题,请参考以下文章

springBoot Interceptor拦截器注入mapper 为null

请教Mybatis中如何在程序中获取Mapper中定义的SQL语句

spring 整合mybatis后 若mapper.java与mapper.xml不在同一文件夹,该怎么配置

Mapper的使用

mybatis 通用mapper.xml中 insert 方法不是自增主键怎么返回

mybatis 通用mapper.xml中 insert 方法不是自增主键怎么返回?