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: "user@stackoverflow.com"
},
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: "user@stackoverflow.com"
},
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.