I am trying to retrieve all record today from an entity class using jpa.
My entity class has a date created property.
public class SingleTripDetails {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private SingleTripDetailsStatus status = SingleTripDetailsStatus.MATCHED;
#CreationTimestamp
private Timestamp dateCreated;
#JsonIgnore
#Column(insertable = false, updatable = true)
#UpdateTimestamp
private Timestamp lastModified;
}
I am trying to get all records by the dateCreated property.
public List<SingleTripDetails> findByStatusAndDateCreated(SingleTripDetailsStatus status, Timestamp date);
I do the following in my data service class
public List<SingleTripDetails> getAmountMadeToday(Date date, String email) {
return driverRiderApplicationRepository.findByStatusAndDateCreated(SingleTripDetailsStatus.ENDED, new Timestamp(date.getTime()));
}
but it does not work. What could I be doing wrong?
handling Date is a very tricky part, a Timestamp can save up to the precision of nanoseconds.
let's look at your repository method
driverRiderApplicationRepository.findByStatusAndDateCreated(
This is going to do an exact match on Status and DateCreated, without knowing data saved in DB, I am just assuming date are being stored with time.
As I understand you want all amount made today, I would suggest (for me safest way)you change your repository method like below
findByStatusAndDateCreatedBetween(Statustype status, Timestamp t1, Timestamp t2)
now
in Timestamp t1: provide a date with time as 00:00
in Timestamp t2: provide the same date with time as 23:59
Related
I have an application that contains some JPA classes that are using LocalDate / LocalDateTime fields and these fields are being mapped into PostgreSQL columns as Bytea.
The greatest problem with this approach is that I can't do queries with SQL, for example, I can't query this: SELECT * FROM star_date BETWEEN '2020-01-01' AND '2020-01-02', because DateTime and date columns using the Bytea type.
Below a have an example of a class that shows my current problem scenery! This class is using JPA to generate the table in PostgreSQL, so it happens automatically. Look at created fiend into class and design of the table.
#Data
#Entity
#Table(name = "processes")
public class Process implements Serializable {
#Id
#GeneratedValue(generator = "ProcessSequenceGenerator")
private Long id;
private Long legacyId;
private String createdBy;
private LocalDateTime created;
}
The table design:
Has somebody ever had an issue like this one?
I'm using Spring Boot 1.4.7.RELEASE! So a fix my problem including into Column the property columnDefinition and a #Convert like below:
#Column(nullable = false, updatable = false, columnDefinition = "TIMESTAMP")
#Convert(converter = LocalDateTimeConverter.class)
private LocalDateTime created;
Right now, I'm looking for a way to convert bytea that is into my current table in postgresql.
I'm using Spring Boot with JPA and Lombok.
My Sample entity contains four dates, the approved date, sample date, and a createdAt and modifiedAt that is maintained by JPA itself with the Auditable class. JPA manages the schema, database running MySQL and all the date columns are DateTime. All Dates are of class java.util.Date.
Sample entity (simplified for reasons)
#Entity
#Data
#EqualsAndHashCode(callSuper = false)
public class Sample extends Auditable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
Integer id;
Date approved;
#DateTimeFormat(pattern = "yyyy-MM-dd'T'H:m")
Date sampleDate;
}
The DateTimeFormat on the sampleDate is to help Spring convert form-data to a java.util.Date.
Auditable.java
#MappedSuperclass
#EntityListeners(AuditingEntityListener.class)
public class Auditable {
#CreatedDate
#Column(name = "created_at", updatable = false, nullable = false)
#Temporal(TemporalType.TIMESTAMP)
private Date createdAt;
#LastModifiedDate
#Column(name = "modified_at")
#Temporal(TemporalType.TIMESTAMP)
private Date modifiedAt;
}
When my controller performs this:
Sample s = sampleRepository.getOne(id);
s.setApproved(new Date());
sampleRepository.save(s);
Spring Generates this error message:
com.mysql.cj.jdbc.exceptions.MysqlDataTruncation: Data truncation: Data too long for column 'approved' at row 1
You would better use LocalDateTime instead of java.util.Date or java.sql.Date, if you are doing this with java >= 8.
Audited entities' createdDate, lastModifiedDate should be set by Jpa Auditor(framework), not by client(in this context, you).
Also, you can try #Temporal(TemporalType.DATE) instead of TemporalType.TIMESTAMP if you want to keep your code.
Updated
Sorry about I missed what exact subject you raised.
Just try add #Temporal(TemporalType.DATE) above Date approved;.
So the backstory of this problem: I have created an event calendar that allows events to span multiple days. In my DB i have a table for the event and i have a table called event_dates, which is just event_id and date.
To retrieve the rows correctly with the event dates i do an INNER JOIN on EVENT_DATES (event_id)
The return from the db is correct, the row contains all of the information about the event along with the 'date' column tacked on at the end.
My domain for Event class:
#Data
#Entity
#Table(name="events")
#SecondaryTable(name = "event_date", pkJoinColumns=#PrimaryKeyJoinColumn(name="event_id", referencedColumnName="event_id"))
#RequiredArgsConstructor
public class Event {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name="event_id")
private Long id;
private String eventTitle;
private String eventCategory;
private String eventType;
#Column(table="event_date", name="date", columnDefinition = "DATE", unique=true)
private LocalDate date;
#Column(table="event_date", name="event_date_id")
private Long eventDateId;
private boolean allDayEvent;
#Column(name = "start_time", columnDefinition = "TIME")
private LocalTime startTime;
#Column(name = "end_time", columnDefinition = "TIME")
private LocalTime endTime;
private String timezone;
private boolean onlineEvent;
private String city;
private String state;
private String country;
private String language;
private String description;
private boolean register;
private String registrationLink;
private boolean multiDay;
}
Here is where the issue occurs:
While the db is returning every row along with the correct dates (no duplicate days),
spring data is creating the first row as an entity with the first date, but then when it hits the next row it sees that the ID for the event is the same as the previous entity and it just copies that entity over again in the array, it never checks to see if the date is unique for that entity. The dates never change and it's important that it does or my api returns events happening over and over again on the same day (correct amount of duplicates however haha).
So the return value from spring is the correct number of entries but the dates for each entity remain the same because it's not checking that the event_id and date fields are unique to each entity being added to the array of return results.
Ive seen using #UniqueConstraint but the problem is that the #UniqueConstraints span two tables, not the same table, and I haven't found any examples that show how to configure for this type of situation.
I'm like 95% there I just need the dates for each entity to be unique!
I am developing a CRUD application in Spring boot and Hibernate. I have a table called Order. This table has two columns called status (integer) and datetime (which of type mysql datetime). In my application, I regulary update that status column's value in one of the rows.
When I do this, something weird happens. The status column is updated for that record, however, the datetime column is also being updated, which I don't even instruct. After each update to a row, datetime is set to 3 hours earlier than the previous value of its.
I am developing this application in Java's Spring Boot and Spring Boot JPA MySQL. I am using JPA repositories. Here is the snipped that makes the update:
public String incrementOrderStatus(Long orderId) {
Order order = orderRepository.findOne(orderId);
OrderState nextState = order.getState().next();
order.setState(nextState);
orderRepository.save(order);
return nextState.toString();
}
An Order has the following attributes:
#Data
#Entity
#Table(name = "`order`")
#NoArgsConstructor
#AllArgsConstructor
public class Order {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(nullable = false, updatable = false)
private Long id;
private String name;
private Calendar datetime;
#Enumerated(EnumType.ORDINAL)
private OrderState state;
private String address;
private String phoneNumber;
private String email;
#Enumerated(EnumType.ORDINAL)
private OrderSource source;
private Float totalPrice;
#ManyToOne(optional = true)
private Offer offerUsed;
private String notes;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "order", fetch = FetchType.LAZY)
private List<MealOrderDescriptor> meals;
public Order(CustomOrderView orderView) {
this.name = orderView.getName();
this.datetime = Calendar.getInstance(TimeZone.getTimeZone("Europe/Istanbul"));
this.state = OrderState.PENDING;
this.address = orderView.getAddress();
this.phoneNumber = orderView.getPhoneNumber();
this.source = orderView.getSource();
this.totalPrice = orderView.getTotalPrice();
this.notes = orderView.getNotes();
}
}
In the JDBC query string I also set the timezone to my timezone, which is serverTimezone=Europe/Istanbul. I am using a MySQL version of 5.7.19 and JDBC version is 6.0.6, Java 1.8 and Spring Boot 1.5.9 and in an Ubuntu 16.04.3
Thanks in advance.
Even though you don't call order.setDatetime() before orderRepository.save(order);, datetime field contains value received by orderRepository.findOne(orderId).
After that, orderRepository.save(order); statement tries to update datetime field with the value received by orderRepository.findOne(orderId). If it is minus 3 hours from the previous value then it is likely a TimeZone problem.
I think, if you use TIMESTAMP type instead of DATETIME this situation will disappear. Because MySQL DATETIME type does not hold TimeZone information.
MySQL converts TIMESTAMP values from the current time zone to UTC for storage, and back from UTC to the current time zone for retrieval. (This does not occur for other types such as DATETIME.)
You can check official documentation.
I have a SQLServer and am using hibernate to map an entity to a table that I already have.
the table has a field of type "timestamp" [field_date] timestamp NOT NULL which is the only date the table has.
I have tried mapping it on an entity like this:
#Column(name="field_date")
private Date date;
and even
#Column(name="field_date",columnDefinition="TIMESTAMP")
private Date date;
but every time I try to do a select on that entity I get an SQLServerException of type
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: The conversion from timestamp to TIMESTAMP is unsupported.
1) Try mapping it to the Java class java.sql.Timestamp.
http://docs.oracle.com/javase/7/docs/api/java/sql/Timestamp.html
Also here I would try removing this from your annotation
columnDefinition="TIMESTAMP"
2) Here is another mapping to try.
So alternatively you can try this approach.
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "CreatedOn", nullable = false)
public Date getCreatedOn() {
return this.createdOn;
}
public void setCreatedOn(Date createdOn) {
this.createdOn = createdOn;
}
3) This is like 2) but it is to be used if you want
mapping for the class field (not for the getter).
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "Last_Updated_Date", nullable=false)
private Date lastUpdatedDate;