gpt4 book ai didi

java - "select new Object ... join ... where"的问题

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:41:08 26 4
gpt4 key购买 nike

我的 HQL 查询有问题

三类

ClassOne 是我的 BusinessObject

public class ClassOne {  
private int id;
private int status;
private Set<ClassTwo> classTwos;
+ other fields/getters/setters/constructor etc
}

ClassTwo 在一组 ClassOne 中被引用,是 ClassOne 对象的历史

public class ClassTwo {  
private int id;
private int oldStatus;
private int newStatus;
private String message;
//+ getters/setters/constructor etc
}

ClassThree 是我的 DTO/VO 只有一个 classTwo(不是整个历史)

public class ClassThree {  
private int id;
private int status;
private ClassTwo classTwo;
public ClassThree(int pId, int pStatus, ClassTwo pClassTwo) {
id=pId;
status=pStatus;
classTwo=pClassTwo;
}
//+ getters/setters etc
}

现在我想像这样创建一个 HQL 查询:
我想获取具有特定状态的 ClassThree 的所有对象,如果它存在具有特定 newStatus 的最新 ClassTwo。
例如:
我想获取 ClassOne 的所有 DTO (ClassThree),其状态现在为 1,但在它们的历史早期它已经是 2,我想要最新的 ClassTwo 对象,它的 newStatus 为 2。

SELECT new ClassThree(c1.id, c1.status, c2)  
FROM ClassOne c1
LEFT JOIN c1.classtwos c2 (...)

and (...) 是我不知道该做什么的地方,我什至不确定是不是join/join fetch

环顾四周并尝试了很多,但没有任何线索。特别是在连接提取时,我遇到了一些 Hibernate 错误,例如 org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list

像那样获取 BusinessObject 是没有问题的

SELECT distinct(c1)
FROM ClassOne c1
LEFT OUTER JOIN FETCH c1.classtwos c2

然后我将 ClassTwos 作为我的字段。

提前致谢,
雅各布

P.S.:有一件事可能很重要,ClassTwo 没有引用 ClassOne!!

P.P.S:解决我的问题的简单 SQL 查询看起来或多或少像这样:

select * from classone as c1 left join (select * from classtwo where newstatus = 2) c2 on c1.id=c2.id_classone whete c1.status = 1 

此查询有效并获取我的 PostGreSQL 数据库所需的所有信息,但我真的希望有一个 HQL 可以继续使用,尤其是出于维护原因等......

更新解决方案:

获取所有状态为 1 的 ClassOne 的 ID

Collection<Integer> ids = null;
ids = (Collection<Integer>) getHibernateTemplate().execute(
new HibernateCallback() {
public Object doInHibernate(Session pSession) throws HibernateException, SQLException {
return getDocumentIds(pSession, pStatus);
}
}
);

现在我得到所有处于状态 2 的 DTO(感谢 Ivan):

命名查询Document.dto.with.transfer

SELECT new DocumentDTO(d.id, d.status, histo)
FROM Document d
LEFT JOIN d.histories histo
WHERE
d.id in (:ids)
AND
(histo.id =
SELECT MAX(innerhisto.id)
FROM Document innerd
JOIN innerd.histories innerhisto
WHERE d.id = innerd.id AND innerhisto.newStatus = 21)

(在我的代码中我使用了一些命名查询)

List<DocumentDTO> lRes = new ArrayList<DocumentDTO>();
Query lQuery = getSession(false).getNamedQuery("Document.dto.with.transfer");
lQuery.setParameterList("ids", ids);
lResultList.addAll(lQuery.list());

然后我从我的列表 id 中删除所有已经找到的 id

for (DocumentDTO dto : lResultList) {
ids.remove(dto .getId());
}

我使用 DTO 的第二个构造函数执行第三个查询,使用虚拟对象初始化我的历史记录。

命名查询Document.dto.simple

SELECT new DocumentDTO(d.id, d.status)
FROM Document d
WHERE
d.id in (:ids)

(另一个命名查询)

lQuery = getSession(false).getNamedQuery("Document.dto.simple");
lQuery.setParameterList("ids", ids);
lResultList.addAll(lQuery.list());

完成了。

最佳答案

要包含没有历史记录的文档,我们应该使用 LEFT JOIN 并测试空集合,然后我们使用子查询 (SELECT COUNT(...)) 来检测所有从未处于状态 2 的文档。最后一个 OR-clause 用于获取具有指定状态的最后一个历史记录。

这是 HQL 查询:

SELECT new DocumentDto(doc.id, doc.status, hist) 
FROM Document doc
LEFT JOIN doc.histories hist
WHERE doc.status = :docStatus
AND (size(doc.histories) = 0
OR (SELECT COUNT(innerhist)
FROM Document innerdoc JOIN innerdoc.histories innerhist
WHERE innerdoc.id=doc.id AND innerhist.newStatus = :historyStatus) = 0
OR (hist.newStatus = :historyStatus AND hist.id =
(SELECT max(innerhist.id)
FROM Document innerdoc
JOIN innerdoc.histories innerhist
WHERE innerdoc.status = :docStatus AND innerhist.newStatus = :historyStatus))

然后在查询中调用 setParameter("historyStatus", 2)setParameter("docStatus", 1) 以获得正确的结果。

就是这样!

请注意,我做了一个假设,我们可以使用 Historyid 属性的值作为对象放置顺序的指示器你的数据库。

关于java - "select new Object ... join ... where"的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3006749/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com