3

I have 2 tables. One is called Employee, and the other is called Phones, and an employee can have multiple Phones.

Employee Class:

@Entity
@Table(name = "employee")
public class Employee {

    @Id
    @Column(name = "id", unique = true, nullable = false)
    @GeneratedValue(strategy = javax.persistence.GenerationType.IDENTITY)
    private Integer id;

    @Column(name = "name", unique = true, nullable = false, length = 25)
    private String name;

    @OneToMany(mappedBy="owner", fetch= FetchType.EAGER, orphanRemoval=true, cascade={CascadeType.ALL})
    private List<Phone> phones;

Phone class:

@Entity
@Table(name = "phone")
public class Phone {

    @Id
    @Column(name = "id", unique = true, nullable = false)
    @GeneratedValue(strategy = javax.persistence.GenerationType.IDENTITY)
    private long id;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "employee_id")
    private Employee owner;

    @Column(name = "phone_type", nullable = false, length = 25)
    private String phoneType;

    @Column(name = "phone_number", nullable = false, length = 25)
    private String phoneNumber;

Suppose I want to add a phone to an existing employee. I am doing this:

Phone phone = new Phone();
phone.setOwner(employee);
phone.setPhoneNumber("999-555-0001");
phone.setPhoneType("home");
employee.getPhones().add(phone);        
dao.merge(employee); // Is it possible to get this to both persist new phones and update existing phones that were changed?

I'm not sure how to merge new phones in, given that some of the phones in the phoneSet have already been persisted. Must I persist each phone manually? An example would be greatly appreciated. I looked into cascading but I can't seem to get it to work. The error I'm receiving is: java.lang.IllegalStateException: An entity copy was already assigned to a different entity.

user64141
  • 5,141
  • 4
  • 37
  • 34
  • Do you receive an error? Can you post it? Also I assume you have omitted the getter and setter methods for each field which are required. – Kevin Bowersox Nov 09 '12 at 00:48
  • for cascading add [cascade = CascadeType.ALL, orphanRemoval = true] in your @OneToMany annotation – willome Nov 09 '12 at 15:23
  • Do you have any @Transactional somewhere ? – willome Nov 09 '12 at 15:23
  • Seems to be a bug in Hibernate 4.1.3+. This doesn't happen in Hibernate 4.1.0. See: https://hibernate.onjira.com/browse/HHH-7605?focusedCommentId=48872&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-48872 – Mohsen Nov 23 '12 at 11:57

1 Answers1

2

I think the issue may be in your join column annotation in the Phone class. You are specifying a join column of employee_id yet in the Employee class the @Column annotation for the id field is mapped to the column id.

Try changing/synchronizing the join columns:

@ManyToOne(fetch = FetchType.EAGER, targetEntity=your.package.here.Employee.class)
@JoinColumn(name = "id")
private Employee owner;

or

Employee.java

@Id
@Column(name = "employee_id", unique = true, nullable = false)
@GeneratedValue(strategy = javax.persistence.GenerationType.IDENTITY)
private Integer id;

Phone.java

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "employee_id", targetEntity=your.package.here.Employee.class)
private Employee owner;
Kevin Bowersox
  • 93,289
  • 19
  • 159
  • 189
  • 1
    The name of the join column in the Phone table does not need to match the name of the primary key column in the Employee table, in fact the original mappings in the question seem correct. Besides, targetEntity is only needed in the Employee entity if the List were untyped (not using generics), and is only specified in relationship annotations (@OneToMany, @ManyToMany, etc.). – German Apr 25 '13 at 17:54