关于使用mybatis向数据库中插入数据放回值为-2147482646的问题解析

本文深入探讨了在MyBatis中配置defaultExecutorType为BATCH时,执行数据库插入操作返回-2147482646这一异常值的原因。通过源码分析,揭示了这一配置如何影响SqlSession的行为,并提供了修改建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    首先,我们先看下这个返回值-2147482646,这时int的最大值进行+1操作后的值,估计大家都已经知道造成这种结果的原因是再为mybatis配置相关属性时将defaultExecutorType设为BATCH的缘故.

那为什么这么配置会返回这个值呢?大家跟我一块去看看源码吧.

     开门见山,先让大家看下我的mybatis.xml配置

大家请忽略,涂鸦部分(嘻嘻...重点放在框住部分)

    第一,既然对数据的操作都要经过SqlSession来完成,那SqlSession又是哪来的呢?不啰嗦上源码.

由图可以看出,在设置SqlSessionFactory的时候新建的SqlSessionTemplate模板,SqlSessionTemplate是不是有点面熟?

对了就是我们在配置文件中的配置的SqlSessionTemplate.而且能从第一张图片中看到我们的defaultExecutorType就设为BATCH.

默认的就是BATCH.

那么我们现在获得到SqlSession后进行一次插入操作:

getSqlSession().insert("CustomerMailMapper.addMailInfo",mail);

那我们看源码SqlSession接口中对应的方法

接着去看实现类中的方法实现

可以看出,还是调用的他本身的update方法,那怎么办?接着看嘛...

终于让我们看到返回值的出处了,但这就完了么?还没有可以看出调用了自己的executor属性的update属性.

这Executor也是接口,那我们之间看他的实现类

有这几种,根据我们的配置当然会是执行BatchExecutor,但是当我们进到BatchExecutor是会发现他并没有update方法,那在哪呢?

原来他继承了BaseExecutor这个抽象类,BaseExecutor里有update方法.

可以看出这里返回的值是调用的本身的doUpdate方法,是不是感觉真相距离我们越来越近了,可以剧透下你的直觉是对的.来上图

看到我画的重点没,可以看出这个方法不管你的逻辑是怎么实现的直接给你返回了-2147482646.真是千呼万唤始出来啊.所以如果大家需要在向数据库插入数据时的返回值就把Batch给改掉,而这个值都可以设置那些呢?

Batch就是指的SqlSessionTemplate中的ExecutorType这个属性,而这个属性是个枚举类

只有是那种,所以你想要怎样,百度下这三种配置所对应的情况就行了.

(拜拜...)

 

 

 

<think>好的,我现在需要回答用户关于如何使用MyBatis拦截器和注解来防止或实现SQL注入的问题。首先,我得回忆一下MyBatis拦截器的相关知识。根据用户提供的引用内容,MyBatis拦截器可以拦截Executor、ParameterHandler、StatementHandler等组件的方法,这可能涉及到SQL处理的各个阶段。 用户提到引用1和2中的拦截器主要用于打印完整SQL,而引用3和4涉及通过拦截器修改SQL。防止SQL注入通常需要对输入参数进行过滤或转义,或者在SQL执行前检查是否有恶意代码。因此,可能的实现方式包括:使用ParameterHandler拦截器对参数进行处理,或者在StatementHandler拦截器中对生成的SQL语句进行校验。 接下来要考虑注解的作用。MyBatis的注解如@Intercepts和@Signature用于定义拦截器的作用目标。例如,可以创建一个拦截器,在参数设置时(ParameterHandler的setParameters方法)检查参数是否含有敏感字符,并进行转义。或者,在StatementHandler的prepare阶段修改SQL语句,添加过滤条件。 需要确保拦截器的配置正确,比如在Spring中通过@Bean注册拦截器,如引用1中的示例。同时,要处理不同数据库的转义规则,比如单引号的转义等。此外,可能还需要结合自定义注解来标记需要特殊处理的参数或方法,但用户提供的引用中没有提到自定义注解的使用,可能需要进一步思考如何结合现有注解。 还需要考虑SQL注入的常见攻击方式,比如通过用户输入添加' OR '1'='1之类的语句。拦截器可以在参数绑定前对字符串类型的参数进行转义,将单引号替换为两个单引号,或者使用预编译语句来避免拼接。MyBatis本身使用预编译的占位符,但如果有不安全的动态SQL,仍然可能存在风险,因此拦截器可以作为补充防护。 可能的问题点包括:拦截器的执行顺序、如何高效地检查所有参数、防止误处理合法输入。另外,需要参考MyBatis的文档,确保拦截器的实现不会影响其他功能,比如分页插件等。 总结步骤可能包括:1. 创建实现Interceptor接口的类,使用@Intercepts指定拦截的方法;2. 在拦截方法中对参数或SQL进行处理;3. 注册拦截器到MyBatis配置中;4. 测试拦截器是否有效防止SQL注入。同时,可以建议结合MyBatis的动态SQL特性,使用安全的#{}占位符,避免${}导致的拼接问题。</think>### MyBatis拦截器与注解实现SQL注入防护机制 #### 一、SQL注入防护核心思路 1. **参数过滤**:在参数绑定阶段对输入内容进行合法性校验或转义处理 2. **语句校验**:在SQL执行前检查语句结构是否合法 3. **动态SQL控制**:规范MyBatis动态标签使用,避免`${}`不安全拼接[^2] #### 二、具体实现方案 ##### 方案1:参数处理器拦截(推荐) ```java @Intercepts({ @Signature(type = ParameterHandler.class, method = "setParameters", args = {PreparedStatement.class}) }) public class SqlInjectionInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { ParameterHandler handler = (ParameterHandler) invocation.getTarget(); Object parameterObject = handler.getParameterObject(); // 参数安全检查 if (parameterObject != null) { checkForSqlInjection(parameterObject); } return invocation.proceed(); } private void checkForSqlInjection(Object param) { if (param instanceof String) { String value = (String) param; if (containsSqlInjectionPattern(value)) { throw new IllegalArgumentException("检测到非法SQL注入字符"); } } // 处理Map/Bean等复杂类型 } } ``` ##### 方案2:语句处理器拦截 ```java @Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}) }) public class StatementInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { StatementHandler handler = (StatementHandler) invocation.getTarget(); MetaObject metaObject = SystemMetaObject.forObject(handler); String originalSql = (String) metaObject.getValue("delegate.boundSql.sql"); // SQL语句安全检查 if (detectSqlInjection(originalSql)) { throw new SQLException("检测到危险SQL操作"); } return invocation.proceed(); } } ``` #### 三、配置启用拦截器 ```java @Configuration public class MyBatisConfig { @Bean @ConditionalOnProperty(name = "mybatis.security.enabled", havingValue = "true") public SqlInjectionInterceptor sqlInjectionInterceptor() { return new SqlInjectionInterceptor(); } } ``` #### 四、安全防护最佳实践 1. **结合注解参数验证**:使用JSR-303验证框架 ```java public class UserParam { @Pattern(regexp = "^[a-zA-Z0-9_]+$", message = "包含非法字符") private String username; } ``` 2. **动态SQL规范**:强制使用`#{}`占位符 3. **高危字符过滤清单**: ```java private static final String[] SQL_INJECTION_KEYWORDS = { "'", "\"", ";", "--", "/*", "*/", "xp_", "exec ", "union ", "drop ", "insert ", "delete " }; ``` 4. **日志监控**:结合SQL打印拦截器进行审计[^1] #### 五、防护效果验证 1. 测试注入攻击: ```sql SELECT * FROM users WHERE name = 'admin' OR '1'='1' ``` 2. 拦截器将触发以下异常: ```log java.lang.IllegalArgumentException: 检测到非法SQL注入字符 ``` #### 六、注意事项 1. 需要处理特定场景的合法字符(如包含单引号的内容) 2. 需兼容不同数据库方言的特殊语法 3. 建议配合参数加密存储等安全措施[^4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值