Seam EntityQuery多对多连接,独特和Oracle

时间:2011-07-21 03:44:36

标签: oracle many-to-many seam

我是一个已经建立的项目中的Seam新手,所以我使用的很多代码都是借用的,我并不总是完全确定它是如何工作的。我的问题是我使用从EntityQuery扩展的查询对象来支持具有搜索和排序功能的列表页面,该列表页面需要搜索多对多关系和单独的多对一关系,这些关系也必须用于分类。由于必须加入多对多关系以允许搜索功能,因此查询会为每个分配返回重复记录。这不是什么大不了的事,因为我只是在ejbql中添加了“distinct”,并且运行正常。但是,当我尝试通过其他多对一关系进行排序时,Oracle会抛出错误。在使用distinct关键字http://ora-01791.ora-code.com/http://oraclequirks.blogspot.com/2009/04/ora-01791-not-selected-expression.html时,Oracle似乎不会接受不在select子句中的列。

以下是实体中定义的关系:[Subject m:m JobFunction](显然通过赋值表[Subject o:m Subject_JobFunction m:o JobFunction])和[Subject m:o Type]。因为我需要通过JobFunction搜索Subject,所以它在ejbql中加入,这需要distinct关键字才能将不同的Subjects返回到列表页面。当我尝试通过Type.name(通过多对一关系)进行排序时,生成的查询会使Oracle生气并抛出“ORA-01791:not a SELECTed expression”错误。 SubjectQuery代码:

@Override
public String getEjbql() {
    return "select subject from Subject subject left outer join subject.jobFunctions as jobFunction";
}

@Override
@SuppressWarnings("rawtypes")
public List<ValueExpression> getRestrictions() {
    ValueExpression[] RESTRICTIONS = { 
            createValueExpression("lower(subject.name) like #{subjectQuery.prepRestriction(subjectQuery.subject.name)}"), 
            createValueExpression("subject.active = #{subjectQuery.active}"), 
            createValueExpression("subject.type.name = #{subjectQuery.typeName}"), 
            createValueExpression("jobFunction.name = #{subjectQuery.jobFunctionName}")
            };
    return Arrays.asList(RESTRICTIONS);

}

当用户通过前端按类型名称排序时设置查询顺序:

"#{subjectQuery.order=='UPPER(subject.type.name) asc'}"

我收到了Oracle错误。如果我从ejbql中取出明显的,排序工作正常,但我得到重复的主题记录。当我添加distinct关键字时,列表工作正常,没有重复记录,但排序会引发错误。有没有人有任何关于如何重构ejbql以返回不同记录而不使用distinct关键字以使排序满意的建议,或者如何进行排序而不会让Oracle生气,因为查询中引用的排序列不在select子句中?我已经阅读了几个地方,我的答案可能在Hibernate Criteria API中,但我不知道如何在我想要完成的扩展EntityQuery类的上下文中利用它。请帮助!

2 个答案:

答案 0 :(得分:0)

如果您要添加DISTINCT,则会出现问题。

“因为必须加入多对多关系以允许搜索功能,所以查询会为每个分配返回重复记录。”

考虑一个人可以在许多项目上工作而一个项目可以有很多人的情况。 “人/项目”具有独特性。如果您想要一个在项目A或B(或两者)中工作的人员列表,那么您可能会得到

FRED/PROJ_A
BILL/PROJ_A
FRED/PROJ_B
TOM/PROJ_B
BILL/PROJ_C

如果您只显示名称(而不是项目),您仍然可以按项目订购,但您会看到

FRED
BILL
FRED
TOM
BILL

如果你做DISTINCT,你就不能再按项目排序了,因为你不知道FRED是来自PROJ_A还是PROJ_B,或者BILL是在TOM之前(基于PROJ_A)还是在TOM之后(基于PROJ_C)。

因此,删除DISTINCT并始终显示您要订购的列(因为这样您就会明白为什么重复项实际上并不重复)。

答案 1 :(得分:0)

我不确定生成的查询是如何不同的,但我找到了答案。我不知道hibernate的fetch命令,它修复了对distinct关键字的需求(同样,不确定如何,可能是通过subquerying?)。将ejbql更改为:

@Override
public String getEjbql() {
    return "select subject from Subject subject left join fetch subject.jobFunctions jobFunction";
}

不再需要distinct,因此,Oracle不会抱怨列不在select子句中的顺序。该列表按预期工作,排序列工作!耶!

可以预见,我在stackoverflow上找到了答案。问题不完全相同,但hql语法对我有用:HQL order by within a collection