I'm having a strange behavior when I try to update an existing entity. A Order
entity has a time
field, which is set using a java.lang.Date
object (I know the class has been superseded by more advanced ones, but it is good enough for my needs). There is a unique constraint which prevents two Order
s from having the same time
.
If I run the following piece of code:
final Date date = new Date();
customer.getOrders().forEach(order -> {
order.setTime(date);
//two orders cannot have the same time
date.setTime(date.getTime() + 1000);
});
A DataConstraintViolationException
is thrown, because Hibernate tried to persist two different orders with the same time
. However, this should not happen, because each time a Order
's time
is update, the date
object is updated too, setting its time to be one second later - this actually happens, I can see it using the debugger. If I look at the Hibernate's log, however, I see the following:
//first order
binding parameter [5] as [TIMESTAMP] - [Sun Jul 12 11:59:27 CEST 2020]
//second order
binding parameter [5] as [TIMESTAMP] - [Sun Jul 12 11:59:27 CEST 2020]
To me, this means that Hibernate is still using the old value of the date
object, even though it has been updated before.
If I make a slight modification to the previous code, this problem disappears:
final Date date = new Date();
customer.getOrders().forEach(order -> {
//a new Date object is created
order.setTime(new Date(date.getTime()));
//two orders cannot have the same time
date.setTime(date.getTime() + 1000);
});
Here, I create a new Date
object each time I update an entity. This object is created using the same time of the already-existing date
object, which, as stated, is correctly updated each time an entity is updated.
What can be the cause of this strange behaviour? Am I missing something?
final Date date = new Date();
customer.getOrders().forEach(order -> {
order.setTime(date);
//two orders cannot have the same time
date.setTime(date.getTime() + 1000);
});
Date is an object in Java. You create exactly one instance and link this instance to all orders. modifiying this one instance will affect all orders processed in this loop.
your second version (order.setTime(new Date(date.getTime()));) creates a new "Date" instance for each iteration of the loop
when you create a Date object, the time in the object is a constant!
So every time you call date.getTime(), it actually get the date time of the moment you create the Date object.
public class DateTimeTest {
public static void main(final String args[]) throws InterruptedException{
System.out.println("Test case begin");
Date date = new Date();
System.out.println(date.getTime());
TimeUnit.SECONDS.sleep(10);
System.out.println(date.getTime());
}
}
Here is what I have in the console
Test case begin
1594549131082
1594549131082
You can see the time didn't change after 10 seconds sleep
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.