Skip to content

Commit 5bbb969

Browse files
committed
Improving skills
1 parent 235ef8e commit 5bbb969

File tree

5 files changed

+50
-50
lines changed

5 files changed

+50
-50
lines changed

.cursor/rules/412-frameworks-quarkus-panache.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: 412-frameworks-quarkus-panache
3-
description: Use when you need data access with Quarkus Hibernate ORM Panache — including PanacheEntity / PanacheEntityBase, PanacheRepository, named and HQL queries, transactions, pagination, and immutable-friendly patterns. This is the Quarkus analogue to Spring Data for relational persistence; prefer Panache APIs over verbose persistence boilerplate. For Flyway-backed DDL and versioned schema changes, use `@413-frameworks-quarkus-db-migrations-flyway`.
3+
description: Use when you need data access with Quarkus Hibernate ORM Panache — including PanacheEntity / PanacheEntityBase, PanacheRepository, named queries, JPQL, native SQL, transactions, pagination, and immutable-friendly patterns. This is the Quarkus analogue to Spring Data for relational persistence; prefer Panache APIs over verbose persistence boilerplate. For Flyway-backed DDL and versioned schema changes, use `@413-frameworks-quarkus-db-migrations-flyway`.
44
license: Apache-2.0
55
metadata:
66
author: Juan Antonio Breña Moral
@@ -14,7 +14,7 @@ You are a Senior software engineer with extensive experience in Quarkus, Hiberna
1414

1515
## Goal
1616

17-
Panache simplifies Hibernate ORM in Quarkus: **active record** (`PanacheEntity`) for small entities or **repository** (`PanacheRepository`) for a cleaner separation. Prefer explicit queries (`find`, `list`, `HQL`) over magic lazy graphs; keep aggregates focused; use `@Transactional` on services. For hand-written SQL and reporting, use `@411-frameworks-quarkus-jdbc` instead of forcing everything through Panache. For schema evolution with Flyway, use `@413-frameworks-quarkus-db-migrations-flyway`.
17+
Panache simplifies Hibernate ORM in Quarkus: **active record** (`PanacheEntity`) for small entities or **repository** (`PanacheRepository`) for a cleaner separation. Prefer explicit queries (`find`, `list`, JPQL) over magic lazy graphs; keep aggregates focused; use `@Transactional` on services. Use native queries when you want SQL you control and still stay in Hibernate (transactions, same datasource, optional entity mapping). For hand-written SQL and reporting that should bypass Hibernate at the application boundary, use `@411-frameworks-quarkus-jdbc` instead of forcing everything through Panache. For schema evolution with Flyway, use `@413-frameworks-quarkus-db-migrations-flyway`.
1818

1919
## Constraints
2020

@@ -34,7 +34,7 @@ Before applying any recommendations, ensure the project is in a valid state by r
3434
- Example 1: Active record entity
3535
- Example 2: Panache repository
3636
- Example 3: Service layer transaction
37-
- Example 4: Parameterized HQL queries
37+
- Example 4: Parameterized JPQL queries
3838
- Example 5: DTO projections
3939
- Example 6: Pagination
4040
- Example 7: @NamedQuery for stable, reused queries
@@ -109,7 +109,7 @@ public class BookRepository implements PanacheRepository<Book> {
109109

110110
public List<Book> search(String userFragment) {
111111
return list("FROM Book WHERE title LIKE '" + userFragment + "%'");
112-
// injection risk — never concatenate user input into HQL
112+
// injection risk — never concatenate user input into JPQL
113113
}
114114
}
115115
```
@@ -159,10 +159,10 @@ public void publish(@PathParam("id") long id) {
159159
}
160160
```
161161

162-
### Example 4: Parameterized HQL queries
162+
### Example 4: Parameterized JPQL queries
163163

164164
Title: Positional and named parameters; firstResultOptional for single rows
165-
Description: Panache offers three levels of query syntax: field shorthand for simple equality, positional `?1` parameters, and full HQL with `Parameters.with(...)` for named bindings. Use `firstResultOptional()` for single-row lookups rather than `findById` when querying by non-PK columns. Never concatenate user input into query strings.
165+
Description: Panache offers three levels of query syntax: field shorthand for simple equality, positional `?1` parameters, and full JPQL with `Parameters.with(...)` for named bindings. Use `firstResultOptional()` for single-row lookups rather than `findById` when querying by non-PK columns. Never concatenate user input into query strings.
166166

167167
**Good example:**
168168

@@ -206,7 +206,7 @@ import java.util.List;
206206
public class BookRepository implements PanacheRepository<Book> {
207207

208208
public List<Book> searchByAuthor(String fragment) {
209-
// Bad: HQL injection risk — never build query strings from user input
209+
// Bad: query injection risk — never build query strings from user input
210210
return find("FROM Book WHERE author LIKE '%" + fragment + "%'").list();
211211
}
212212
}
@@ -335,7 +335,7 @@ public class BookRepository implements PanacheRepository<Book> {
335335
### Example 7: @NamedQuery for stable, reused queries
336336

337337
Title: Declare on the entity; invoke with # prefix; validated at startup
338-
Description: `@NamedQuery` declarations are parsed and validated by Hibernate at application startup, catching HQL errors early. Use them for frequently executed, stable queries to enable Hibernate's query plan caching and to centralise SQL intent near the entity it queries.
338+
Description: `@NamedQuery` declarations are parsed and validated by Hibernate at application startup, catching query parse errors early. Use them for frequently executed, stable queries to enable Hibernate's query plan caching and to centralise SQL intent near the entity it queries.
339339

340340
**Good example:**
341341

@@ -382,7 +382,7 @@ import java.util.List;
382382
@ApplicationScoped
383383
public class BookRepository implements PanacheRepository<Book> {
384384

385-
// Bad: inline HQL string is validated at runtime only —
385+
// Bad: inline JPQL string is validated at runtime only —
386386
// a typo in "plblished" is not caught until the query is first executed
387387
public List<Book> findPublishedByGenre(String genre) {
388388
return find("FROM Book WHERE genre = ?1 AND plblished = true ORDER BY title", genre).list();
@@ -392,8 +392,8 @@ public class BookRepository implements PanacheRepository<Book> {
392392

393393
### Example 8: JOIN FETCH to avoid N+1 queries
394394

395-
Title: Eagerly load associations in one HQL query instead of triggering lazy loads per entity
396-
Description: When a use case iterates a collection association on every returned entity, issuing N individual `SELECT` statements. Use `JOIN FETCH` in HQL to load the association in the same query. Outside of an open Hibernate session (e.g. serializing to JSON), lazy access throws `LazyInitializationException`.
395+
Title: Eagerly load associations in one JPQL query instead of triggering lazy loads per entity
396+
Description: When a use case iterates a collection association on every returned entity, issuing N individual `SELECT` statements. Use `JOIN FETCH` in JPQL to load the association in the same query. Outside of an open Hibernate session (e.g. serializing to JSON), lazy access throws `LazyInitializationException`.
397397

398398
**Good example:**
399399

@@ -614,7 +614,7 @@ class BookRepositoryTest {
614614

615615
## Output Format
616616

617-
- **ANALYZE** entities, repositories, and services for HQL injection risk, leaky entity boundaries, missing `@Transactional`, unbounded list queries, lazy N+1 patterns, missing `@Version`, and absence of test isolation
617+
- **ANALYZE** entities, repositories, and services for query injection risk, leaky entity boundaries, missing `@Transactional`, unbounded list queries, lazy N+1 patterns, missing `@Version`, and absence of test isolation
618618
- **CATEGORIZE** findings by impact (SECURITY for query injection, CORRECTNESS for missing transactions or N+1, PERFORMANCE for unbounded queries or missing pagination, MAINTAINABILITY for entity exposure at API boundaries)
619619
- **APPLY** improvements: introduce parameterized queries, `project(Class)` DTO projections, `page(Page.of(...))` pagination, `@NamedQuery` for stable queries, `JOIN FETCH` for needed associations, `@Version` for concurrency control
620620
- **IMPLEMENT** changes consistently: keep entity, service, and REST resource layers coherent; update test fixtures when entity shape changes
@@ -626,10 +626,10 @@ class BookRepositoryTest {
626626

627627
- **BLOCKING SAFETY CHECK**: ALWAYS run `./mvnw compile` before ANY Panache refactoring — compilation failure is a HARD STOP
628628
- **CRITICAL VALIDATION**: Run `./mvnw clean verify` after changes; confirm persistence tests pass with Dev Services before promoting
629-
- **QUERY SAFETY**: Never concatenate user input into HQL, PanacheQL, or native SQL — use `?1`, `:name`, or `Parameters.with(...)` exclusively
629+
- **QUERY SAFETY**: Never concatenate user input into JPQL, PanacheQL, or native SQL — use `?1`, `:name`, or `Parameters.with(...)` exclusively
630630
- **ENTITY BOUNDARIES**: Do not return managed entities directly from REST resources — map to DTOs or use `project(Class)` to keep API contracts stable and prevent accidental field exposure
631631
- **PAGINATION**: Never call `listAll()` or an unbound `list(query)` on production tables — always apply `.page(Page.of(index, size))` or a LIMIT clause
632-
- **N+1 PREVENTION**: When a use case accesses collection associations on every returned entity, add `JOIN FETCH` to the HQL query; lazy access outside a Hibernate session throws `LazyInitializationException`
632+
- **N+1 PREVENTION**: When a use case accesses collection associations on every returned entity, add `JOIN FETCH` to the JPQL query; lazy access outside a Hibernate session throws `LazyInitializationException`
633633
- **OPTIMISTIC LOCKING**: Adding `@Version` to an existing entity requires a `version` column in the schema — apply via a migration (`@413-frameworks-quarkus-db-migrations-flyway`) before deploying; mismatched schema causes startup failure
634634
- **CDI SELF-INVOCATION**: Never call a `@Transactional` method via `this.method()` within the same CDI bean — the interceptor is bypassed; extract to a separate injected bean
635635
- **INCREMENTAL SAFETY**: Change one entity, repository, or service at a time; verify with `@QuarkusTest` + `@TestTransaction` between steps; do not combine aggregate boundary changes with query refactoring in one commit

skills-generator/src/main/resources/skills/412-skill.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<version>0.13.0</version>
88
<license>Apache-2.0</license>
99
<description><![CDATA[
10-
Use when you need data access with Quarkus Hibernate ORM Panache — including PanacheEntity / PanacheEntityBase, PanacheRepository, named and HQL queries, DTO projections (project(Class)), pagination (Page.of()), N+1 avoidance (JOIN FETCH), optimistic locking (@Version / OptimisticLockException), @NamedQuery for validated reusable queries, transactions, @TestTransaction for test isolation, and immutable-friendly patterns. This is the Quarkus analogue to Spring Data for relational persistence.
10+
Use when you need data access with Quarkus Hibernate ORM Panache — including PanacheEntity / PanacheEntityBase, PanacheRepository, named queries, JPQL, native SQL, DTO projections (project(Class)), pagination (Page.of()), N+1 avoidance (JOIN FETCH), optimistic locking (@Version / OptimisticLockException), @NamedQuery for validated reusable queries, transactions, @TestTransaction for test isolation, and immutable-friendly patterns. This is the Quarkus analogue to Spring Data for relational persistence.
1111
]]>
1212
</description>
1313
</metadata>
@@ -19,16 +19,16 @@ Apply Panache patterns for Hibernate ORM in Quarkus.
1919
**What is covered in this Skill?**
2020
2121
- Active record (PanacheEntity) vs PanacheRepository — when to use each
22-
- Parameterized HQL / Panache queries: positional (?1) and named (:param) — no unsafe concatenation
22+
- Parameterized JPQL / Panache queries: positional (?1) and named (:param) — no unsafe concatenation
2323
- @NamedQuery on entities for reusable, build-time validated queries
2424
- DTO projections with project(Class) to avoid exposing managed entities
2525
- Pagination with Page.of(pageIndex, pageSize) and query.count()
26-
- N+1 avoidance with JOIN FETCH in HQL queries
26+
- N+1 avoidance with JOIN FETCH in JPQL queries
2727
- Optimistic locking with @Version and handling OptimisticLockException
2828
- @Transactional application services
2929
- @TestTransaction for automatic rollback in @QuarkusTest tests
3030
- Mapping entities vs exposing DTOs at REST boundaries
31-
- Pairing with `@411` for raw SQL when needed
31+
- Native queries via Hibernate when you want controlled SQL in the same transaction; pairing with `@411` for JDBC when bypassing Hibernate at the boundary
3232
3333
**Scope:** Apply recommendations based on the reference rules and good/bad code examples.
3434
]]></goal>

skills/412-frameworks-quarkus-panache/SKILL.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: 412-frameworks-quarkus-panache
3-
description: Use when you need data access with Quarkus Hibernate ORM Panache — including PanacheEntity / PanacheEntityBase, PanacheRepository, named and HQL queries, DTO projections (project(Class)), pagination (Page.of()), N+1 avoidance (JOIN FETCH), optimistic locking (@Version / OptimisticLockException), @NamedQuery for validated reusable queries, transactions, @TestTransaction for test isolation, and immutable-friendly patterns. This is the Quarkus analogue to Spring Data for relational persistence. Part of the skills-for-java project
3+
description: Use when you need data access with Quarkus Hibernate ORM Panache — including PanacheEntity / PanacheEntityBase, PanacheRepository, named queries, JPQL, native SQL, DTO projections (project(Class)), pagination (Page.of()), N+1 avoidance (JOIN FETCH), optimistic locking (@Version / OptimisticLockException), @NamedQuery for validated reusable queries, transactions, @TestTransaction for test isolation, and immutable-friendly patterns. This is the Quarkus analogue to Spring Data for relational persistence. Part of the skills-for-java project
44
license: Apache-2.0
55
metadata:
66
author: Juan Antonio Breña Moral
@@ -13,16 +13,16 @@ Apply Panache patterns for Hibernate ORM in Quarkus.
1313
**What is covered in this Skill?**
1414

1515
- Active record (PanacheEntity) vs PanacheRepository — when to use each
16-
- Parameterized HQL / Panache queries: positional (?1) and named (:param) — no unsafe concatenation
16+
- Parameterized JPQL / Panache queries: positional (?1) and named (:param) — no unsafe concatenation
1717
- @NamedQuery on entities for reusable, build-time validated queries
1818
- DTO projections with project(Class) to avoid exposing managed entities
1919
- Pagination with Page.of(pageIndex, pageSize) and query.count()
20-
- N+1 avoidance with JOIN FETCH in HQL queries
20+
- N+1 avoidance with JOIN FETCH in JPQL queries
2121
- Optimistic locking with @Version and handling OptimisticLockException
2222
- @Transactional application services
2323
- @TestTransaction for automatic rollback in @QuarkusTest tests
2424
- Mapping entities vs exposing DTOs at REST boundaries
25-
- Pairing with `@411` for raw SQL when needed
25+
- Native queries via Hibernate when you want controlled SQL in the same transaction; pairing with `@411` for JDBC when bypassing Hibernate at the boundary
2626

2727
**Scope:** Apply recommendations based on the reference rules and good/bad code examples.
2828

0 commit comments

Comments
 (0)