i am trying out derived entities using @JoinedColumns,
let me show you my code,
below is the sql code,
create table TBL_EMPLOYEE_FIVE(
EMP_ID integer ,
NAME varchar(50),
COUNTRY varchar(50),
MGR_ID integer,
MGR_COUNTRY varchar(50),
constraint PK_COMPOSIT_001AD primary key(EMP_ID,COUNTRY),
constraint FK_COMPO_00123 foreign key(MGR_ID,MGR_COUNTRY) references TBL_EMPLOYEE_FIVE
)
this is the code below for the mapped entity,
package com.entities.derived;
@Entity
@Table(name="TBL_EMPLOYEE_FIVE")
@IdClass(EmployeeId.class)
public class EmployeeOne implements Serializable{
// contructors
@Id
@Column(name="EMP_ID")
private Integer employeeId;
@Id
@Column(name="COUNTRY")
private String empCountry;
@Column(name="NAME")
private String employeeName;
@ManyToOne( cascade= {CascadeType.PERSIST, CascadeType.PERSIST},
fetch= FetchType.LAZY,
targetEntity=EmployeeOne.class)
@JoinColumns({
@JoinColumn(name="MGR_ID",referencedColumnName="EMP_ID"),
@JoinColumn(name="MGR_COUNTRY",referencedColumnName="COUNTRY")
})
private EmployeeOne manager;
@OneToMany(cascade={CascadeType.PERSIST, CascadeType.PERSIST},mappedBy="manager")
private Set<EmployeeOne> employees;
// getters, setters, hashcode and equals implementation
}
this is the code below for the class id,
@Embeddable
public class EmployeeId implements Serializable{
public EmployeeId(){}
public EmployeeId(Integer employeeId,String empCountry){
this.employeeId = employeeId;
this.empCountry = empCountry;
}
private Integer employeeId;
private String empCountry;
// getters, hashcode and equals implementation
}
the code written in main method and which works properly without Exception is as follows,
for persisting new Employee,
private static int generateId(EntityManager em,String country)throws Exception{
Query q = em.createQuery("select max(e.employeeId) from EmployeeOne e where e.empCountry = '"+country+"'");
List list = q.getResultList();
int count = 0;
if(list != null && list.size() > 0){
count = Integer.parseInt(String.valueOf((list.get(0) != null) ? list.get(0) : "0"));
}
count++;
return count;
}
inserting new employee,
private static void insertEmployee2(EntityManager em) throws Exception{
EmployeeOne manager = new EmployeeOne("Rajkumar Bahadur", "NEPAL");
manager.setEmployeeId(generateId(em, manager.getEmpCountry()));
Set<EmployeeOne> employees = new HashSet<EmployeeOne>();
int count = generateId(em, "FIJI");
employees.add(new EmployeeOne(count,"Okajima Fahim","FIJI",manager));
employees.add(new EmployeeOne(++count,"Jabulani Xitwo","FIJI",manager));
manager.setEmployees(employees);
em.persist(manager);
}
for fetching the employees is ,
private static void getEmployees(EntityManager em) throws Exception{
EmployeeOne manager = em.find(EmployeeOne.class, new EmployeeId(3,"CHINA"));
Set<EmployeeOne> employees = manager.getEmployees();
for(EmployeeOne emp : employees){
System.out.println(emp);
}
}
All the above methods run fine.
But the only code which doesn't works is merge, the code is as follows
private static void updateEmployee(EntityManager em) throws Exception{
EmployeeOne manager = em.find(EmployeeOne.class, new EmployeeId(3,"CHINA"));
Set<EmployeeOne> employees = manager.getEmployees();
int count = generateId(em, "IRAN");
employees.add(new EmployeeOne(count,"Zaid Khan","IRAN",manager));
employees.add(new EmployeeOne(++count,"Maqbool Ansari","IRAN",manager));
em.merge(manager);
}
the exception which i get is ,
javax.persistence.EntityNotFoundException: Unable to find com.entities.derived.EmployeeOne with id com.entities.derived.EmployeeId@226b19
at org.hibernate.ejb.Ejb3Configuration$Ejb3EntityNotFoundDelegate.handleEntityNotFound(Ejb3Configuration.java:155)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:210)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:251)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:148)
....
Can you please tell me where i am going wrong
Change
@ManyToOne( cascade= {CascadeType.PERSIST, CascadeType.PERSIST},
fetch= FetchType.LAZY,
targetEntity=EmployeeOne.class)
To
@ManyToOne( cascade= {CascadeType.PERSIST, CascadeType.MERGE},
fetch= FetchType.LAZY,
targetEntity=EmployeeOne.class)
You need to cascade the creation of EmployeeOne instances when the parent is "updated" (merged). By changing the @ManyToOne annotation to include CascadeType.MERGE, you should achieve this.