开发者

How can i retrieve a list of entites + an additional value with JPA/Hibernate?

开发者 https://www.devze.com 2023-02-02 20:46 出处:网络
There are two tables, report and reportcomment. Every reportcomment is assign (via foreign key) to a report, therefore a report has zero to many reportcomments.

There are two tables, report and reportcomment. Every reportcomment is assign (via foreign key) to a report, therefore a report has zero to many reportcomments.

If I need a list, that gives me all reports with the respective number of comments of every report, I would do the following (with SQL):

SELECT r.*, c.cnt
FROM report r
LEFT JOIN (
    SELECT ir.id AS report_id, COUNT(ic.id) AS cnt
    FROM report ir
    INNER JOIN reportcomment ic ON ir.id = ic.report_id
    GROUP BY ir.id
) c ON c.report_id = r.id

I开发者_C百科 would like to retrieve such a list with JPA/Hibernate and store the c.cnt somewhere in my Report entity object. How could that be achieved?


I think the simpliest way would be to create a transient field in Report and convert tuples returned by the appropriate query manully, something like this:

List<Object[]> tuples = em.createQuery(
    "SELECT r, COUNT(c) " +
    "FROM ReportComment c RIGHT JOIN c.report r" +
    "GROUP BY r.id, ...").getResultList();

List<Report> reports = new ArrayList<Report>();
for (Object[] tuple: tuples) {
    Report r = (Report) tuple[0];
    r.setCommentCount((Long) tuple[1]);
    reports.add(r);
}


I believe @SqlResultSetMapping may work for you.

http://download.oracle.com/javaee/5/api/javax/persistence/SqlResultSetMapping.html

http://blogs.oracle.com/JPQL01/entry/native_query_in_java_persistence


I'm sure there are a number of reasons that what you're working on isn't designed this way. There's probably a greater number of reasons why you don't want to redesign it. I realize this might not answer your question at all, but if I were you and I had the time, I'd have the inclination to make something like this:

public class Comment { 
...
List<CommentReport> commentReports = new ArrayList<CommentReport>();

@OneToMany(mappedBy="comment")
public List<CommentReports> getCommentReports() {
    return commentReports;
}

public void setCommentReports(List<CommentReport> commentReports) {
    this.commentReports = commentReports;
}

@Transient
public int countReports() {
    return commentReports.size();
}

What i've proposed assumes you're working in a web application and are using some sort of open-session-in-view. Otherwise you'd probably have to fetch those comments eagerly which could be bad.

But, if you're going to use hibernate why not go a bit further? It's whole purpose is to abstract and hide database code and what i've provided is a step in that direction.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号