How do I get a Month from LocalDate in JPQL query? - java-8

I got a transaction with a LocalDate as created attribute:
private LocalDate created;
I also got following query to retrieve every date out of my table transaction.
SELECT DISTINCT t.created FROM Transaction t
This however just gives me all dates and I am mapping those dates to all month that were found.
public List<Month> findAllUsesdMonth() {
return getEm().createNamedQuery(Transaction.FIND_ALL_MONTH, LocalDate.class).getResultList().stream().map(LocalDate::getMonth)
.collect(Collectors.toList());
}
This leads to duplicate month obviously because I selected distinct dates and not distinct months. A workaround would be to use a Set instead of a List.
I would like to retrieve only the month in the JPQL query instead of mapping them afterward. Is there any possibility to do so?

Date format: yyyy-MM-dd HH:mm:ss
Query: SELECT t FROM Transaction t GROUP BY (SUBSTRING(t.created, 6, 7))
By calling this NamedQuery you will get distinct month.

Related

Spring MongoRepository filter string date column

Is it possible to filter a MongoRepository in Spring where there is a column with date strings like that:
2019-01-01T00:00:00
2022-01-20T00:00:00
2022-05-01T00:00:00
I try to get all columns where the Date value is after a certain date.
I tried the following statements:
findAllByPersonIdAndDateAfter(int id, Date after);
findAllByDateAfter(Date date)
findAllByDateGreaterThan(Date date);
Invoked it with e.g.:
Date after = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2022-03-31 23:00:00");
repository.findAllByDateAfter(after)
But it always returns 0 rows.

JPA Criteria API - Add days to DATE using ORACLE

I'm trying to use JPA Criteria API to filter a date between a specific range.
The problem is that I don't have directly the date in my entity, I obtain the date using a date field and adding a number of days (which are in another field) to this date .
I look around and I saw some responses which recommends to calculate the date in java before pass it to criteria builder, but the problem is that I don't know the number of days to add because it depends on the days in a specific column of the table.
The simplified table OBJECT has a field CREATION_DATE of type date and EXPIRATION_DAYS which is a number. I want to filter by a range of possible expiration date, I get the expiration date of each element in OBJECT table adding EXPIRATION_DAYS to CREATION_DATE, the SQL query is:
select * from OBJECT
where CREATION_DATE + EXPIRATION_DAYS
between to_date('01/01/2018','dd/MM/yyyy') and to_date('01/02/2018','dd/MM/yyyy')
In CriteriaBuilder I make some attempts, but I think the best approach I try to use is the follow:
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Object> criteria = criteriaBuilder.createQuery(Object.class);
List<Predicate> predicates...
predicates.add(criteriaBuilder.between(
criteriaBuilder.function("AddDate", Date.class, Object.get("creationDate"), criteriaBuilder.literal("day"), Object.get("expirationDays")),
dateInit, dateEnd));
criteria.where(predicates.toArray(new Predicate[]{}));
...
TypedQuery<Object> query = entityManager.createQuery(criteria);
return query.getResultList();
I use function("addDate"...) method, the problem is that I thought JPA implementation translate "addDate" to specific database vendor but it's not, because it's throwing the following exception which is pretty clear:
javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.4.v20160829-44060b6): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLSyntaxErrorException: ORA-00904: "ADDDATE": invalid identifier
And the query trace:
(AddDate(t0.CREATION_DATE, ?, t0.EXPIRATION_DAYS) BETWEEN ? AND ?)).
How can I achieve this using ORACLE as a database? Or there is a better approach?
In Hibernate seems that there is the #Formula annotation which provides the functionality I'm looking for, however there is no such thing in JPA neither in specific implementation I'm using(eclipselink).
I want to avoid the necessity of declare a specific function, but unfortunately I do it this way, first I declare the function ADD_DAYS in Oracle as follows:
create or replace function ADD_DAYS(dateValue DATE, daysValue NUMBER)
return DATE is
begin
return dateValue + daysValue;
end;
Then I call this function using function method of criteriaBuilder, and passing as parameters the function name, the type of object returned by the oracle function, and the two arguments I define, the column with the date, and the column with the days to add:
criteriaBuilder.function("ADD_DAYS", Date.class, Object.get("creationDate"), Object.get("expirationDays"))

Oracle - Get MAX value from concatenated fields

I'm trying to retrieve the max datetime of a task started, grouping by task_code.
I've tried the following query to get all the max date, but the date and time are two different fields, if I try to concatened like,
MAX(DATEINI||' '||HOURINI)
to get the latest datetime by group, the query return empty. Is possible to do this, am I missing something?
SELECT DATEINI||' '||HOURINI AS STARTED, TASK, TASK_CODE
FROM TB_TASKS WHERE DATEINI IN
(SELECT MAX(DATEINI) FROM TB_TASKS GROUP BY TASK_CODE)
ORDER BY DATEINI DESC, HOURINI DESC;
Try working with dates instead of strings like this:
SELECT DATEINI||' '||HOURINI AS STARTED, TASK, TASK_CODE
FROM TB_TASKS WHERE TO_DATE(DATEINI||' '||HOURINI,'DD/MM/YYYY HH:MI:SS') IN
(SELECT MAX(TO_DATE(DATEINI||' '||HOURINI,'DD/MM/YYYY HH:MI:SS')) FROM TB_TASKS GROUP BY TASK_CODE)
ORDER BY DATEINI DESC, HOURINI DESC;
Check that to_date format depends of your context.

search record using year criteria in hibernate

I need all records which have year entered from search criteria.
for ex: String year = "2012";
In hibernate how it work ?
criteria.add(Restrictions.like("createDate", "%"+year+"%"));
createDate is fetch in format DD-MM-YY from oracle database.
Please suggest..
Try something like:
criteria.add(Restrictions.sqlRestriction("to_char({alias}.CREATE_DATE, 'yyyy') = ?", year, Hibernate.STRING));
I'm assuming that the name of the column mapped to createDate is CREATE_DATE

Hibernate criteria for get records which have year 2012

i need all records which have year entered from search criteria.
for ex:
String year = "2012";
In hibernate it work for
criteria.add(Restrictions.like("createDate", "%"+year+"%"));
createDate is in format DD-MM-YY.
Please suggest..
criteria.add(Restrictions.like("createDate", "%2012%", MatchMode.ANYWHERE));
But I would prefer changing your db field to a date format(its string at the moment?) and performing a greater than comparison (instead of like).
like only applies for the String . For the date field , you can use Restrictions.between() to generate between '01/01/2012 00:00:00' and '12/31/2012 23:59:59' for the where clause
SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
Date fromDate = df.parse("1-1-2012 00:00:00");
Date toDate = df.parse("31-12-2012 23:59:59");
criteria.add(Restrictions.between("createDate", fromDate, toDate));
Also , please note that all the properties used in the Criteria API is the Java property name , but not the actual column name.

Resources