Spring Boot中記錄JDBC、JPA及MyBatis執行SQL及參數的正確姿勢
環境:SpringBoot3.4.0
1. 簡介
在Spring Boot應用開發中,監控和記錄SQL執行語句對于調試、性能優化以及確保數據訪問層的正確性至關重要。無論是使用JDBC直接操作數據庫,還是通過JPA或MyBatis等ORM框架,他們都有不同的SQL語句的記錄方式。
本文將介紹在Spring Boot中使用JDBC、JPA及MyBatis進行數據庫操作時記錄執行的SQL語句。這些方法包括配置日志級別以捕獲SQL輸出、自定義數據源輸出SQL語句,以及使用第三方庫來增強SQL記錄的功能。
2. 實戰案例
2.1 JDBC記錄SQL
如下數據庫操作:
private final JdbcTemplate jdbcTemplate ;
public JdbcService(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void query() {
String sql = "select id, name, age from user x where x.id = ?" ;
User user = this.jdbcTemplate.queryForObject(sql, new RowMapper<User>() {
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
return new User(rs.getLong(1), rs.getString(2), rs.getString(3)) ;
}
}, 8) ;
System.err.printf("user = %s\n", user) ;
}
默認情況下,執行上面操作是不會輸出任何SQL語句的,我們可以通過如下的配置:
logging:
level:
'[org.springframework.jdbc.core.JdbcTemplate]': debug
圖片
如果你還希望輸出動態參數,則再添加如下日志配置:
logging:
level:
'[org.springframework.jdbc.core.StatementCreatorUtils]': trace
圖片
2.2 JPA記錄SQL
如下數據庫操作:
private final UserRepository userRepository ;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public User findById(Long id) {
return this.userRepository.findById(id).orElse(null) ;
}
最常見的輸出執行SQL方式
spring:
jpa:
show-sql: true
properties:
hibernate:
'[format_sql]': true
圖片
但是此種方式是直接通過System.out方式進行輸出,并且還不會記錄預處理語句的參數;不推薦此做法。
使用日志框架記錄
在application.yml或properties中進行日志的配置:
logging:
level:
'[org.hibernate.SQL]': debug
'[org.hibernate.orm.jdbc.bind]': trace
org.hibernate.SQL:記錄執行的SQL。
org.hibernate.orm.jdbc.bind:記錄預處理語句的參數。
圖片
2.3 MyBatis記錄SQL
如下數據庫操作:
@Select("select id, age, name, deleted from user where id = ${id}")
User queryUserById(@Param("id") Long id) ;
注意:${xx}有注入風險?我重寫了mybatis處理SQL的一個核心類,不再有任何注入風險。
比較常見的配置日志方式
mybatis:
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
如上配置日志輸出結果如下:
圖片
不僅僅輸出的是sql還將數據也輸出了,并且這里是通過System.out進行輸出的,并且還不管你是否配置的debug級別都會進行輸出,下面是源碼部分:
圖片
使用SLF4j日志實現
mybatis:
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
如上配置后并不會輸出sql日志,還需要進行如下的配置:
logging:
level:
'[com.pack.mapper]': DEBUG
2.4 萬能SQL記錄方式
使用攔截器是記錄各種SQL查詢的最佳方法。在這種方法中,我們可以攔截JDBC調用,對其進行格式化,然后以自定義格式記錄SQL查詢。
下面介紹一個第三方開源庫datasource-proxy,該組件用于攔截SQL查詢并記錄。
<dependency>
<groupId>com.github.gavlyukovskiy</groupId>
<artifactId>datasource-proxy-spring-boot-starter</artifactId>
<version>1.10.0</version>
</dependency>
日志級別配置如下:
logging:
level:
'[net.ttddyy.dsproxy.listener]': debug
這時候不論你使用JDBC,JPA還是MyBatis都能優雅的記錄SQL信息。
圖片