private static final int MaxBatchLength = 100;
public void updateBatch(List<T>list, BaseMapper<T> mapper){

         if (!Proxy.isProxyClass(mapper.getClass())){
throw new RuntimeException("mapper必须是代理对象");
}
InvocationHandler invocationHandler = Proxy.getInvocationHandler(mapper);
if (null==invocationHandler){
throw new RuntimeException("mapper必须是有处理器的代理对象");
}
Field fieldSession;
try {
fieldSession = invocationHandler.getClass().getDeclaredField("sqlSession");
} catch (NoSuchFieldException e) {
throw new RuntimeException("从mapper代理对象中获取不到sqlSession", e);
}
Field fieldMapper;
try {
fieldMapper = invocationHandler.getClass().getDeclaredField("mapperInterface");
} catch (NoSuchFieldException | SecurityException e) {
throw new RuntimeException("从mapper代理对象中获取不到mapperInterface", e);
}
fieldSession.setAccessible(true);
SqlSession session;
try {
session = (SqlSession) fieldSession.get(invocationHandler);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new RuntimeException("从mapper代理对象中获取sqlSession失败,不应该出现此异常", e);
}
fieldMapper.setAccessible(true);
Class<?> mapperInterface;
try {
mapperInterface = (Class<?>) fieldMapper.get(invocationHandler);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new RuntimeException("从mapper代理对象中获取mapperInterface失败,不应该出现此异常", e);
}
// 方法名(mybatis的对应xml中的sql语句的id)
String methodName = mapperInterface.getName() + ".updateEntityBatch";
System.out.println("获取方法的SQL:"+methodName);
//传递参数保证,要更新的字段存在(若没有判空,则可以不用传递参数)
BoundSql boundSql = session.getConfiguration().getMappedStatement(methodName).getBoundSql(list.get(0)); //是否是独立的事务
boolean atmo = true, succ = false;
System.out.println("每次批量执行最大长度为:"+MaxBatchLength ); //获取批量执行的sql
String sql = boundSql.getSql();
//获取连接
Connection connection = null;
PreparedStatement ps = null;
List<Closeable> closeables = new LinkedList<>();
try {
connection = session.getConnection();
if (atmo = null == connection || connection.isClosed()) {
DataSource dataSource = session.getConfiguration().getEnvironment().getDataSource();
connection = dataSource.getConnection();
//事务不自动提交
connection.setAutoCommit(false);
System.out.println("session中的连接不可使用,使用独立的连接和事务");
} else {
System.out.println("使用session的连接,事务和session保持一致");
} ps = connection.prepareStatement(sql); int index = 0;
System.out.println("需要批量更新"+list.size()+"个对象"); for (int i = 0, j = list.size(); i < j; i++, index++) {
T t = list.get(i);
//将实体类转换为map
BeanMap map = BeanMap.create(t);
System.out.println("绑定对象:"+ map);
for (int ii = 1, jj = boundSql.getParameterMappings().size(); ii <= jj; ii++) {
ParameterMapping parameterMapping = boundSql.getParameterMappings().get(ii - 1);
String name = parameterMapping.getProperty();
Object value = map.get(name);
if (null == value) {
// 为空时候尝试取默认值
value = map.get(name + "Default");
}
if (null != value && value instanceof Date) {
Timestamp date = new Timestamp(((Date) value).getTime());
value = date;
}
// 单独处理clob类型
if (JdbcType.CLOB.equals(parameterMapping.getJdbcType())) {
StringReader sr = new StringReader(null == value ? "" : value.toString());
ps.setClob(ii, sr);
closeables.add(sr);
} else {
ps.setObject(ii, value, parameterMapping.getJdbcType().TYPE_CODE);
}
}
ps.addBatch();
if (index > MaxBatchLength) {
ps.executeBatch();
ps.clearBatch();
index = 0;
}
}
if (index > 0) {
//执行剩下的
ps.executeBatch();
}
succ = true;
}catch (Exception e){
throw new RuntimeException("批量更新失败",e);
}finally {
// 如果是独立的事务
if (atmo && null != connection) {
log.info("检测到独立事务,判断提交/回滚");
if (succ) {
try {
connection.commit();
log.info("独立事务提交成功");
} catch (SQLException e) {
log.info("独立事务提交失败");
throw new RuntimeException(e);
}
} else {
try {
connection.rollback();
log.info("独立事务回滚成功");
} catch (SQLException e) {
log.info("独立事务回滚失败");
throw new RuntimeException(e);
}
}
}
if (null != ps) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (atmo && null != connection) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
for (Closeable closeable : closeables) {
try {
closeable.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

java通过反射拿到mybatis中的sql语句并操作的更多相关文章

  1. 控制台输出 mybatis 中的sql语句

    控制台输出 mybatis 中的sql语句 在 log4j.xml 文件中 增加如下配置 <!-- mybatis 输出的sql,DEBUG级别 --> <logger name=& ...

  2. MyBatis中动态SQL语句完成多条件查询

    一看这标题,我都感觉到是mybatis在动态SQL语句中的多条件查询是多么的强大,不仅让我们用SQL语句完成了对数据库的操作:还通过一些条件选择语句让我们SQL的多条件.动态查询更加容易.简洁.直观. ...

  3. Mybatis中动态SQL语句中的parameterType不同数据类型的用法

    Mybatis中动态SQL语句中的parameterType不同数据类型的用法1. 简单数据类型,    此时#{id,jdbcType=INTEGER}中id可以取任意名字如#{a,jdbcType ...

  4. MyBatis 中实现SQL语句中in的操作 (11)

    MyBatis 中实现SQL语句中in的操作 概括:应用myBatis实现SQL查询中IN的操作 1.数据库结构及其数据 2.mapper.xml文件 <?xml version="1 ...

  5. 在mybatis中写sql语句的一些体会

    本文会使用一个案例,就mybatis的一些基础语法进行讲解.案例中使用到的数据库表和对象如下: article表:这个表存放的是文章的基础信息 -- ------------------------- ...

  6. mybatis中打印sql语句

    在mybatis-config.xml中properties节点下,配置一个settings节点 <settings> <setting name="cacheEnable ...

  7. EF Core中执行Sql语句查询操作之FromSql,ExecuteSqlCommand,SqlQuery

    一.目前EF Core的版本为V2.1 相比较EF Core v1.0 目前已经增加了不少功能. EF Core除了常用的增删改模型操作,Sql语句在不少项目中是不能避免的. 在EF Core中上下文 ...

  8. 阶段3 1.Mybatis_08.动态SQL_03.mybatis中动态sql语句-foreach和sql标签

    foreach标签 in的查询 sql语句好写,但是传参在映射文件里面改怎么传呢 定义一个List<Integer>成员变量,然后生成get和set 定义一个新的查询方法 open:开始符 ...

  9. 阶段3 1.Mybatis_08.动态SQL_02.mybatis中动态sql语句-where标签的使用

    这里的userSex是实体类里面的属性名,而不是数据库内的字段名称 一个老王改成性别女,为了区分一下 增加sex字段的查询 where标签 用上where和刚才的执行效果是一样的 where标签使我们 ...

随机推荐

  1. 02 IDEA创创建第一个maven工程

    导入坐标

  2. spring boot 参数传递(spring boot 参数传数 arg0 每一个参数 arg0#{arg0},arg1 #{arg1})

    spring boot 参数传数 arg0 每一个参数 arg0#{arg0},arg1  #{arg1} @Select("select * from sys_user where nam ...

  3. BZOJ 4804: 欧拉心算 欧拉函数

    Description 给出一个数字N Input 第一行为一个正整数T,表示数据组数. 接下来T行为询问,每行包含一个正整数N. T<=5000,N<=10^7 题解: 求 $\sum_ ...

  4. centos7升级kernel之后,vmware无法打开

    12.57版本的vmware: https://my.vmware.com/group/vmware/details?downloadGroup=WKST-1257-LX&productId= ...

  5. 无缝轮播的案例 及css3无缝轮播案例

    无缝轮播的案例: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> < ...

  6. ruby中=>是什么意思

    如果是对数组赋值,下标 => 值例如 a = {1 => "1",2 => "22"}a[1] "1"a[2] " ...

  7. scrapy-redis源码浅析

    原文链接 前言 分析这个项目的源码原因是需要有去重过滤,增量爬取两个功能,而scrapy-redis项目已经帮我们实现了,想看看他是怎么实现的.这里只贴出部分主要代码,查看时请打开源码对照,笔记有点长 ...

  8. Nginx+Tomcat实现单IP、多域名、多站点的访问

    最近帮朋友做了两个网站,预算很小很小.小到两个网站只能跑在一台512M内存的公网服务器上(tomcat+MySQL,由于内存太小了,只能把两个网站部署在同一个tomcat上),每个网站有自己的域名,初 ...

  9. 在Python中操作文件之truncate()方法的使用教程

    在Python中操作文件之truncate()方法的使用教程 这篇文章主要介绍了在Python中操作文件之truncate()方法的使用教程,是Python入门学习中的基础知识,需要的朋友可以参考下 ...

  10. nessus 安装

    下载安装包: https://www.tenable.com/downloads/nessus 下载插件: https://docs.tenable.com/nessus/Content/Downlo ...