Skip to content

Commit

Permalink
server/springboot: alter "list tickets" SQL query on the fly
Browse files Browse the repository at this point in the history
One learning is that we cannot rely on the "method name to SQL query"
magic that JPA supports -- rewriting queries using QueryRewriter only
works for JPQL or "native" (=dialect of the database) queries.

lmgty:
JPQL (Java Persistence Query Language) is a query language used to perform
database operations on entities defined in JPA (Java Persistence API). It
is similar to SQL but operates on the entity objects instead of the
database tables.

Signed-off-by: Stephan Renatus <[email protected]>
  • Loading branch information
srenatus committed Nov 5, 2024
1 parent b27e749 commit c867614
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,42 @@
package com.styra.tickethub_springboot.dao.model;

import com.styra.tickethub_springboot.App;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.jpa.repository.QueryRewriter;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface TicketRepository extends JpaRepository<Ticket, Integer> {
List<Ticket> findByTenant(Tenant tenant);
public interface TicketRepository
extends JpaRepository<Ticket, Integer>, QueryRewriter {
@Query(
value = "SELECT t.id, t.customer, t.description, t.last_updated, t.resolved, t.tenant FROM \"Tickets\" t LEFT JOIN \"Tenants\" t1 ON t1.id=t.tenant WHERE t1.name=:#{#tenant.name}",
nativeQuery = true,
queryRewriter = TicketRepository.class
)
List<Ticket> findByTenant(@Param("tenant") Tenant tenant);

List<Ticket> findByTenantAndId(Tenant tenant, Integer id);

@Override
default String rewrite(String query, Sort sort) {
// Omitted:
// 1. get conditions from OPA, after feeding it query and user information
// 2. convert conditions to SQL WHERE clause
//
// SQL logging uncovered **a lot** of queries happening for "list tickets".
// I'd assume that they're done automatically by Spring Data JPA, to ensure
// relationships etc; but it also means they are under the radar of this rewriter.
// However, I'd envision that there's one rewriter that would be used with all
// the repositories, so maybe we would end up covering call queries after all.
String rewritten = query + " AND t.resolved = false"; // leading space is crucial
Logger logger = LoggerFactory.getLogger(App.class);
logger.info("rewritten: " + rewritten);
return rewritten;
}
}
6 changes: 6 additions & 0 deletions server/springboot/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,9 @@ logging.level.com.styra.tickethub_springboot.dao.model=TRACE
# production, you probably shouldn't do this.
spring.security.user.name=demouser
spring.security.user.password=letmein

# dump all the SQL
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE

0 comments on commit c867614

Please sign in to comment.