user5567313
user5567313

Reputation:

Persisting object does not persist all its relational objects

I am have three entities with relations look like this:

Here are my Java Classes:

@Entity
@Table
public class Order implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "order_id")
    private long id;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "customer_id", nullable = false)
    private Customer customer;

    @OneToMany(mappedBy = "order")
    private List<Article> orderedArticles;
}

@Entity
@Table
public class Customer implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "customer_id")
    private long id;

    @OneToMany(mappedBy = "customer")
    private List<Order> orders;
}

@Entity
@Table
public class Article implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "article_id")
    private long id;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "order_id", nullable = false)
    private Order order;
}

And then I persist the order to the database:

Customer customer = createCustomer()
List<Article> articles = createArticles();
Order order = new Order(customer, articles)
entityManager.persist(order);

The order and customer were successfully persisted but strangely that the article not. Can anyone help me here what did i do wrong? How can I make one call to persist the order and parallel the customer and article will be also persisted?

Thank you very much!

Upvotes: 0

Views: 65

Answers (2)

SternK
SternK

Reputation: 13111

  1. As it mentioned in this article:

Cascading only makes sense for Parent – Child associations (the Parent entity state transition being cascaded to its Child entities). Cascading from Child to Parent is not very useful and usually, it’s a mapping code smell.

So, for example your Order - Article association should be corrected in this way:

@Entity
@Table
public class Order implements Serializable {

    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
    private List<Article> orderedArticles;
}

@Entity
@Table
public class Article implements Serializable {

    @ManyToOne // CascadeType.ALL should not be used here
    @JoinColumn(name = "order_id", nullable = false)
    private Order order;
}

The same correction should be made for the Customer - Order association.

  1. You use bidirectional @OneToMany. So, as documentation states:

Whenever a bidirectional association is formed, the application developer must make sure both sides are in-sync at all times.

For example your Order entity should have the following methods:

@Entity
@Table
public class Order implements Serializable {

    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
    private List<Article> orderedArticles;

    public void addArticle(Article article) {
        orderedArticles.add(article);
        article.setOrder(this);
    }

    public void removeArticle(Article article) {
        orderedArticles.remove(article);
        article.setOrder(null);
    }
}

to make the bidirectional association Order - Article in-sync. The same correction should be made for the Customer - Order association.


Assuming that your Order and Customer entities have the appropriate helper methods, the valid example of persisting can look like this:

  Article article1 = new Article();
  // ...
  Article article2 = new Article();
  // ...

  Order order = new Order();
  order.addArticle(article1);
  order.addArticle(article2);

  Customer customer = new Customer();
  customer.addOrder(order);
  
  entityManager.persist(customer);

So, you should start from articles creation, then add them to the order (or orders), then add your order (or orders) to the customer entity and then persist the customer. Due to the usage of CascadeType.ALL all children entities will be persisted too.

Upvotes: 0

Alex Yang
Alex Yang

Reputation: 13

Try change

@OneToMany(mappedBy = "order")
private List<Article> orderedArticles;

to

@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private List<Article> orderedArticles;

Upvotes: 1

Related Questions