JPA select entities with date below parameter - java

I'm trying to select all entities where the value of the date field is below a given argument. However, my code doesn't seem to work.
SomeEntity.java
#Entity
public class SomeEntity {
#Id #GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private ZonedDateTime date = ZonedDateTime.now(ZoneId.of("UTC"));
}
SomeEntityRepository.java
public interface SomeEntityRepositoryextends CrudRepository<SomeEntity, Long> {
/**
* Get all SomeEntity created before :until
*/
#Query("Select e from SomeEntity e where e.date < :until")
List<SomeEntity> findAllUntil(#Param("until") ZonedDateTime until);
}
My problem is this:
I will have a SomeEntity object where the date is 2019-08-31T10:00:00.000+02:00 and the value of until is 2019-08-24T10:00:00.000+02:00 (seven days earlier)
However, the object is still returned from the query.
I am using PostgreSQL 9.6

Not every JDBC driver supports it. You can use one of following solutions:
Use TimeStamp instead of ZonedDateTime.
Use proper driver and follow its configuration requirements. For instance, for Oracle you may need to specify converter:
#Convert(converter=OracleZonedDateTimeSeriliazer.class)
private ZonedDateTime date = ZonedDateTime.now(ZoneId.of("UTC"));
For other databases you may need to implement such a convertor and specify it via #Convert.

Related

JPA repository find by a date field only for a certain month

I have an entity that has a LocalDateTime field. I want to query these entities by the month of this date field. I have the following query:
List<MyEntity> findAllByDate_MonthValue(Integer monthValue)
This does not work, it produces the following error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myEntityRepository': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalArgumentException: Failed to create query for method public abstract java.util.List MyEntityRepository.findAllByDate_MonthValue(Integer)! Illegal attempt to dereference path source [null.date] of basic type
I don't get the error, I tried other approaches and none worked. Moreover, I tried to use the #Query annotation, but I don't have the YEAR/MONTH/etc... and neither EXTRACT functions.
You can't use a reference to a month.
You need to convert your query in something like:
findAllByDateBetween
this method will take two dates that are used as minor and major limit of the query. So you need to create a method to get the first day of month and first day of next month to correctly call this method.
A complete list of all keywords accepted in the JPA methods is available here and the reference to the Between keyword is the following:
Keyword Example JPQL Snippet
---------------------------------------------------
Between findByStartDateBetween ... where x.startDate between ?1 and ?2
Assuming that you are using Hibernate as the ORM provider, you can use HQL and a query similar to this in order to extract the month value from a given date and compare it to a given integer value. Consider the following example:
Entity class
#Table(name = "SomeEntity")
#Entity(name = "SomeEntity")
#Data
public class SomeEntityClass {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String someColumn;
#Basic
private ZonedDateTime someDate;
}
And the following repository interface:
Repository
public interface SomeEntityRepository extends JpaRepository<SomeEntityClass, Long> {
#Query(
name = "SomeEntityClass.findAllByMonth",
value = "SELECT E FROM SomeEntity E WHERE MONTH(E.someDate) = :monthValue"
)
List<SomeEntityClass> findAllByMonth(#Param("monthValue") Integer monthValue);
}
I hope this is something that is useful to you.

spring boot repository: check if Date exists

In my reservation-entity i have a column "bookingDate" --> example: "2021-05-10 12:00:00".
So in this object the date and starttime of an user-booking gets displayed.
If a user wants to book a timeslot, i want to check first if the selected timeslot is empty. So i want to query the database by date&startTime.
I tried it with https://www.baeldung.com/spring-data-jpa-query-by-date , but it didnt work. I got the errors: "The annotation #Temporal is disallowed for this location" & "#Temporal cant be used for variables"
these are the relevant classes:
Reservation.java
#Entity
public class Reservation {
#Id #GeneratedValue
private int reservationId;
#DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
private LocalDateTime bookingDate;
private int court = 1;
private String playerNames;
private int userIdReservation;
//getter and setters
With the method "findByBookingDate()" i want to query the database, if the selected timeslot is empty...
VerificationClass.java
public boolean validateReservation(Reservation r) {
LocalDateTime tempDate = r.getBookingDate();
if(reservationRepository.findByBookingDate(tempDate)){ // todo: + and Court
logger.getLogger().info(this.getClass().getName() + "||Booking Slot is empty -- Reservation created||");
return true;
}
logger.getLogger().info(this.getClass().getName() + "||Booking Slot is full -- Reservation failed||");
return false;
}
ReservationRepository.java
#Repository
#Repository
public interface ReservationRepository extends JpaRepository<Reservation, Integer>{
#Query("Select r from reservation r where r.booking_date = :tempDate")
boolean findByBookingDate(#Param("tempDate") LocalDateTime tempDate);
}
If I run it like this i always get an "org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'backyardcodersSpringReactApplication'" --> so the application does not successfully start up.
Im very thankful for every tip and critique!
cheers!
Not understood completely. this is just a lead maybe not a perfect solution.
You can use java.time.LocalDateTime . and annotation be like #DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME).
And the query should be like. [the query will check all the reservation for that day]
Select
from reservation_table
Where
timeSlot between ‘2021-05-10 00:00:00’ and ‘2021-05-10 23:59:59’
I copied your code in my local file. Instead of
import org.springframework.data.jpa.repository.Temporal;
I used
import javax.persistence.Temporal;
in your Reservation.java file.
Also this is my very first answer on Stackoverflow.
First of all #Temporal have three different arguments and it can be applied to the variable of type date , time and time stamp.
Usage
#Temporal(Temporal type.DATE)
private Date date;
#Temporal(Temporal type.TIMESTAMP) // INSERT BOTH DATE WITH TIME TILL MILLISECONDS
private Calendar date;
Why not just just extract the localdate from your LocalDateTime and pass it on? and extract the hour and pass it on and query 2 different columns with it.
LocalDateTime.toLocalDate()
LocalDateTime.getHour()

How to design a data model which is having a date range?

In my Spring application I need to design a data model which is having date range. Is there any data type which can be used?
Currently I did something like this.
#Entity
#Table(name = "scheduled_period")
public class ScheduledPeriod {
private Date oneDay;
private Date fromDate;
private Date toDate;
}
I want to put fromDate and toDate together in to something like dateRange
Best solution is yours, by using LocalDate.
By using two LocalDate to Start Date and End Date.
and working with them, see:
HQL / JPA find available items between date range
some DBMS's like PostgreSQL has datatype named: daterange
for example:
CREATE TABLE reservation (room int, during daterange);
INSERT INTO reservation VALUES
(1108, '[2010-01-01 14:30, 2010-01-01 15:30)');
but Java (JPA) does not support datarange data type.
If you generate that table into Entity, it generated to Object.
private Object during;
public Object getDuring() {
return this.during;
}
public void setDuring(Object during) {
this.during = during;
}
finally, if you persist to use rangedate, you can define a new class (Entity) named RangeDate with two LocalDates or use array of LocalDate (if your DMBS support it).

Hibernate UserType to map #Formula result to non-entity custom object

Using Hibernate 3.5.3:
In the database is a function (that uses Oracle's pipelined table functions) which returns a number of rows and values when supplying the ID of the entity. (This function is part of legacy code which can't be changed).
Result example:
select * from table(DateOptions_Function('ID_OF_ENTITY'));
OPTION DATE
-----------------------
startDate 2012/09/01
endDate 2013/04/01
otherDate 2011/01/01
I want to map the result of a #Formula (containing the above SQL) to an object on the entity.
public class DateOptions {
private LocalDate startDate;
private LocalDate endDate;
private LocalDate otherDate;
// getters and setters omitted
}
I want to map it like so in the entity:
#Formula("(select * from table(DateOptions_Function(ENTITY_ID)))")
#Type(type = "mypackage.DateOptionsUserType")
public DateOptions getDateOptions() {
return dateOptions;
}
I have tried creating a Hibernate UserType with the hope of creating a DateOptions object using the ResultSet in nullSafeGet(...).
I specify the sql types in my DateOptionsUserType
public int[] sqlTypes() {
return new int[] {Types.VARCHAR, Types.DATE};
}
I keep getting the following exception on startup though:
org.hibernate.MappingException: property mapping has wrong number of columns: mypackage.MyEnity.dateOptions type: mypackage.DateOptionsUserType (I have also tried CompositeUserType with the same result).
Any idea what might be causing the issue? Is it even possible (mapping a #Formula to custom non-entity object)?
since you basicly have 3 fields with a formula i would see if executing the function 3 times is still fast enough
#Formula("(select DATE from table(DateOptions_Function(ENTITY_ID))) WHERE option='startDate'")
private LocalDate startDate;
#Formula("(select DATE from table(DateOptions_Function(ENTITY_ID))) WHERE option='endDate'")
private LocalDate endDate;
#Formula("(select DATE from table(DateOptions_Function(ENTITY_ID))) WHERE option='otherDate'")
private LocalDate otherDate;

Java: JPA classes, refactoring from Date to DateTime

With a table created using this SQL
Create Table X (
ID varchar(4) Not Null,
XDATE date
);
and an entity class defined like so
#Entity
#Table(name = "X")
public class X implements Serializable {
#Id
#Basic(optional = false)
#Column(name = "ID", nullable = false, length = 4)
private String id;
#Column(name = "XDATE")
#Temporal(TemporalType.DATE)
private Date xDate; //java.util.Date
...
}
With the above, I can use JPA to achieve object relational mapping. However, the xDate attribute can only store dates, e.g. dd/MM/yyyy.
How do I refactor the above to store a full date object using just one field, i.e. dd/MM/yyyy HH24:mm?
If you want to also store time information at the database level, use TemporalType.DATETIME:
#Column(name = "XDATE")
#Temporal(TemporalType.DATETIME)
private Date xDate; //java.util.Date
Use a TIMESTAMP column type at the database level (and xDate will be stored as 'yyyy-MM-dd HH:mm:ss.S').
Have you tried changing the #Temporal value to TemporalType.DATETIME? java.util.Date and java.sql.Date both store date and time components, the TemporalType controls which part JPA stored/pays attention to; date, time, or both.

Categories

Resources