2 years ago
#44441
Vinz
Java when Instantiating 2 new objects any change to the first is applied to the second
I have a Booking object that contains two Places objects in that way :
@Entity @Table(name = "booking", schema = "public")
public class Booking {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToOne(cascade = CascadeType.ALL,orphanRemoval = true)
@JoinColumn(name = "pickup_place_id", referencedColumnName = "id")
private Place pickUpPlace;
@OneToOne(cascade = CascadeType.ALL,orphanRemoval = true)
@JoinColumn(name = "dropoff_place_id", referencedColumnName = "id")
private Place dropOffPlace;
}
For the Place Object :
@Entity @Table(name = "place", schema = "public")
public class Place {
public enum PlaceType{
PICKUP,
STOP,
DROPOFF,
}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Enumerated(EnumType.STRING)
@Column(name = "place_type", nullable = false)
private Place.PlaceType placeType;
@Column(name = "google_place_id", nullable = true, length = 100)
private String googlePlaceId;
@JoinColumn(name = "city_id", referencedColumnName = "id", nullable = false)
@ManyToOne(fetch = FetchType.LAZY)
private City city;
@Column(name = "lat", nullable = true)
private Double lat;
@Column(name = "lon", nullable = true)
private Double lon;
}
then in a controller when populating a new booking I instantiate the places like this :
Booking booking = new Booking();
booking.setPickUpPlace(new Place(city, googlePlaceId , Place.PlaceType.PICKUP));
booking.setDropOffPlace(new Place(city, googlePlaceId , Place.PlaceType.DROPOFF));
at a later stage in the controller I happen to update the booking PickUp Place city with :
booking.getPickUpPlace().setCity(otherCity);
and the result was that both the pickupPlace and the dropOffPlace of the booking end up with the otherCity asigned to them.
Then I started to add logs at several stages in the controller and when logging the objects pickUpPlace and dropOffPlace just after instantiating I got the same result :
com.myapp.domain.Place@2af
com.myapp.domain.Place@2af
The same object hash code, which seemed to be normal to me because the objects were not yet persisted to DB yet and therefore without id, and the default HashCode only uses the id and the version number of the saved object...
Just to be sure the issue was not there I overrode the HashCode (){} and equals(){} of the Place Object with a more complete hash and equal taking into account all the properties of the object... and here, magic, the issue disappeared and the 2 instantiated objects are correctly differentiated and a change in one is not done in the other one anymore.
So my issue is solved. Only By luck I would say as the 2 instantiated Place happen to have the PlaceType with a a different value, but what if I had to instantiate 2 objects with same initial values ? (which will happen when I will start to add PlaceType.STOPS to the booking... those will be instantiated with the same initial values)
I don't like to solve an issue without understanding where the problem really was... Does this mean that in Java when instantiating 2 objects, not yet persisted, with the same properties they in fact point to the same object in memory ? Or is there an architectural problem in my project ?
Thanks in advance to Java Experts for a quick explaination of the observed phenomena for a Java noob...
java
jpa
zk
0 Answers
Your Answer