How to use JdbcTemplate to perform Join queries

前提是你 提交于 2019-12-05 07:26:30

You would be able to create a single query using outer joins (I'm assuming here that it is possible to have a diary that doesn't have any pages and have pages that don't have comments).

Now, instead of doing multiple queries (one for each page), this does a single query using outer joins to connection Diary, Page and Comment. As you can see below, this will mean that the diary and page information is returned multiple times, but I think there is a tradeoff between having multiple DB calls and a bit of redundant information.

 class FullDiaryRowCallbackHandler implements RowCallbackHandler {
    private Collection<Diary> diaries = new ArrayList<Diary>();
    private Diary currentDiary = null;
    private Page currentPage = null;

    public void processRow(ResultSet rs) {
       long diaryId = rs.getLong("d.id");
       if (currentDiary == null || diaryId != currentDiary.getId()) {
          currentDiary = new Diary();
          currentPage = null;
          diaries.add(currentDiary);
          currentDiary.setId(diaryId);
          currentDiary.setCreationDate(toLocalTime(rs.getTimestamp("d.creationDate")));
          currentDiary.setDescription(rs.getString("d.description"));
          ...
       }
       long pageId = rs.getLong("p.id");
       if (!rs.wasNull() && currentPage != null && currentPage.getId() != pageId) {
          currentPage = new Page();
          if (currentDiary.getPages() == null) {
              currentDiary.setPages(new ArrayList<Page>());
          }
          currentDiary.getPages().add(currentPage);
          currentPage.setId(pageId);
          currentPage.setCreationDate(toLocalTime(rs.getTimestamp("p.creationDate")));
          ...
       }
       long commentId = rs.getLong("c.id");
       if (!rs.wasNull() && currentPage != null) {
          Comment comment = new Comment();
          if (currentPage.getComments() == null) {
              currentPage.setComments(new ArrayList<Comment>());
          }
          currentPage.getComments().add(comment);
          comment.setId(commentId);
          comment.setPostingDate(toLocalTime(rs.getTimestamp("c.postingDate")));
          comment.setComment(rs.getString("c.comment"));
       }
    }

    public Collection<Diary> getDiaries() {
       return diaries;
    }
 }

 FullDiaryRowCallbackHandler rowCallbackHandler = new FullDiaryRowCallbackHandler();
 Collection<Diary> result = jdbcTemplate.query(
    "select d.id, " +
           "d.creationDate, " +
           "d.description, " +
           "p.id, " +
           "p.creationDate, " +
           "c.id, " +
           "c.postingDate, " +
           "c.comment " +
      "from Diary d " +
      "left outer join Page p on d.id = p.diary " +
      "left outer join Comment c on p.id = c.page " +
     "where d.member = ? " +
     "order by d.id, p.id, c.id",
    rowCallbackHandler,
    myMemberId);
Collection<Diary> diariesForMember = rowCallbackHandler.getDiaries();

Note, the code isn't particularly pretty, because you have to handle the result sets and take care of when a new page is returned (that's why the order by clause is important), but that's the sort of thing that the likes of Hibernate take care for you under the hood when they are eagerly fetching (I'm not saying Hibernate is better or not, for I like using JdbcTemplate for the control it provides over the queries that I'm issuing, but Hibernate (or JPA) do a lot of the heavy lifting when it comes to populating object graphs).

See also JdbcTemplate#query

EDIT:

Modified to return all diaries, pages, comments for a member.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!