You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否结合Hibernate Criteria API使用@PostLoad注解?

Can we use @PostLoad with Hibernate Criteria API?

Short answer: No, you can't directly use a transient property populated via @PostLoad in Hibernate Criteria API queries — here's why and what you can do instead.

Why your @PostLoad approach throws an error

The error org.hibernate.QueryException: could not resolve property: start of: com.entity.EntityExample occurs because:

  • Your start field is marked @Transient, which tells Hibernate it’s not mapped to any database column and shouldn’t be tracked as a queryable property.
  • The Criteria API builds queries by translating property references into database-level SQL. Since start doesn’t exist in the database (and Hibernate doesn’t recognize it as a valid query target), it can’t resolve the field when constructing the query.

In contrast, @Formula works because Hibernate treats the annotated property as a virtual derived column. It embeds the formula’s SQL expression directly into the generated query, so the database computes the value during the query itself — that’s why the Criteria API can resolve it without issues.

Solutions to work around this

Option 1: Filter in memory (small datasets only)

If you want to keep using @PostLoad, fetch all entities first then filter the transient property in your application code. Note this is only feasible for small datasets, as fetching all rows can hurt performance with large volumes:

public Collection<EntityExample> get(String start) {
    Session session = getSession();
    Criteria criteria = session.createCriteria(EntityExample.class, "entity");
    // Fetch all entities from the database
    List<EntityExample> allEntities = criteria.list();
    // Filter using the @PostLoad-populated start property
    return allEntities.stream()
        .filter(entity -> !start.equals(entity.getStart()))
        .collect(Collectors.toList());
}

Option 2: Make @Formula maintenance-friendly

To avoid manual updates to the @Formula value when refactoring underlying columns, centralize the expression logic:

  1. Define the formula as a static constant in your entity class, so you only update it once if columns change:
@Entity
public class EntityExample {
    private static final String START_COMPUTATION = "start_year::text || start_period::text";

    private Integer startYear;
    private Integer startPeriod;

    @Formula(value = START_COMPUTATION)
    private String start;

    // Getters and setters
}
  1. Alternatively, create a database view that includes the computed start column, then map your entity to the view instead of the base table. This centralizes the logic in the database, so refactoring table columns only requires updating the view.

Option 3: Use HQL with inline computation

If you don’t want to use @Formula, write an HQL query that computes the start value directly in the query (mirroring how @Formula works):

public Collection<EntityExample> get(String start) {
    Session session = getSession();
    String hql = "FROM EntityExample e WHERE CONCAT(e.startYear, e.startPeriod) != :start";
    Query query = session.createQuery(hql);
    query.setParameter("start", start);
    return query.list();
}

This way, the computation happens in the database, and you don’t rely on @PostLoad for query filtering.

内容的提问来源于stack exchange,提问作者rogerio_gentil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:58:15