2013-02-26 9 views
5

Mam następujący modelu bazy danychJak korzystać JdbcTemplate Dołącz do wykonywania zapytań

 create table Diary (id bigint NOT NULL AUTO_INCREMENT, 
       creationDate TIMESTAMP DEFAULT CURRENT_TIMESTAMP, 
       name varchar(255) not null, 
       description text, 
       viewtype varchar(255) not null, 
       member bigint, 
       primary key (id), 
       foreign key (member) references Member(id)); 


     create table Page (id bigint NOT NULL AUTO_INCREMENT, 
       creationDate TIMESTAMP DEFAULT CURRENT_TIMESTAMP, 
       viewtype varchar(255) not null, 
       diary bigint, 
       member bigint, 
       primary key (id), 
       foreign key (diary) references Diary(id), 
       foreign key (member) references Member(id)); 

     create table Comment (id bigint NOT NULL AUTO_INCREMENT, 
       postingDate TIMESTAMP DEFAULT CURRENT_TIMESTAMP, 
       comment text not null, 
       page bigint, 
       member bigint, 
       primary key (id), 
       foreign key (page) references Page(id) 
       foreign key (member) references Member(id)); 

Używam sprężyny JDBC szablon.

 My interface looks like follows: accountid is the memeberid in the database. 

    Collection<Diary> getDiaries(Long accountId); 

A mój pamiętnik wygląda następująco:

  public class Diary { 
      private Collection<Page> pages; 
      private Long id; 
      private LocalTime creationDate; 
      private String name; 
      private String description; 
      private ViewType type; 
      } 

Chciałem wiedzieć, jak będzie wyglądać zapytanie teraz, czy chcę, aby przygotować obiekt Diary użyciu JDBC szablon. Jest również możliwe, aby po prostu odpalić tylko jedno zapytanie i po prostu przygotować ten obiekt Diary, ponieważ uniknę dla tego samego żądania wielokrotnego odpalania zapytań. Dla powyższego interfejsu jest bardzo prawdopodobne, że będę używał kwerendy s join lub jest jakikolwiek prostszy sposób możliwy przy użyciu wiosennego szablonu JDBC.

Odpowiedz

3

Można utworzyć pojedyncze zapytanie przy użyciu sprzężeń zewnętrznych (zakładam, że możliwe jest posiadanie pamiętnika, który nie ma żadnych stron i stron, które nie mają komentarzy).

Teraz, zamiast wykonywać wiele zapytań (po jednym dla każdej strony), wykonuje pojedynczą kwerendę, korzystając z zewnętrznych połączeń do połączeń Diary, Page i Comment. Jak widać poniżej, będzie to oznaczać, że dziennik i informacje o stronie są zwracane wiele razy, ale myślę, że istnieje kompromis pomiędzy wielokrotnymi połączeniami DB i odrobiną zbędnych informacji.

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(); 

pamiętać, że kod nie jest szczególnie ładny, ponieważ masz do obsługi zestawów wyników i dbać o kiedy nowa strona jest zwracana (dlatego klauzula order by jest ważne), ale jest to rodzaj rzecz, którą lubi Hibernate zaopiekuje się tobą pod maską, gdy są chętni do pobrania (nie mówię, że Hibernate jest lepszy lub nie, ponieważ lubię używać JdbcTemplate do kontroli nad zapytaniami, które wydaje, ale Hibernate (lub JPA) wykonuje wiele ciężkich czynności, jeśli chodzi o zapełnianie wykresów obiektów).

Zobacz także JdbcTemplate#query

EDIT:

Modified zwrócić wszystkie pamiętniki, stron, komentarze do członka.

+0

Dzięki beny. Muszę to przetestować. –

+0

Właśnie napisałem bardzo proste zapytanie -> wybierz d.id, d.creationDate, d.name, d.description, d.viewtype z Member m wewnętrzny join Diary d na d.member = m.id gdzie m.id = "4915018864030990478"; To zwraca mi wszystkie pamiętniki dla Członka. Teraz każdy dziennik może mieć n stron, więc co myślisz, jeśli zrobię wiele sub wewnętrznych sprzężeń z tym zapytaniem. Twój kurs wygląda dobrze, ale chciałem się dowiedzieć, czy to też możliwe, czy nie. –

+0

@SaurabhKumar: Zmieniono sposób postępowania ze wszystkimi dziennikami dla członka. – beny23

Powiązane problemy