Hibernate @Filter 枚举集合

8

我需要找出如何使用基于注解的过滤器,其中参数列表是枚举类型定义为:

@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);

我收到来自 Hibernate 的错误信息:

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

数据存储在PostgreSQL中,该类型的定义如下:
CREATE TYPE statuscmp AS ENUM ('ACTIVE','INACTIVE','PAUSED','DRAFT','SCHEDULED','ENDED','ARCHIVED');

我看到很多关于如何对单个枚举值进行条件查询和过滤的SO问题,但还没有关于在一组枚举值上进行过滤的问题。是否有一种方法可以显式地转换单个值?

1个回答

1

一般情况下,你不需要将值转换类型,实际上,你只需按照它们存储的形式传递这些值即可。

如果我们假设你的字段只有 @Enumerated(EnumType.STRING) 这个注解,那么该列就是一个简单的 varchar 字段。 (将一个 Java 类型映射到 PostgreSQL 枚举类型是另一个大话题。)

如果现在你想要将你的 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();
}

所以只需过滤值的集合即可。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接