Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > hibernateTemplate. Pagination.


Автор: garbuz 30.7.2009, 10:30
Возникли непонятки с pagination.
Делаю так
Код

 public List<Post> getAll() {
        return template.findByExample(new Post(), 4 , 4);
    }

Выбираются четыре записи, причем выборка начинается не с четвертой, а с третье. И первые три выбранные записи одинаковые.
Делаю по-другому.
Код

public List<Post> getAll() {
        System.out.println("PostDAOImpl => getAll");
         DetachedCriteria criteria = DetachedCriteria.forClass(Post.class)
                .addOrder(Order.desc("createdDate"));
         return template.findByCriteria(criteria, 4, 4);
      
    }

Выбирается четыре записи, только по две одинаковых. Добавив эту строчку
Код

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

получаем две записи. Что же в итоге делать? Неужели чтобы получить 4 записи надо так писать?
Код

 public List<Post> getAll() {
        System.out.println("PostDAOImpl => getAll");
        //return template.find("FROM Post order by createdDate desc");


        DetachedCriteria criteria = DetachedCriteria.forClass(Post.class)
                .addOrder(Order.desc("createdDate"));
        criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
        return template.findByCriteria(criteria, 4, 8);

    }

Автор: MisterCleric 30.7.2009, 10:55
Привет. Нет-нет. У тебя проблема связана с тем, что ты выбираешь коллекцию, элементы которой также содержат коллекции. Т.е. твой Post содержит ManyToOne List<Message>.
в результате используется InnerJoin в селекте. а подумай сам: когда ты такой запрос выполнишь на базе, сколько раз у тебя повторится инфа по посту? Да столько сколько мессаждей в этом посте.

Что бы такого не происходило, надо или LazyLoad(а может и не поможет...) или вот так:
Код

@Entity
@SequenceGenerator(name = "SEQUENCE", sequenceName = "GEN_TOPIC", allocationSize = 1)
@org.hibernate.annotations.AccessType("field")
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
public class Topic implements Serializable {
    @Id
    @GeneratedValue(generator = "SEQUENCE")
    @Column(updatable = false, nullable = false, unique = true)
    private Long id;

 @OneToMany(mappedBy = "topic", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @Fetch(FetchMode.SELECT) // сюда обратить внимание!!!
    @Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
    @OrderBy("regDate desc")
    private List<Message> messages = new ArrayList<Message>();
}

Автор: garbuz 30.7.2009, 16:02
Цитата(MisterCleric @  30.7.2009,  10:55 Найти цитируемый пост)
Привет. Нет-нет. У тебя проблема связана с тем, что ты выбираешь коллекцию, элементы которой также содержат коллекции. Т.е. твой Post содержит ManyToOne List<Message>.

Вот класс
Код

@Entity
@Table(name="posts")
public class Post {
    
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="postId")
    private Long postId;
    
    @Column(name="title")
    private String postName;

    @Column(name="preview")
    private String preview;
    
    @Column(name="content")
    private String postBody;
    
    @ManyToOne(cascade = {CascadeType.REFRESH}, fetch = FetchType.EAGER)
    @JoinColumn(name="userId")
    private User author;
    
        
    @ManyToMany(cascade = CascadeType.REFRESH, fetch = FetchType.EAGER)
    @JoinTable(name="posts_tags",
    joinColumns = @JoinColumn(name = "postId"),
    inverseJoinColumns = @JoinColumn(name = "tagId"))
    private Set<Tag> tags;
    
    @ManyToOne(cascade = CascadeType.REFRESH, fetch = FetchType.EAGER)
    @JoinColumn(name="categoryId")
    private Category category;
    
    
    @ManyToOne(cascade = {CascadeType.REFRESH}, fetch = FetchType.EAGER)
    @JoinColumn(name="statusId")
    private Status status;

    @Column(name="createdDate")
    private Date createdDate;

    @Column(name="modifiedDate")
    private Date modifiedDate;

У всех полей FetchType.EAGER. Это наверно не очень хорошо, но пока так. У поста есть коллекция тегов и все. Пост имеется ввиду не тот что на форуме, а например тот что в блоге, который вместо сообщении содержит коментарии. В данном случае у поста нет коллекии комментариев. Каждый комментарий содержит ссылку на пост.
Посмотрел sql, котрый генерит хибернейт - это ужасно. Очень большой запрос со множеством джоинов. Джоины скорее всего из-за FetchType.EAGER

Автор: MisterCleric 30.7.2009, 16:12
Ну может я немного поспешил предугадать, но суть от этого не меняется:
из-за  того, что у тебя 
Цитата

private Set<Tag> tags;

и выходит вот это дублирование. поставь тот хинт, что я предложил и должно помочь.
У меня, собственно, так везде, где используется Pagination
Еще могу предложить такое архитектурное решение, для такой задачи, как вынос логики этой коллекции во VIEW на базе, или просто запросом, результат которого будет меппиться на твой Post, таким образом ты сможешь и логику свою обрабатывать и не будет у тебя лишних JOIN

Автор: garbuz 30.7.2009, 17:08
MisterCleric, спасибо! Вроде помогло! Дома вечерком еще попробую!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)