Spring Sorting with Nulls_Last Handling not working - spring

I created a sort rule like this for sorting my list:
Sort sort = new Sort(new Sort.Order(Sort.Direction.ASC,"productOrder", Sort.NullHandling.NULLS_LAST), new Sort.Order(Sort.Direction.ASC,"producedYear", Sort.NullHandling.NULLS_LAST));
with this rule I want to sort the productOrder first, and then if the productOrder is the same then the producedYear will be compared and sorted. If there are null values presented, it should be sorted at the end of the list. productOrder will have type Long and producedYear will have type Double.
My Repository interface extends the JpaRepository:
public interface ProductRepository extends JpaRepository<Product, String> {
List<Product> findByDisabledAndValid(int disabled, int valid, Sort sort);
}
But the sorted list I received is containing the null values always at the beginning of the list. This means the null values will be sorted first, then come the productOrder, and finally the producedYear will be sorted. It seems that the third parameter that I defined on my Sort.Order method is not working.
Does anyone have an idea why? Thank you very much

Instead of using the Sort.NullHandling.NULLS_LAST integrated with Spring, I solved the above problem by creating my own Sort function, like this:
Collections.sort(resultList, Comparator
.comparing(Product::getProductOrder, Comparator.nullsLast(Comparator.naturalOrder()))
.thenComparing(Product::getProducedYear, Comparator.nullsLast(Comparator.naturalOrder())));
Hope this help if someone also faces the same problem.
Regards!

Related

How to sort columns multiple columns in spring jpa which has parameters being passed?

I have a Jpa repository and I need to sort by two columns i order.
public interface PetRepository extends JpaRepository<PetClass, PetKey> {
List<PetClass> findAllByStatusAndWeightAndBirthDateBetween(String status, String weight, Date fromDate, Date toDate);
}
First I need to sort it by PetClass's petHeight property in ascending order and then by petLength property in descending order.
If I needed to sort only one column then I could have done findAllByStatusAndWeightAndBirthDateBetweenOrderByPetLength but I can't use two 'orderBy' in one method it seems because it throws an error saying such.
You can easily construct multi sort in repository
return this.PetRepository.findAll(Sort.by("status").descending().and(Sort.by("weight")).a cending());

How to GroupBy objects from a list by some common catalog of properties in Java 8

I've been struggling with a problem with one of my lists of data because one of the requirements after generating it is to group some of them by some common parameters (more than 1)
What I should get at the end is a map where the value is a list of common objects. For example.
List<Cause> listToGroup = new ArrayList<>();
listToGroup.add(Similar);
listToGroup.add(Common);
listToGroup.add(Similar);
listToGroup.add(Similar);
listToGroup.add(Common);
In a weird way to represent one group (Similar) and the other (Common), those should be separated into two different lists (that list is generated by a request to other methods, in that case, I just added manually to show what could be the contained data in the list). My main problem is the criteria to group them because is based on a group of parameters that are shared, but not all (if the required parameters are equal, should belong to the same list) In the class shown below, that behaviour is seen because there are some parameters that are not being considered.
public class Cause extends GeneralDomain {
//parameters which must be equals between objects
private Long id;
private Date creationDate;
private Part origin;
private Part destination;
//parameters which are not required to be equal
private BigDecimal value
private Stage stageEvent
//omitted getters and setters
}
I've been seeing the comparator method and the groupingBy method provided in Java 8, but at the moment I just know how to perform that task considering just one parameter (for example grouping them by id) And I have no idea about how to group them using more than one parameter.
//this should be the code if the requirement would be just one parameter to groupby, but in my case are more than one.
Map<Long, List<Cause>> result = request.getList(criteria)
.stream()
.map(p -> parsin.createDto(p))
.collect(groupingBy(Cause ::getId));
I would be really glad for any suggestion. If my explanation is not clear, I'm so sorry. That became so complicated that even is hard for me to explain

Spring data - Order by multiplication of columns

I came to a problem where I need to put ordering by multiplication of two columns of entity, for the sake of imagination entity is:
#Entity
public class Entity {
#Column(name="amount")
private BigDecimal amount;
#Column(name="unitPprice")
private BigDecimal unitPrice;
.
.
.
many more columns
}
My repo interface implements JpaRepository and QuerydslPredicateExecutor,
but I am struggling to find a way to order my data by "amount*unitPrice",
as I can't find a way to put it into
PageRequest (new Sort.Order(ASC, "amount * unitPrice"))
without having PropertyReferenceException: No property amount * unitPrice... thrown.
I can't user named query, as my query takes quite massive filter based on user inputs (can't put where clause into query, because if user hasn't selected any value, where clause can't just be in query).
To make it simple. I need something like findAll(Predicate, Pageable), but I need to force that query to order itself by "amount * unitPrice", but also have my Preditate (filter) and Pageable (offset, limit, other sortings) untouched.
Spring Sort can be used only for sorting by properties, not by expressions.
But you can create a unique sort in a Predicate, so you can add this sort-predicate to your other one before you call the findAll method.

Compare two list in javers

I have a question regarding list comparator. I have a web application which have page with table.
I can edit data in this table and also delete row.
Standard comparator working correct when i edit data but i have problem when i remove row.
The problem is common (i think) when i remove e.g one row what is happening
javers comparing old list with now one it's looks something like this:
old list have two object now list have one object (i removed first one) now javers don't know which object
was removed and he compare first object from old list with second object from new list and for him
whole object was changed and that is not true.
My thought was I will wrote own list comparator and in this comparator before javers compare method will be colled
i check if comparing objects have the same ID.
Unfortunately i have problem to obtain object ID.
My comparator looks like this
public class ListComperator implements CustomPropertyComparator {
public ValueChange compare(List list1, List list2, GlobalId globalId, Property property) {
for (Object o1 : list1) {
for (Object o2 : list2) {
if(o1.getId().equals(o2.getId()) ) {
javers.compare(o1, o2);
}
}
}}}
The second list "list2" have my object from which i can get any property e.g ID.
The firs list "list1" is list with some ValueObjectId and i don't know how to get property with id from object o1.
Is there a way to get this information or maybe i'm doing something totally wrong please help.
I suppose that you have ValueObjects stored in those Lists? Since ValueObjects has no identifiers, there is no way to detect how they 'move' between List indexes when List is changed. Custom comparator won't help much without a
way to identify you objects.
I suggest to add some kind of identifiers to your objects stored in a List and map them as Entities (use #Id annotation).

Liferay comparator not working

I am using method for finding structure articles:
List<JournalArticle> articles = JournalArticleLocalServiceUtil.getStructureArticles(groupId, "15566", 0, 10000, comparator);
comparator is instance of class:
public class OrderByEventsStartDate extends OrderByComparator{
public int compare(Object o1, Object o2){
System.out.println("comparator test");
return 1;
}
}
Message is never printed and results are not sorted... Any help, please?
results are not sorted...
Because you are always returning 1.
Now to create an OrderByComparator you need to do something more.
If you look at the source code as to how the OrderByComparator is used by the different persistence methods you would get some idea.
Also a look at some of Liferay's implemented Comparators will shed some light as to what you need to do:
Journal Comparators - You can check the ArticleTitleComparator
UserFirstNameComparator
A super-short tutorial on implementing OrderByComparator in liferay
You would require to create 3 fields:
public static final String ORDER_BY_ASC - Specifies the field with which you want to order the results. In the ascending manner.
public static final String ORDER_BY_DESC - Specifies the field with which you want to order the results. In descending order.
public static final String[] ORDER_BY_FIELDS - Specifies the different fields required for sorting (refer UserFirstNameComparator for multiple fields).
Implement the compare method on the field you would like to sort
Impement the getOrderBy() method - refer ArticleTitleComparator
Impement the getOrderByFields() method - refer ArticleTitleComparator
Impement the isAscending() method, required in compare and getOrderBy methods to decide whether it is asc or desc - refer ArticleTitleComparator
Message is never printed and
Because you have not implemented these methods, it ignores the OrderByComparator you have passed. You can check the source code of the method you are using JournalArticleLocalServiceImpl#getStructureArticles
Hope this helps.

Resources