怎样在控制台或者日志打印输出JDBC执行的sql语句

在使用JDBC prepareStatement执行SQL时,为了调试,通常需要将SQL及参数打印到控制台或日志。原始方法是手动获取并打印,但当参数较多时变得繁琐。本文介绍了如何利用反射机制简化这一过程,通过反射获取参数值并输出,同时提醒在使用预编译语句时注意参数顺序与POJO属性顺序的一致性,以避免赋值错误。

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

今天用jdbc preparestatement 写sql语句查询,但是在执行的过程中实际查询出的结果和预期的结果不一致,然后就在想有什么办法能够在控制台或者Log4j日志输出最终执行的SQL语句,以便于调试。如果是hibernate可以通过配置show_sql 为 true 在控制台显示执行的SQL,因为使用的是纯JDBC的写法,然后自己在程序中直接通过System.out.println(sql);打印SQL语句,然后又打印参数,这种方式确实是可以。但是,遇到insert语句或者Update语句的时候,因为实际操作中需要传入的匹配参数有点多,然后通过System.out.println()这种方式写的就有点多了,十几个参数就需要写十几行,然后就在想,能不能通过什么方式进行简化一下。。。

/**
     * 显示SQL语句
     * @param sql
     * @param paramMap
     */
    public static void show_sql(Logger log,String sql,List<String> paramList){
        log.info("##sql:{}",sql);
        log.info("##参数:{}",JSONArray.fromObject(paramList));

        /*if(null != paramList && paramList.size() > 0){
            for (int i = 0; i < paramList.size(); i++) {
                log.info(""+i+" : "+paramList.get(i));
            }
        }*/
    }

最原始的方法,直接一个一个取:

//输出SQL语句
            paramList.add(officeUserInfo.getUsername());
            paramList.add(officeUserInfo.getPassword());
            paramList.add(officeUserInfo.getCust_name());
            paramList.add(officeUserInfo.getMobile());
            paramList.add(String.valueOf(officeUserInfo.getState()));
            paramList.add(officeUserInfo.getOffice_id());
            paramList.add(String.valueOf(officeUserInfo.getRole()));
            paramList.add(officeUserInfo.getTel());
            paramList.add(officeUserInfo.getLeadPerson());
            paramList.add(officeUserInfo.getMobile2());
            paramList.add(officeUserInfo.getTel2());
            paramList.add(officeUserInfo.getContact());
            paramList.add(officeUserInfo.getQq());
            paramList.add(officeUserInfo.getFex());
            paramList.add(officeUserInfo.getAddr());
            paramList.add(officeUserInfo.getAddr2());
            paramList.add(officeUserInfo.getCust_tax_code());
            paramList.add(officeUserInfo.getIdcard_no());
            paramList.add(officeUserInfo.getSws());
            paramList.add(officeUserInfo.getSsfj());
            paramList.add(String.valueOf(officeUserInfo.getUserType()));
            paramList.add(officeUserInfo.getCreate_user());
            paramList.add(officeUserInfo.getUpdate_user());
            paramList.add(officeUserInfo.getCreate_time());
            paramList.add(officeUserInfo.getUpdate_time());
            CommonUtil.show_sql(log, sql, paramList);

然后这种方式就有点伤,虽然比较笨挫,但是确实是有效的方式,之后又想起了前段时间刚刚学习的反射机制,突然意识到好像可以通过Java反射机制直接get取值,然后上面的代码就可以简化成下面的,关于反射机制在前一篇博客中已经有过介绍,这里也是直接调用的那个反射工具类中封装的取值方法:

Java学习之反射机制 :
http://blog.youkuaiyun.com/hu1991die/article/details/43793931

利用反射取值:

//通过反射取值
            Map<String, String> getFieldValueMap = ClassRefUtil.getFieldValueMap(officeUserInfo);
            for (Entry<String, String> entry : getFieldValueMap.entrySet()) {
                //因为返回的是一个Map类型的集合,然后需要对这个集合进行迭代,然后将值装载到paramList中,最后日志循环输出
                paramList.add(entry.getValue());
            }
            CommonUtil.show_sql(log, sql, paramList);

输出结果:

这里写图片描述

最后的输出结果和上面的是一致的,上面的其实也可以直接循环输出通过反射取值后返回的map类型的集合,因为前面有很多地方都用到了paramList,然后参数都是放在paramList中的,所以感觉这个地方多此一举了,本来直接就可以通过遍历map集合输出结果,而这里还要先从map集合中遍历出来,然后装进list中,然后又遍历list输出最终结果,,,因为前面很多地方都用到了,所以这个地方就没有改过来。

例子:

这里写图片描述

输出结果:

这里写图片描述

下面是改进之后的,直接使用map存参数就可以了。

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

然后下面的这种insert语句,通过PrepareStatement预编译方式赋值的时候,其实也是可以通过这种反射取值的方式,循环赋值,不过,这个地方好像需要注意一点:insert语句中的?的顺序必须要和POJO类中定义的属性的顺序应该要完全一致才可以,不然就有可能赋值的时候会出现匹配不正确的情况,有可能本来b位置的值赋给了a,那就伤大了,我想那些框架(如Hibernate等)应该都是通过反射进行处理的,具体是怎么处理的我现在还不知道,改天去研究研究。。

这里写图片描述

在Spring Boot应用中,可以通过在application.yml文件中配置,实现打印JDBCSQL语句的功能,并且格式化输出到控制台。 具体的实现步骤如下: 1. 在application.yml文件中,配置以下信息: ```yaml spring: datasource: url: jdbc:mysql://localhost:3306/test username: root password: root driver-class-name: com.mysql.jdbc.Driver # 打印SQL语句 # 可选的值:NONE、CONSOLE、LOG_FILE、LOG_FILE_AND_CONSOLE # 默认值:NONE datasource: type: com.alibaba.druid.pool.DruidDataSource # 配置Druid数据源,可以省略 druid: initial-size: 5 max-active: 20 min-idle: 5 max-wait: 60000 pool-prepared-statements: true max-pool-prepared-statement-per-connection-size: 20 validation-query: SELECT 1 test-on-borrow: true test-while-idle: true time-between-eviction-runs-millis: 60000 min-evictable-idle-time-millis: 300000 filters: stat,wall,log4j connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 # 配置日志级别为DEBUG,打印SQL语句 # 可以使用logging.level.org.springframework.jdbc.core.JdbcTemplate=DEBUG代替 logging: level: org: springframework: jdbc: core: JdbcTemplate: DEBUG # 配置输出到控制台,并格式化输出SQL语句 pattern: console: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" appender: console: target: SYSTEM_OUT encoder: pattern: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" ``` 其中,logging.level.org.springframework.jdbc.core.JdbcTemplate=DEBUG可以在application.yml中配置,也可以在log4j或logback等日志框架中配置。 2. 在代码中使用JdbcTemplate时,即可在控制台中看到打印SQL语句,例如: ```java @Autowired private JdbcTemplate jdbcTemplate; public void query() { List<Map<String, Object>> result = jdbcTemplate.queryForList("SELECT * FROM user"); //... } ``` 在控制台中会打印出格式化后的SQL语句,例如: ```java 2021-07-28 11:08:59.887 [main] DEBUG o.s.j.c.JdbcTemplate - Executing SQL query [SELECT * FROM user] ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值