Alex Silkovsky
Alex Silkovsky

Reputation: 561

JPA: can't make OrderBy work

I'm trying to print ordered list after persisting it and retrieving.

My Entities:

@Entity
public class News {
    @Id @GeneratedValue
    private Long id;
    private String content;
    @OneToMany(cascade = CascadeType.ALL)
    @OrderBy("likes DESC")
    private List<Comment> comments = new LinkedList<>();

    //------------------
}

@Entity
public class Comment {
    @Id
    @GeneratedValue
    private Long id;
    private String content;
    private int likes;
}

Main method snippet:

tx.begin();
{
    // persist
    News n1 = new News("Super news!!");
    Comment c1 = new Comment("comment 1", 1);
    Comment c2 = new Comment("comment 2", 200);
    Comment c3 = new Comment("comment 3", 10);

    n1.addComment(c1);
    n1.addComment(c2);
    n1.addComment(c3);

    em.persist(n1);

    // find
    News news = em.find(News.class, n1.getId());
    for (int i = 0; i < news.getComments().size(); i++) {
        System.err.println(news.getComments().get(i).getLikes());
    }
}
tx.commit();

The result printed in declaration order (1 -> 200 -> 10) and I expect (200 -> 10 -> 1). Can somebody help with this?

Upvotes: 2

Views: 1428

Answers (2)

Parvez
Parvez

Reputation: 641

@OrderBy is applied when sql query is executed. In your case the data is already in memory so sql query is not executed. You can try using @Sort annotation that apply sorting in memory. Depending on your use case it may not be efficient if your list is big.

@Sort(type = SortType.COMPARATOR, comparator = CommentsComparator.class)

EDIT: @Sort is a hibernate specific annotation. For pure JPA I think the collection (List) can be updated to some sorted collection like SortedSet if possible.

Upvotes: 1

Alex S. Diaz
Alex S. Diaz

Reputation: 2667

I guess that you are getting your entity from the entity manager and not from db, so you are getting the same object that you created (not sorted object). You should try to refresh caché before the em.find() method:

em.getTransaction().begin();
em.persist(n1);
em.getTransaction().commit();

// Clear object
em.getEntityManagerFactory().getCache().evict(News.class, n1.getId());

// find
News news = em.find(News.class, n1.getId());
for (int i=0; i<news.getComments().size(); i++){
    System.err.println(news.getComments().get(i).getLikes());
}

From Javadoc, the method:

<T> T find(java.lang.Class<T> entityClass, java.lang.Object primaryKey)

Find by primary key. Search for an entity of the specified class and primary key. If the entity instance is contained in the persistence context, it is returned from there.

I empathize the part that maybe is getting you troubles.

Upvotes: 3

Related Questions