【问题标题】:Hibernate @Filter collection of enumsHibernate @Filter 枚举集合
【发布时间】:2015-10-14 08:53:36
【问题描述】:

我需要弄清楚如何使用定义为的枚举参数列表应用基于注释的过滤:

@Column(name = "target_status")
@Enumerated(EnumType.STRING)
@Type(type="PGEnumConverter", parameters = {
    @Parameter(name = "enumClassName",
               value = "com.company.model.campaign.CampaignTarget$Status")
})
private Status targetStatus;

所以我的@FilterDef 看起来像这样:

    @FilterDef(name="filterCampaignTargetByStatuses",
               defaultCondition="target_status in (:statuses)",
               parameters = @ParamDef(name = "statuses", type = "string"))

当我启用过滤器时,它看起来像这样:

    session.enableFilter("filterCampaignTargetByStatuses").
    setParameterList("statuses", statuses);

我从休眠中得到的错误是:

 org.hibernate.HibernateException: Incorrect type for parameter [statuses]

数据在PostgreSQL中,类型定义:

CREATE TYPE statuscmp AS ENUM ('ACTIVE','INACTIVE','PAUSED','DRAFT','SCHEDULED','ENDED','ARCHIVED');

我已经看到很多关于如何针对单个 Enum 值进行条件查询和过滤的 SO 问题,但还没有关于过滤 set 枚举值的问题。有没有办法显式转换单个值?

【问题讨论】:

    标签: java hibernate postgresql enums


    【解决方案1】:

    一般情况下,您不必“强制转换”值,实际上您只需以它们存储的形式传递值。

    如果我们假设您的字段仅注释为 @Enumerated(EnumType.STRING),则该列将是一个普通的 varchar 字段。 (将 java 类型映射到 postgres 枚举是另一个大话题。)

    如果您现在想将 Status 枚举实例列表与数据库中的相关字符串值进行比较,请将其作为字符串集合传递,换句话说,如果它是 java enum,则调用它的 toString() 方法.

    例如这是你的枚举:

    public enum EntityStatus {
        A, B, C;
    }
    

    这是你的实体:

    import javax.persistence.Entity;
    import javax.persistence.EnumType;
    import javax.persistence.Enumerated;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    
    import org.hibernate.annotations.Filter;
    import org.hibernate.annotations.FilterDef;
    import org.hibernate.annotations.ParamDef;
    
    @Entity
    @FilterDef(name = "byMultipleStates", defaultCondition = "status in (:states)", parameters = @ParamDef(name = "states", type = "string"))
    @Filter(name = "byMultipleStates", condition = "status in (:states)")
    public class StatusEntity {
    
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private long id;
    
        @Enumerated(EnumType.STRING)
        private EntityStatus status;
    
        public long getId() {
            return id;
        }
    
        public EntityStatus getStatus() {
            return status;
        }
    
        public void setStatus(EntityStatus status) {
            this.status = status;
        }
    
    }
    

    这可能是您要过滤的代码:

    public List<StatusEntity> filterByStates(final Set<EntityStatus> states) {
        final Session hibernateSession = entityManager.unwrap(Session.class);
        hibernateSession.enableFilter("byMultipleStates").setParameterList("states",
                states.stream().map(state -> state.toString()).collect(Collectors.toList()));
        final Query query = hibernateSession.createQuery("SELECT e FROM StatusEntity e");
    
        return query.list();
    }
    

    或者在 Java 8 之前的方式:

    public List<StatusEntity> filterByStates(final Set<EntityStatus> states) {
        final Set<String> statesAsString = new HashSet<>();
        for (final EntityStatus state : states) {
            statesAsString.add(state.toString());
        }
    
        final Session hibernateSession = entityManager.unwrap(Session.class);
        hibernateSession.enableFilter("byMultipleStates").setParameterList("states", statesAsString);
        final Query query = hibernateSession.createQuery("SELECT e FROM StatusEntity e");
    
        return query.list();
    }
    

    所以只过滤一组值是可能的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-25
      • 2011-04-09
      • 1970-01-01
      • 2012-02-18
      • 2019-06-08
      • 1970-01-01
      • 2020-08-10
      相关资源
      最近更新 更多