简体   繁体   中英

Hibernate using old object value for binding

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM