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).
Related
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()
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.
We have a case, where we require only the day and the month and thus would use the java.time.MonthDay (Javadocs) to represent that information.
We are aware that we could create our own JPA object for persistence or just use the java.sql.Date object, but that generally requires an unrequired year information.
Another way is to call the method .atYear(int) (Javadoc) (with a fictitious year) on it and receive a java.time.LocalDate (Javadoc), which can be easily converted to java.sql.Date. But this is prone to missunderstandings in the future (and also persist the year information).
Is there some "elegant"/supposed solution for this case? Or is there a replacement for SQL that supports the whole new date and time API for Persistence.
Another case would be java.time.YearMonth (Javadoc).
Thanks for reading!
Since SQL databases don't have a type compatible with MonthDay, use a VARCHAR columns, and simply use toString() and MonthDay.parse().
Or use a custom DateTimeFormatter, if you don't like the --12-03 format.
The default format will correctly sort, as a string.
here are the code snippets:
// column define:
#Column(name = "date", columnDefinition = "mediumint", nullable = false)
#Convert(converter = MonthDayIntegerAttributeConverter.class)
protected MonthDay date;
// converter define:
public class MonthDayIntegerAttributeConverter implements AttributeConverter<MonthDay, Integer> {
#Override
public Integer convertToDatabaseColumn(MonthDay attribute) {
return (attribute.getMonthValue() * 100) + attribute.getDayOfMonth();
}
#Override
public MonthDay convertToEntityAttribute(Integer dbData) {
int month = dbData / 100;
int day = dbData % 100;
return MonthDay.of(month, day);
}
}
How can I persist a jodatime YearMonth object to a sql database?
#Entity
public class MyEntity {
private YearMonth date; //how to persist?
//some more properties
}
I want later to be able to pick all entities by a specific month.
The better question is how do you intend to use the data in the database? Generally you want to store dates in databases using data types supported by the target database as opposed to strings or composite integers. That would allow you to use the built in database date/time functions and validations as opposed to needing to implement that logic in your application.
You can certainly add methods to your entity to convert to/from jodatime values to your entity for the parts of your application that need it.
You need a javax.persistence.Converter for this (see How to convert java.util.Date to Java8 java.time.YearMonth):
#Entity
public class MyEntity {
#Convert(converter = YearMonthConverter.class)
private YearMonth date; //how to persist?
//some more properties
}
The following is an example converter for Java8 java.time.YearMonth to java.utilDate. You need to change java.time.YearMonth to org.joda.time.YearMonth and use the appropriate methods to convert to/from the desired type:
(imports omitted):
#Converter(autoApply = true)
public class YearMonthConverter implements AttributeConverter<YearMonth, Date> {
#Override
public Date convertToDatabaseColumn(YearMonth attribute) {
// uses default zone since in the end only dates are needed
return attribute == null ? null : Date.from(attribute.atDay(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
}
#Override
public YearMonth convertToEntityAttribute(Date dbData) {
// TODO: check if Date -> YearMonth can't be done in a better way
if (dbData == null) return null;
Calendar calendar = Calendar.getInstance();
calendar.setTime(dbData);
return YearMonth.of(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1);
}
}
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;