views:

59

answers:

1

Hello,

I am working with JPA and I would like to persist an object (Action) composed of an object (Domain).

There is the Action class code:

@Entity(name="action")
@Table(name="action")
public class Action {

  @Id
  @GeneratedValue(strategy=GenerationType.IDENTITY)
  @Column(name="num")
  private int num;

  @OneToOne(cascade= { CascadeType.PERSIST, CascadeType.MERGE,
      CascadeType.REFRESH })
  @JoinColumn(name="domain_num")
  private Domain domain;

  @Column(name="name")
  private String name;

  @Column(name="description")
  private String description;

  public Action() {
  }

  public Action(Domain domain, String name, String description) {
    super();
    this.domain=domain;
    this.name=name;
    this.description=description;
  }

  public int getNum() {
    return num;
  }

  public Domain getDomain() {
    return domain;
  }

  public String getName() {
    return name;
  }

  public String getDescription() {
    return description;
  }
}

When I persist an action with a new Domain, it works. Action and Domain are persisted. But if I try to persist an Action with an existing Domain, I get this error:

javax.persistence.EntityExistsException: 
Exception Description: Cannot persist detached object [isd.pacepersistence.common.Domain@1716286]. Class> isd.pacepersistence.common.Domain Primary Key> [8]

How can I persist my Action and automatically persist a Domain if it does not exist? If it exists, how can I just persist the Action and link it with the existing Domain.

Best Regards,

FF

A: 

From the exception that you posted, it looks like you are trying to use a detached Domain object with a new Action object. Before persisting the Action, you'll need to reattach the Domain object using the EntityManger.merge method:

domainObject = entityManager.merge(domainObject);
Action action = new Action(domainObject, "name", "description");
entityManager.persist(action);

If you want to handle both cases described in your question, you can use merge instead of persist on the Action object. The merge method will persist the new Action, and will re-attach or persist the Domain object (since you have Cascade.MERGE specified).

Action action = new Action(domainObject, "name", "description");
action = entityManager.merge(action);

Just remember to use the new instance of the Domain object associated with the Action after the merge. If you are going to use the domain object after merging the Action object, be sure to do something like this:

domainObject = action.getDomain();
Jim Hurne
The first solution you gave me did not work in my case. The second works perfectly! Thanks the answer!FF
Fleuri F