【问题标题】:Hibernate Filter being ignored休眠过滤器被忽略
【发布时间】:2016-08-31 19:53:48
【问题描述】:

我的应用程序使用 Hibernate 5.02 和 Wildfly 10 以及 PostgreSQL 9.5 数据库。我正在尝试对通过 NamedQuery 构造的实体中保存的 @OneToMany 集合启用过滤器。不幸的是,似乎过滤器被忽略了。以下是不同的组成部分,为便于阅读而进行了编辑。

@NamedNativeQueries({
@NamedNativeQuery(
        name = "getAnalystProcess",
        query = "SELECT * FROM analysis.analystprocess WHERE id = :processId",
        resultClass = AnalystProcessEntity.class
)})
@FilterDef(
    name = "analystProcessUnanalyzedMsgsFilter",
    parameters = { @ParamDef(name = "processIds", type = "integer"), @ParamDef(name = "analystIds", type = "integer") })
@Filter(name = "analystProcessUnanalyzedMsgsFilter", condition = "analystprocess_id IN (:processIds) AND id NOT IN (SELECT msg_id FROM analysis.analyzedmsg WHERE analyst_id IN (:analystIds) AND analystprocess_id IN (:processIds)) ORDER BY process_msg_id")
@Entity
@Table(name = "analystprocess", schema = "analyst")
public class AnalystProcessEntity implements JPAEntity {

public static final String GET_PROCESS = "getAnalystProcess";
public static final String MSG_FILTER = "analystProcessUnanalyzedMsgsFilter";
public static final String MSG_FILTER_PROC_ID_PARAM = "processIds";
public static final String MSG_FILTER_ANALYST_ID_PARAM = "analystIds";

private static final long serialVersionUID = 1L;

...

@OneToMany(fetch = FetchType.LAZY, orphanRemoval = true, mappedBy = "process")
@OrderColumn(name = "process_msg_id")
@LazyCollection(LazyCollectionOption.EXTRA)
private List<MsgEntity> msgList;

@Entity
@Table(name = "msg", schema = "analyst")
public class MsgEntity implements JPAEntity {

...

@ManyToOne(cascade = CascadeType.ALL, optional = false)
@JoinColumn(name = "analystprocess_id", referencedColumnName = "id")
private AnalystProcessEntity process;

@Column(name = "process_msg_id")
private Integer processMsgId;

private void buildAnalystProcess() {
    LOG.info("Building AnalystProcessEntity");
    analystUser.getJdbcSession().enableFilter(AnalystProcessEntity.MSG_FILTER)
                .setParameter(AnalystProcessEntity.MSG_FILTER_PROC_ID_PARAM, analystProcessId)
                .setParameter(AnalystProcessEntity.MSG_FILTER_ANALYST_ID_PARAM, analystUser.getId());

    Query query = analystUser.getJdbcSession().getNamedQuery(AnalystProcessEntity.GET_PROCESS)
            .setParameter("processId", analystProcessId);

//        Query query = analystUser.getJdbcSession().createNativeQuery("SELECT * FROM analysis.analystprocess WHERE id = :processId")
//                    .setParameter("processId", analystProcessId)
//                    .addEntity(AnalystProcessEntity.class);

    analystProcess = (AnalystProcessEntity) query.getSingleResult();

CREATE TABLE analysis.analystprocess (
        id SERIAL PRIMARY KEY,
        name TEXT NOT NULL UNIQUE,
        description TEXT,
        created_date TIMESTAMP NOT NULL DEFAULT now(),
        ...
);

CREATE TABLE analysis.msg (
        id SERIAL PRIMARY KEY,
        analystprocess_id INTEGER NOT NULL REFERENCES analysis.analystprocess(id) ON DELETE CASCADE ON UPDATE CASCADE,
        process_msg_id INTEGER NOT NULL,
        constraint tbl_statusid_analystprocessid unique(status_id, analystprocess_id)
);

如上所示,我还尝试了通过 createNativeQuery 而不是 getNamedQuery 构建 AnalystProcessEntity 类的过滤器,但没有运气。

我还在@FilterDef 中添加了一个带有硬编码值的 defaultCondition,只是为了查看它是否会执行默认条件,但它仍然没有。

我已经在实体定义和类定义上面尝试了@Filter。我什至遇到了一篇博客文章,它听起来像是条件引用实体字段(变量名)而不是表字段(列名)。试图在表中的 Entity 和 Postgres 命名约定中坚持 Java 命名约定,所以我尝试在条件中切换引用,但无济于事。

我在 Hibernate 中打开了 sql 日志记录,但条件没有出现在任何地方,就好像它只是被忽略了一样。

任何帮助将不胜感激!

【问题讨论】:

    标签: postgresql hibernate orm


    【解决方案1】:

    所以,问题在于我将 @FilterDef 应用于错误的类。我的假设是,因为我正在构建包含 MsgEntity 集合(我正在尝试过滤)的 AnalystProcessEntity,所以 @FilterDef 将应用于 AnalystProcessEntity 类。相反,它需要应用于它实际过滤的实体(事后看来是 20/20,这很明显)。

    此外,需要修改实际条件以在子选择查询中使用完整引用。

    我希望这对某人有所帮助...

    @NamedNativeQueries({
    @NamedNativeQuery(
            name = "getAnalystProcess",
            query = "SELECT * FROM analysis.analystprocess WHERE id = :processId",
            resultClass = AnalystProcessEntity.class
    )})
    @Filter(name = "analystProcessUnanalyzedMsgsFilter", condition = "id NOT IN (SELECT amsg.msg_id FROM analysis.analyzedmsg amsg WHERE amsg.analyst_id IN (:analystIds) AND amsg.analystprocess_id IN (:processIds))")
    @Entity
    @Table(name = "analystprocess", schema = "analyst")
    public class AnalystProcessEntity implements JPAEntity {
    
    public static final String GET_PROCESS = "getAnalystProcess";
    public static final String MSG_FILTER = "analystProcessUnanalyzedMsgsFilter";
    public static final String MSG_FILTER_PROC_ID_PARAM = "processIds";
    public static final String MSG_FILTER_ANALYST_ID_PARAM = "analystIds";
    
    private static final long serialVersionUID = 1L;
    
    ...
    
    @OneToMany(fetch = FetchType.LAZY, orphanRemoval = true, mappedBy = "process")
    @OrderColumn(name = "process_msg_id")
    @LazyCollection(LazyCollectionOption.EXTRA)
    private List<MsgEntity> msgList;
    

    @FilterDef(
        name = "analystProcessUnanalyzedMsgsFilter",
        parameters = { @ParamDef(name = "processIds", type = "integer"), @ParamDef(name = "analystIds", type = "integer") })
    @Entity
    @Table(name = "msg", schema = "analyst")
    public class MsgEntity implements JPAEntity {
    
    ...
    
    @ManyToOne(cascade = CascadeType.ALL, optional = false)
    @JoinColumn(name = "analystprocess_id", referencedColumnName = "id")
    private AnalystProcessEntity process;
    
    @Column(name = "process_msg_id")
    private Integer processMsgId;
    

    此外,我遇到了另一个问题,即 null 出现在集合中,尽管我使用的是 @OrderColumn,我认为它解决了这个问题。似乎通过使用@Filter,将插入空值来代替最终被过滤掉的内容(排除)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-04
      • 2011-12-11
      • 2011-10-18
      • 1970-01-01
      相关资源
      最近更新 更多