出现ORA-01461:仅能绑定要插入LONG列的LONG值 mybatis+orcale
来源:互联网 发布:黑马编程培训机构 编辑:程序博客网 时间:2024/05/17 07:45
批量存储CLOB类型:
原sql语句:
<insert id="insertByList" parameterType="java.util.List">insert into Users(fid,fname)<foreach open="(" close=")" collection="list" item="item"index="index" separator="union">select#{item.fid,jdbcType=VARCHAR},#{fname,jdbcType=CLOB}from dual</foreach></insert>
此时报错:出现ORA-01461:仅能绑定要插入LONG列的LONG值
原因在于sql语句中 select 后面的字段如果大于4000个字节时就会被转成Long型。
解决办法:使用拦截器
BatchExecutorAdaptor.java
package com.voucher.engine.utils.batch;import com.google.common.base.Throwables;import org.apache.ibatis.executor.BatchExecutor;import org.apache.ibatis.executor.BatchResult;import org.apache.ibatis.mapping.MappedStatement;import org.apache.ibatis.session.Configuration;import org.apache.ibatis.transaction.Transaction;import java.sql.SQLException;import java.util.Arrays;import java.util.Collections;import java.util.List;import java.util.Map;final class BatchExecutorAdaptor extends BatchExecutor { public BatchExecutorAdaptor(Configuration configuration, Transaction transaction) { super(configuration, transaction); } @Override public int update(MappedStatement ms, Object parameter) throws SQLException { if (parameter == null) { super.update(ms, parameter); } Map map = (Map)parameter; map.get("list"); final Object params = map.get("list"); final Iterable<?> paramIterable = toIterable(params); try { for (Object obj : paramIterable) { super.update(ms, obj); } List<BatchResult> batchResults = doFlushStatements(false); if (batchResults == null || batchResults.size() == 0) { return 0; } return resolveUpdateResult(batchResults); } catch (Exception e) { doFlushStatements(true); Throwables.propagate(e); return 0; } } private Iterable<?> toIterable(final Object params) { if (params == null) { return Collections.emptyList(); } Iterable<?> paramIterable; if (params instanceof Iterable) { paramIterable = (Iterable<?>) params; } else if (params.getClass().isArray()) { Object[] array = (Object[]) params; paramIterable = Arrays.asList(array); } else { paramIterable = Collections.singletonList(params); } return paramIterable; } private int resolveUpdateResult(final List<BatchResult> batchResults) { int result = 0; for (BatchResult batchResult : batchResults) { int[] updateCounts = batchResult.getUpdateCounts(); if (updateCounts == null || updateCounts.length == 0) { continue; } for (int updateCount : updateCounts) { result += updateCount; } } return result; }}
BatchExecutorInterceptor.java
package com.voucher.engine.utils.batch;import java.sql.SQLException;import java.util.Properties;import org.apache.ibatis.executor.BatchExecutor;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.Configuration;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import com.voucher.engine.utils.batch.utils.BatchUtils;import com.voucher.engine.utils.batch.utils.ExecutorUtils;import com.voucher.engine.utils.batch.utils.Reflections;/** * 方便使用的批量更新插件,只需要sql statement id以batch开头,参数为Iterable或者数组即可. * <p/> * 限制:最好是作为第一个拦截器使用,因为在它之前的拦截器不会被调用 * * */@Intercepts({ @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),})public class BatchExecutorInterceptor implements Interceptor { private static final Logger LOGGER = LoggerFactory.getLogger(BatchExecutorInterceptor.class); @Override public Object intercept(final Invocation invocation) throws Throwable { //check argument if (invocation.getArgs()[1] == null) { return invocation.proceed(); } final MappedStatement ms = (MappedStatement) invocation.getArgs()[0]; //if it should use batch if (!BatchUtils.shouldDoBatch(ms.getId())) { return invocation.proceed(); } //create batch executor final Executor targetExecutor = ExecutorUtils.getTargetExecutor((Executor) invocation.getTarget()); if (targetExecutor instanceof BatchExecutor) { return invocation.proceed(); } final Configuration configuration = (Configuration) Reflections.getField("configuration", targetExecutor); final BatchExecutor batchExecutor = new BatchExecutorAdaptor(configuration, targetExecutor.getTransaction()); try { return batchExecutor.update(ms, invocation.getArgs()[1]); } catch (SQLException e) { batchExecutor.flushStatements(true); throw e; } } @Override public Object plugin(final Object target) { if (!(target instanceof Executor)) { return target; } if (target instanceof BatchExecutor) { return target; } return Plugin.wrap(target, this); } @Override public void setProperties(final Properties properties) { }}
BatchUtils.java
package com.voucher.engine.utils.batch.utils;public abstract class BatchUtils { private BatchUtils() { } public static boolean shouldDoBatch(final String statementId) { return statementId.startsWith("batch", statementId.lastIndexOf('.') + 1); }}
package com.voucher.engine.utils.batch.utils;import org.apache.ibatis.executor.CachingExecutor;import org.apache.ibatis.executor.Executor;import java.lang.reflect.Proxy;public abstract class ExecutorUtils { private ExecutorUtils() { } public static Executor getTargetExecutor(final Executor executor) { Executor targetExecutor = executor; while (targetExecutor instanceof Proxy) { targetExecutor = (Executor) Reflections.getField("target", Proxy.getInvocationHandler(targetExecutor)); } //取真正的executor if (targetExecutor instanceof CachingExecutor) { targetExecutor = (Executor) Reflections.getField("delegate", targetExecutor); } return targetExecutor; }}
package com.voucher.engine.utils.batch.utils;import java.lang.reflect.Field;public final class Reflections { private Reflections() { } private static Field findField(Class<?> clazz, String name) { return findField(clazz, name, null); } public static Field findField(Class<?> clazz, String name, Class<?> type) { Class<?> searchType = clazz; while (!Object.class.equals(searchType) && searchType != null) { Field[] fields = searchType.getDeclaredFields(); for (Field field : fields) { if ((name == null || name.equals(field.getName())) && (type == null || type .equals(field.getType()))) { return field; } } searchType = searchType.getSuperclass(); } return null; } public static Object getField(String fieldName, Object target) { Field field = findField(target.getClass(), fieldName); if (!field.isAccessible()) { field.setAccessible(true); } try { return field.get(target); } catch (IllegalAccessException ex) { throw new IllegalStateException("Unexpected reflection exception - " + ex.getClass() .getName() + ": " + ex.getMessage(), ex); } }}
开始写配置文件:
mybatisDao.xml:(以batch开头)
<insert id="batchInsert" parameterType="java.util.List">insert into Users (fid,fname) values(#{fid,jdbcType=VARCHAR},#{fname,jdbcType=CLOB})}</insert>
mybatis-configxml:
<plugins> <plugin interceptor="com.voucher.engine.utils.batch.BatchExecutorInterceptor"></plugin> </plugins>
appliccationContext.xml
<bean id="SqlSessionFactoryOracle" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSourceOracle" /><property name="typeAliasesPackage" value="com.voucher.**.domain" /><property name="mapperLocations"><list><value>classpath*:mybatis/StorageDao.xml</value></list></property><property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/></bean>
ok了 测试一下就好了。
0 0
- 出现ORA-01461:仅能绑定要插入LONG列的LONG值 mybatis+orcale
- mybatis批量插入clob,ORA-01461-仅能绑定要插入LONG列的LONG值
- mybatis批量插入clob,ORA-01461-仅能绑定要插入LONG列的LONG值
- ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值
- ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值
- ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值
- ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值
- ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值
- java.sql.SQLException: ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值
- ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值
- ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值
- ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值
- ORA-01461:仅能绑定要插入 LONG 列的 LONG 值
- ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值
- 调试经验-ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值
- Cause: java.sql.SQLException: ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值
- NHibernate 处理 oracle 的long数据类型(ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值)
- java.sql.SQLException: ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值;ORACLE数据库异常解决办法
- 分块的基本应用
- 判断一个数是不是3的n次方
- 一道在知乎很火的 Java 题——如何同时输出 ab
- 使用angular.bootstrap完成模块的手动加载(一个页面多个ng-app时使用)
- 3.6 Git 分支 - 变基
- 出现ORA-01461:仅能绑定要插入LONG列的LONG值 mybatis+orcale
- Android中Base64加密
- C# 使用 C# Aspose.Cells导出多个Sheet的Excel .net导出Excel C#导出Excel
- MySQL GTID 错误处理汇总
- Android Frament的切换(解决replace的低效)
- Weblogic数据库连接池相关参数说明
- GRE填空:从菜鸟到老鸟的复习规划
- 最大流模板
- EnterCriticalSection