NativeQueryHandler#

com.palmyralabs.palmyra.handlers.NativeQueryHandler

Use when annotation-driven queries aren’t expressive enough. You supply the SQL; Palmyra still handles result streaming, filtering, and row mapping through onQueryResult.

Methods#

Method Signature
aclCheck int aclCheck(FilterCriteria criteria, HandlerContext ctx)
getQuery (abstract) NativeQuery getQuery(FilterCriteria criteria, HandlerContext ctx)
preProcess void preProcess(FilterCriteria criteria, HandlerContext ctx)
onQueryResult Tuple onQueryResult(Tuple tuple, Action action)

NativeQuery#

Package: com.zitlab.palmyra.store. Implements QueryOptions, CountQuery.

Methods#

Method Signature
getQuery / setQuery String getQuery() · void setQuery(String query)
getParams / setParams List<Object> getParams() · void setParams(List<Object> params)
addParams void addParams(Object param) · void addParams(Object... params)
clearParam void clearParam()
hasParams boolean hasParams()
getCountQuery / setCountQuery String getCountQuery() · void setCountQuery(String countQuery)
getFetchSize / setFetchSize int getFetchSize() · void setFetchSize(int fetchSize) — default 100
getLimit / setLimit int getLimit() · void setLimit(int limit)
getOffset / setOffset int getOffset() · void setOffset(int offset)
limitFirst void limitFirst()

params are positional ? placeholders (JDBC-style), not named parameters — bind them in order with addParams(...) or the vararg constructor. Set countQuery when you need an accurate total for pagination that differs from a naive COUNT(*) over the main query.

Example#

@Component
@CrudMapping("/v1/reports/user-sales")
public class UserSalesNativeHandler implements NativeQueryHandler {

    @Autowired
    private UserProvider userProvider;

    @Override
    public int aclCheck(FilterCriteria criteria, HandlerContext ctx) {
        return userProvider.hasRole("REPORT_VIEW") ? 0 : -1;
    }

    @Override
    public void preProcess(FilterCriteria criteria, HandlerContext ctx) {
        // ensure the 'since' parameter is present and well-formed
        if (criteria.getAttribute("since") == null) {
            criteria.addAttribute("since", Instant.now().minus(30, ChronoUnit.DAYS));
        }
    }

    @Override
    public NativeQuery getQuery(FilterCriteria criteria, HandlerContext ctx) {
        String sql = """
            SELECT u.id, u.name, SUM(o.amount) total
            FROM users u JOIN orders o ON o.user_id = u.id
            WHERE o.created_at >= ?
            GROUP BY u.id, u.name
        """;
        NativeQuery q = new NativeQuery(sql, criteria.getAttribute("since"));
        q.setCountQuery("""
            SELECT COUNT(DISTINCT u.id)
            FROM users u JOIN orders o ON o.user_id = u.id
            WHERE o.created_at >= ?
        """);
        q.setFetchSize(500);
        return q;
    }

    @Override
    public Tuple onQueryResult(Tuple tuple, Action action) {
        // round totals to 2 decimals before returning
        BigDecimal total = (BigDecimal) tuple.get("total");
        if (total != null) tuple.set("total", total.setScale(2, RoundingMode.HALF_UP));
        return tuple;
    }
}