简体   繁体   中英

Hibernate: How do I persist order related information

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.

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.

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