Reputation: 170
In my application a user places an order and sets the billing address to one of the address mapped with him. Now in future he edits that address.So my order will map to that updated address.
My Order entity
@Entity
public class Orders{
...
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
@OneToOne
private Address address;
...
}
Address entity
@Entity
@Table(name = "address")
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String address1;
...
}
Person entity
@Entity
public class Person{
...
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Set<Address> addresses = new HashSet<>();
...
}
I want my Order entity to have a copy of the Address as it was during the creation of the order.Any changes in the Address by user in his profile, after order creation should have no impact on that Order.
Upvotes: 0
Views: 619
Reputation: 2040
I assume you allow user to pick the address from his address list(Person#address), so when you submit your order it contains the address that is already on database, including the id
that creates a relationship, does not create an record:
{
user: {
id: 10,
email: "[email protected]"
},
address: {
id: 10,
street: "5th Av"
}
}
If you want to "have a copy of the Address" then you should first update your relationship in Order
class like:
@OneToOne(cascade = CascadeType.ALL)
private Address address;
Then send the address without id
, that would indicate your repository to create a new entry into database.
Json option:
{
user: {
id: 10,
email: "[email protected]"
},
address: {
street: "5th Av", ...
}
}
Or by removing the id
on controller:
@PostMapping("/submit-order")
public Order submitOrder( @RequestBody Order order) {
// Remove Order#id to detatch current record and enforce create a new one
order.getAddress().setId(null);
return this.orderRepository.save(order);
}
This way your order has an exclusive copy of address.
ERROR: org.springframework.orm.jpa.JpaSystemException with message "Address was altered from 1 to null"
If you receive this error is because you are removing the id of the entity within the scope of a transaction or session. You should create a copy of the entity out of that scope or use entity manager to detach the entity, here is a example.
@embeddable solution
Another solution would be to use an embeddable object instead, that way you can store the address fields on order table but have them as a composite object:
First you create an order address object with all required fields and mark it with @Embeddable
annotation:
@Embeddable
public class AddressOrder {
@Column("street")
private String street;
@Column("postal_code")
private String po;
@Column("city")
private String city;
@Column("country")
private String country;
// Getters and setters
}
Then you use the object on your order table as an attribute and mark it with @Embedded
annotation.
@Entity
public class Orders {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;
@Embedded
private AddressOrder address;
// Getters and setters
}
You need to choose the solution according to the database approach you want to use.
Upvotes: 1