Reputation: 23
I am trying to insert a record with onetomany relationship tables usinf casecadeALL. When any DML happens on table I have audit info with insert , update or delete entry in audit table. When I am running insert it is inserting record fine in base tables but during audit I see child table have 2 entry for single insert. It is updating the table with the same record. Not able to understand why casecade all is updating the same record in few milliseconds.
parent class
public class Department
{
/** The destination id. */
@Id
@SequenceGenerator(name = ....", sequenceName = ...)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = ....)
@Column(name = "DEST_ID", nullable = false, unique = true)
private Long destinationId;
/** The destination name. */
@Column(name = "DEST_NM")
private String destinationName;
/** The Std UTC hour operation . */
@OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY)
@JoinColumn(name = "DEST_ID", nullable = false)
private List<Hours> hrList = new ArrayList<Hours>();
}
child class
public class Hours
{
@Id
@SequenceGenerator(name = ...., sequenceName = ....)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = ....)
@Column(name = "HR_ID")
private Long hoursId;
/** The Destination. */
@ManyToOne(optional = true)
@JoinColumn(name = "DEST_ID", nullable = false, insertable = false, updatable = false)
private Department department;
}
in service class calling -
departmentDao.saveOrupdate(department);
in DAO layer
public void saveOrUpdate(Department departmentToStore) {
em.persist(departmentToStore);
}
I have other related tables as well but they are working fine. I have this issue only with tables oneToMany relationship.
Note: Tables are unidirectional. I am using persist method to insert the record.
Please find whole code -
@Entity
@Table(name = "DEPARTMENT")
@XmlRootElement(name = "Department")
public class Department {
/** The destination id. */
@Id
@SequenceGenerator(name = "deptSeq", sequenceName = "SEQ1")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "deptSeq")
@Column(name = "DEST_ID", nullable = false, unique = true)
private Long destinationId;
/** The destination name. */
@Column(name = "DEST_NM")
private String destinationName;
/** The hour operation . */
@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, mappedBy = "department")
private List<Hours> hoursList = new ArrayList<Hours>();
setter & getters ...
}
@Entity
@Table(name = "HOURS")
@XmlRootElement(name = "SpecialHoursOfOperation")
public class SpecialUTCHoursOfOperation {
/** The hour id. */
@Id
@SequenceGenerator(name = "hourSeq", sequenceName = "SEQ2")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "hourSeq")
@Column(name = "HR_ID")
private Long hourId;
/** The Destination. */
@ManyToOne(optional = true)
@JoinColumn(name = "DEST_ID", nullable = false, insertable = false, updatable = false)
private Department department;
/** The hoursdate. */
@Column(name = "SPEC_HR_OPRT_DT")
private Date HoursDate;
setters and getters
}
DepartmentDAOImpl class -
@Override
@Transactional
public Department saveOrUpdate(Department departmentToStore) {
Department department = new Department();
try {
department = persist(departmentToStore);
} catch (PersistenceException pe) {
pe.getMessage();
}
return department;
}
in DeptService.java
public DepartmentVO storeDepartment(DepartmentVO departmentVO){
Department department = new Department();
department = Helper.populateDepartment(departmentVO);
department.setHoursList(Helper.populateHours(departmentVO, department));
department = departmentDAO.saveOrUpdate(department);
return departmentVO;
}
in Helper.java
public static Department populateDepartment(final DepartmentVO departmentVO) {
Department department = new Department();
department.setDestinationName(departmentVO.getDepartmentName());
return department;
}
public static List<Hours> populateHours(final DepartmentVO departmentVO, final Department department) {
List<Hours> hoursList = new ArrayList<Hours>();
List<HoursVO> hoursVOs = departmentVO.getSpecialDayHourVOs();
for (HoursVO hoursVO : hoursVOs) {
Hours hoursObj = new Hours();
hoursObj.setDepartment(department);
hoursObj.setHoursDate(hoursVO.getSpecialDate());
hoursList.add(hoursObj);
}
return hoursList;
}
DB tables - Department (dest_id(pk), dest_nm), Hours (hr_id(pk), dest_id(fk), hr_dt).
then I have rest layer to communicate with front end. If I run this code When debugger reached to save method it throws exception. UniqueCOnstraintviolation ORA-01400: cannot insert NULL into (HOURS."DEST_ID")
Upvotes: 2
Views: 2584
Reputation: 1485
if you are using some interceptor to log audit info, this problem happens due to uni-directional mapping. normally your Department should have used a mappedBy and Hours should have used a ref to Department with joinColumn. that will make it bi-directional. then on save it will not fire extra update queries. you can read more about inverse=true/false on internet and uni-directional pit-falls for jpa. change to bi-di to prevent extra update queries.
Upvotes: 3