我的应用程序使用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日志记录,并且条件并没有显示在任何地方,就像它只是被忽略一样。
非常感谢任何帮助!
答案 0 :(得分:0)
所以,问题是我将@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,插入了null,代替了最终被过滤掉的东西(排除在外)。