3

I have a Employee and Employee Dept table. One employee can have multiple departments.

I have defined the tables in MySQL and generated the entities using JPA.

package model;

import java.io.Serializable;
import javax.persistence.*;
import java.util.List;

/**
 * The persistent class for the emp1000 database table.
 * 
 */
@Entity
@NamedQuery(name="Emp1000.findAll", query="SELECT e FROM Emp1000 e")
public class Emp1000 implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;

    private String firstName;

    private String lastName;

    //bi-directional many-to-one association to EmpDept
    @OneToMany(mappedBy="emp1000")
    private List<EmpDept> empDepts;

    public Emp1000() {
    }

    public int getId() {
        return this.id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getFirstName() {
        return this.firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return this.lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public List<EmpDept> getEmpDepts() {
        return this.empDepts;
    }

    public void setEmpDepts(List<EmpDept> empDepts) {
        this.empDepts = empDepts;
    }

    public EmpDept addEmpDept(EmpDept empDept) {
        getEmpDepts().add(empDept);
        empDept.setEmp1000(this);

        return empDept;
    }

    public EmpDept removeEmpDept(EmpDept empDept) {
        getEmpDepts().remove(empDept);
        empDept.setEmp1000(null);

        return empDept;
    }

}



@Entity
@Table(name="emp_dept")
@NamedQuery(name="EmpDept.findAll", query="SELECT e FROM EmpDept e")
public class EmpDept implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;

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

    //bi-directional many-to-one association to Emp1000
    @ManyToOne
    @JoinColumn(name="emp_id")
    private Emp1000 emp1000;

    public EmpDept() {
    }

    public int getId() {
        return this.id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getEmpDept() {
        return this.empDept;
    }

    public void setEmpDept(String empDept) {
        this.empDept = empDept;
    }

    public Emp1000 getEmp1000() {
        return this.emp1000;
    }

    public void setEmp1000(Emp1000 emp1000) {
        this.emp1000 = emp1000;
    }

}

When I try to generate to create a Employee object and associated dept objects and save it to database, the child table never gets saved.

public class StoreData {
    public static void main(String[] args) {
        Session session=new AnnotationConfiguration()  
        .configure().buildSessionFactory().openSession();  
          
        //creating transaction object  
        Transaction t=session.beginTransaction();  
        
        
        Emp1000 e1 = new Emp1000();
        e1.setFirstName("Prem");
        e1.setLastName("Anand");
        
        EmpDept d1 = new EmpDept();
        d1.setEmpDept("Maths");
        d1.setEmp1000(e1);
        
        EmpDept d2 = new EmpDept();
        d1.setEmpDept("Science");
        d1.setEmp1000(e1);
        
        ArrayList<EmpDept> deptlist = new ArrayList();
        deptlist.add(d1);
        deptlist.add(d2);
        
        
        e1.setEmpDepts(deptlist);
        
        //session.saveOrUpdate(e1);
        
        session.persist(e1);//persisting the object  
        
          
        t.commit();//transaction is committed  
        
        session.close();  
          
        System.out.println("successfully saved");  
        

    }

    }

The Employee object is created in the table but not the Employee dept objects. What settings do I need to change?

I get a new error after adding @OneToMany(mappedBy="emp1000", cascade = CascadeType.ALL):

Feb 25, 2015 8:43:43 AM org.hibernate.util.JDBCExceptionReporter logExceptions
SEVERE: Field 'id' doesn't have a default value
Exception in thread "main" org.hibernate.exception.GenericJDBCException: could not insert: [model.EmpDept]
    at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91)
Valerio Bozz
  • 1,176
  • 16
  • 32
user1050619
  • 19,822
  • 85
  • 237
  • 413

2 Answers2

7

You need to cascade the persist operation down to child entities. Change empDept mapping to

@OneToMany(mappedBy="emp1000", cascade = CascadeType.ALL)
Predrag Maric
  • 23,938
  • 5
  • 52
  • 68
  • I tried it but get a error.. Given the error in the above post – user1050619 Feb 25 '15 at 13:44
  • What is the database type of column `emp_dept#id`? – Predrag Maric Feb 25 '15 at 13:51
  • I changed the column type to `ID` int(11) NOT NULL **AUTO_INCREMENT**, ie; added AUTO_INCREMENT and it started working...Thanks – user1050619 Feb 25 '15 at 13:52
  • That's why I asked you, `AUTO_INCREMENT` should already be there if you let Hibernate generate the tables automatically. You're welcome, glad you got it working. – Predrag Maric Feb 25 '15 at 13:54
  • One more question..Do I need to explicitly set the department object d1.setEmp1000(e1) even though the departments are related to that Employee- e1.setEmpDepts(deptlist); – user1050619 Feb 25 '15 at 13:54
  • Yes, you should maintain both sides of a bidirectional relationship. – Predrag Maric Feb 25 '15 at 13:56
  • A note: if all you want to do is cascade the persist operation down to child entities, you should use `CascadeType.PERSIST`. This answer almost leads one to believe that `CascadeType.ALL` is the same as `CascadeType.PERSIST`. – teuber789 Apr 05 '18 at 21:51
  • That being said, `CascadeType.ALL` is better for many parent-child relationships bc it will propagate all cascading operations (perist, delete, refresh, etc) down to the child entities. More: https://stackoverflow.com/questions/13027214/jpa-manytoone-with-cascadetype-all – teuber789 Apr 05 '18 at 21:52
1

Use this field annotation:

@Cascade({org.hibernate.annotations.CascadeType.ALL}) 

Instead of using javax.persistence.CascadeType.ALL because there is an issue if you use both Hibernate and JPA together.

Valerio Bozz
  • 1,176
  • 16
  • 32