1private static final int MaxBatchLength = 100; 2 3public void updateBatch(List<T>list, BaseMapper<T> mapper){ 4 5 if (!Proxy.isProxyClass(mapper.getClass())){ 6 throw new RuntimeException("mapper必须是代理对象"); 7 } 8 InvocationHandler invocationHandler = Proxy.getInvocationHandler(mapper); 9 if (null==invocationHandler){ 10 throw new RuntimeException("mapper必须是有处理器的代理对象"); 11 } 12 Field fieldSession; 13 try { 14 fieldSession = invocationHandler.getClass().getDeclaredField("sqlSession"); 15 } catch (NoSuchFieldException e) { 16 throw new RuntimeException("从mapper代理对象中获取不到sqlSession", e); 17 } 18 Field fieldMapper; 19 try { 20 fieldMapper = invocationHandler.getClass().getDeclaredField("mapperInterface"); 21 } catch (NoSuchFieldException | SecurityException e) { 22 throw new RuntimeException("从mapper代理对象中获取不到mapperInterface", e); 23 } 24 fieldSession.setAccessible(true); 25 SqlSession session; 26 try { 27 session = (SqlSession) fieldSession.get(invocationHandler); 28 } catch (IllegalArgumentException | IllegalAccessException e) { 29 throw new RuntimeException("从mapper代理对象中获取sqlSession失败,不应该出现此异常", e); 30 } 31 fieldMapper.setAccessible(true); 32 Class<?> mapperInterface; 33 try { 34 mapperInterface = (Class<?>) fieldMapper.get(invocationHandler); 35 } catch (IllegalArgumentException | IllegalAccessException e) { 36 throw new RuntimeException("从mapper代理对象中获取mapperInterface失败,不应该出现此异常", e); 37 } 38 // 方法名(mybatis的对应xml中的sql语句的id) 39 String methodName = mapperInterface.getName() + ".updateEntityBatch"; 40 System.out.println("获取方法的SQL:"+methodName); 41 //传递参数保证,要更新的字段存在(若没有判空,则可以不用传递参数) 42 BoundSql boundSql = session.getConfiguration().getMappedStatement(methodName).getBoundSql(list.get(0)); 43 44 //是否是独立的事务 45 boolean atmo = true, succ = false; 46 System.out.println("每次批量执行最大长度为:"+MaxBatchLength ); 47 48 //获取批量执行的sql 49 String sql = boundSql.getSql(); 50 //获取连接 51 Connection connection = null; 52 PreparedStatement ps = null; 53 List<Closeable> closeables = new LinkedList<>(); 54 try { 55 connection = session.getConnection(); 56 if (atmo = null == connection || connection.isClosed()) { 57 DataSource dataSource = session.getConfiguration().getEnvironment().getDataSource(); 58 connection = dataSource.getConnection(); 59 //事务不自动提交 60 connection.setAutoCommit(false); 61 System.out.println("session中的连接不可使用,使用独立的连接和事务"); 62 } else { 63 System.out.println("使用session的连接,事务和session保持一致"); 64 } 65 66 ps = connection.prepareStatement(sql); 67 68 int index = 0; 69 System.out.println("需要批量更新"+list.size()+"个对象"); 70 71 for (int i = 0, j = list.size(); i < j; i++, index++) { 72 T t = list.get(i); 73 //将实体类转换为map 74 BeanMap map = BeanMap.create(t); 75 System.out.println("绑定对象:"+ map); 76 for (int ii = 1, jj = boundSql.getParameterMappings().size(); ii <= jj; ii++) { 77 ParameterMapping parameterMapping = boundSql.getParameterMappings().get(ii - 1); 78 String name = parameterMapping.getProperty(); 79 Object value = map.get(name); 80 if (null == value) { 81 // 为空时候尝试取默认值 82 value = map.get(name + "Default"); 83 } 84 if (null != value && value instanceof Date) { 85 Timestamp date = new Timestamp(((Date) value).getTime()); 86 value = date; 87 } 88 // 单独处理clob类型 89 if (JdbcType.CLOB.equals(parameterMapping.getJdbcType())) { 90 StringReader sr = new StringReader(null == value ? "" : value.toString()); 91 ps.setClob(ii, sr); 92 closeables.add(sr); 93 } else { 94 ps.setObject(ii, value, parameterMapping.getJdbcType().TYPE_CODE); 95 } 96 } 97 ps.addBatch(); 98 if (index > MaxBatchLength) { 99 ps.executeBatch(); 100 ps.clearBatch(); 101 index = 0; 102 } 103 } 104 if (index > 0) { 105 //执行剩下的 106 ps.executeBatch(); 107 } 108 succ = true; 109 }catch (Exception e){ 110 throw new RuntimeException("批量更新失败",e); 111 }finally { 112 // 如果是独立的事务 113 if (atmo && null != connection) { 114 log.info("检测到独立事务,判断提交/回滚"); 115 if (succ) { 116 try { 117 connection.commit(); 118 log.info("独立事务提交成功"); 119 } catch (SQLException e) { 120 log.info("独立事务提交失败"); 121 throw new RuntimeException(e); 122 } 123 } else { 124 try { 125 connection.rollback(); 126 log.info("独立事务回滚成功"); 127 } catch (SQLException e) { 128 log.info("独立事务回滚失败"); 129 throw new RuntimeException(e); 130 } 131 } 132 } 133 if (null != ps) { 134 try { 135 ps.close(); 136 } catch (SQLException e) { 137 e.printStackTrace(); 138 } 139 } 140 if (atmo && null != connection) { 141 try { 142 connection.close(); 143 } catch (SQLException e) { 144 e.printStackTrace(); 145 } 146 } 147 for (Closeable closeable : closeables) { 148 try { 149 closeable.close(); 150 } catch (IOException e) { 151 e.printStackTrace(); 152 } 153 } 154 } 155 }
java通过反射拿到mybatis中的sql语句并操作
Wesley13
2021-10-11
1134 1 0
点赞
收藏
评论区
加载中...