使用 P6Spy 攔截 SQL 日誌記錄
一、簡介
在本教程中,我們將討論P6Spy ,這是一個開放源代碼的免費庫,可用於攔截 Java 應用程序中的 SQL 日誌。
在本文的第一部分,我們將討論依賴這個外部庫而不是僅僅為 JPA 或 Hibernate 啟用 SQL 日誌記錄的主要優勢,以及我們可以將庫集成到我們的應用程序中的不同方式。然後我們將展示一個使用 P6Spy 的 Spring Boot 應用程序的簡單示例,以查看一些最重要的可用配置。
2. P6Spy安裝
P6Spy需要安裝在應用服務器上。通常,將應用程序 JAR 放在類路徑中並方便地配置驅動程序和 JDBC 連接就足夠了。
使用 P6Spy 的另一種方法是通過與我們應用程序的現有代碼集成,假設對代碼進行小的更改是可以接受的。在下一節中,我們將看到一個示例,說明如何通過自動配置將 P6Spy 集成到 Spring Boot 應用程序中。
[p6spy-spring-boot-starter](https://mvnrepository.com/artifact/com.github.gavlyukovskiy/p6spy-spring-boot-starter)
是一個存儲庫,提供與 P6Spy 和其他數據庫監控庫的集成。多虧了這個庫,啟用 P6Spy 日誌記錄就像在類路徑上添加一個jar
一樣簡單。使用 Maven,只需在POM.xml:
<dependency>
<groupId>com.github.gavlyukovskiy</groupId>
<artifactId>p6spy-spring-boot-starter</artifactId>
<version>1.9.0</version>
</dependency>
如果我們要配置日誌記錄,我們需要在資源文件夾中添加一個名為“spy.properties”
的文件:
appender=com.p6spy.engine.spy.appender.FileLogger
logfile=database.log
append=true
logMessageFormat=com.p6spy.engine.spy.appender.CustomLineFormat
customLogMessageFormat=%(currentTime)|%(executionTime)|%(category)|%(sqlSingleLine)
在這種情況下,我們已將 P6Spy 配置為以自定義格式以附加模式將信息記錄在名為“database.log”
的文件中。這些只是一些配置;其他的記錄在項目網站上。
3. 日誌示例
要查看日誌記錄,我們需要運行一些查詢。讓我們向我們的應用程序添加幾個簡單的端點:
@RestController
@RequestMapping("student")
public class StudentController {
@Autowired
private StudentRepository repository;
@RequestMapping("/save")
public Long save() {
return repository.save(new Student("Pablo", "Picasso")).getId();
}
@RequestMapping("/find/{name}")
public List<Student> getAll(@PathVariable String name) {
return repository.findAllByFirstName(name);
}
}
假設應用程序在端口 8080 上公開,現在讓我們使用 CURL 訪問這些端點:
curl http://localhost:8080/student/save
curl http://localhost:8080/student/find/Pablo
我們現在可以看到在項目目錄中創建了一個名為“ database.log
”的文件,其內容如下:
1683396972301|0|statement|select next value for student_seq
1683396972318|0|statement|insert into student (first_name, last_name, id) values ('Pablo', 'Picasso', 1)
1683396972320|0|commit|
1683396990989|0|statement|select s1_0.id,s1_0.first_name,s1_0.last_name from student s1_0 where s1_0.first_name='Pablo'
如果我們使用PreparedStatements
並手動管理commits
和rollbacks
,日誌記錄也將起作用。讓我們在應用程序中添加另一個控制器來測試此行為:
@RestController
@RequestMapping("jdbc")
public class JDBCController {
@Autowired
private DataSource dataSource;
@RequestMapping("/commit")
public List<Map<String, String>> select() {
List<Map<String, String>> results = new ArrayList<>();
try {
Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement();
statement.executeQuery("SELECT * FROM student");
} catch (Exception e) {
throw new IllegalStateException(e);
}
return results;
}
@RequestMapping("/rollback")
public List<Map<String, String>> rollback() {
List<Map<String, String>> results = new ArrayList<>();
try (Connection connection = dataSource.getConnection()) {
connection.rollback();
} catch (Exception e) {
throw new IllegalStateException(e);
}
return results;
}
@RequestMapping("/query-error")
public void error() {
try (Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement()) {
statement.execute("SELECT UNDEFINED()");
} catch (Exception ignored) {
}
}
}
然後,因此,我們使用 curl 請求訪問了以下端點:
curl http://localhost:8080/jdbc/commit
curl http://localhost:8080/jdbc/rollback
curl http://localhost:8080/jdbc/query-error
結果,我們將在“ database.log
”文件中看到以下日誌:
1683448381083|0|statement|SELECT * FROM student
1683448381087|0|commit|
1683448386586|0|rollback|
1683448388604|3|statement|SELECT UNDEFINED()
4。結論
在本文中,我們看到了依賴外部第三方庫(例如 P6Spy)來記錄數據庫查詢的多種優勢。例如,我們嘗試過的特殊配置使我們擺脫了嘈雜的鄰居問題(想像一下充滿查詢的日誌控制台)。
與往常一樣,代碼可在 GitHub 上獲得。