Quick Start¶
What you'll learn
How to add @QueryAudit to a test, trigger real detections (N+1, missing index, batch insert), read the report, and fix the issues.
This guide walks you through adding QueryAudit to a Spring Boot test, triggering real detections, and reading the report.
The Simplest Example¶
If you just want to see QueryAudit in action, this is all you need:
@SpringBootTest
@QueryAudit
class MyServiceTest {
@Autowired
private MyService myService;
@Test
void myMethod_shouldNotHaveQueryIssues() {
myService.doSomething();
// That's it. QueryAudit analyzes every SQL query executed above
// and fails the test if it finds performance anti-patterns.
}
}
No configuration. No extra beans. No proxy setup. Just the annotation.
Full Walkthrough¶
Step 1: Add Dependencies¶
<dependency>
<groupId>io.github.haroya01</groupId>
<artifactId>query-audit-spring-boot-starter</artifactId>
<version>0.1.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.github.haroya01</groupId>
<artifactId>query-audit-mysql</artifactId>
<version>0.1.0</version>
<scope>test</scope>
</dependency>
Using PostgreSQL?
Replace query-audit-mysql with query-audit-postgresql. Everything else stays the same.
Step 2: Annotate Your Test¶
@SpringBootTest
@QueryAudit
class OrderServiceTest {
@Autowired
private OrderService orderService;
@Test
void findRecentOrders() {
List<Order> orders = orderService.findRecentOrders(10);
assertThat(orders).isNotEmpty();
orders.forEach(order -> {
// This triggers lazy loading -- each order fires a separate
// SELECT to fetch its items. Classic N+1 problem.
assertThat(order.getItems()).isNotNull();
});
}
}
No other changes needed
You don't need to change your DataSource, add a proxy bean, or modify application.yml. The @QueryAudit annotation handles everything.
Step 3: Run Your Tests¶
QueryAudit automatically:
- Intercepts every SQL query (SELECT, INSERT, UPDATE, DELETE) executed during the test
- Collects index metadata via
SHOW INDEX(MySQL) orpg_catalog(PostgreSQL) from your test database - Applies 57 detection rules to the captured queries
- Prints a report to the console output
- Fails the test if confirmed issues are found (configurable)
Step 4: Read the Report¶
================================================================================
QUERY AUDIT REPORT
OrderServiceTest (12 queries analyzed)
================================================================================
CONFIRMED ISSUES (action required)
────────────────────────────────────────────────────────────────────────────────
[ERROR] N+1 Query Detected
Repeated query: select * from order_items where order_id = ?
Executions: 10 times (threshold: 3)
Source: com.example.OrderService.findRecentOrders:42
Suggestion: Use JOIN FETCH or @EntityGraph to load order_items
with the parent query.
[ERROR] Missing Index on WHERE column
Query: select * from order_items where order_id = ?
Table: order_items
Column: order_id
Suggestion: CREATE INDEX idx_order_items_order_id
ON order_items (order_id);
[WARNING] Repeated single-row INSERT should use batch insert
Query: insert into audit_log (action, entity_id, ...) values (?, ?, ...)
Table: audit_log
Detail: Single-row INSERT executed 10 times on table 'audit_log'.
Suggestion: Use batch INSERT (saveAll() in JPA with hibernate.jdbc.batch_size).
────────────────────────────────────────────────────────────────────────────────
INFO (for review)
────────────────────────────────────────────────────────────────────────────────
[WARNING] SELECT * Usage
Query: select * from orders where created_at > ?
Table: orders
Suggestion: List only the columns you need
================================================================================
3 confirmed issues | 1 info | 12 queries
================================================================================
Understanding the Sections¶
CONFIRMED Issues (ERROR / WARNING)¶
These are structural problems that will cause performance degradation at scale. They are verified by SQL pattern analysis and index metadata cross-referencing.
| Severity | Meaning | Action |
|---|---|---|
| ERROR | Critical -- logic bugs, full table locks, N+1 | Must fix before merge |
| WARNING | Important -- missing indexes, inefficient patterns | Should fix |
INFO Items¶
Best-practice suggestions. Won't fail your build by default.
You can promote INFO to CONFIRMED
Change severity in the configuration. See Configuration.
Step 5: Fix the Issues¶
Fix N+1 Query¶
// Before: lazy loading causes N+1
@Query("SELECT o FROM Order o WHERE o.createdAt > :date")
List<Order> findRecentOrders(@Param("date") LocalDateTime date);
// After: JOIN FETCH loads items in a single query
@Query("SELECT o FROM Order o JOIN FETCH o.items WHERE o.createdAt > :date")
List<Order> findRecentOrders(@Param("date") LocalDateTime date);
Fix Missing Index¶
Fix Repeated Single INSERT¶
More Annotations¶
Once you're comfortable with @QueryAudit, explore the 4 annotations:
| Annotation | Use when... |
|---|---|
@QueryAudit | You want full analysis with test failure on issues |
@EnableQueryInspector | You want report-only mode (same as @QueryAudit(failOnDetection = false)) |
@DetectNPlusOne | You only care about N+1 patterns |
@ExpectMaxQueryCount(5) | You want to enforce a query budget |
Next Steps¶
- Spring Boot Integration -- Auto-configuration details and
application.ymloptions - Annotations Guide -- All 4 annotations and when to use each
- Configuration -- Tune thresholds, suppress issues
- Detection Rules -- All 57 detection rules explained