user2680919
user2680919

Reputation: 23

JPA- onetomany casecade inserting same record twice in child table

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

Answers (1)

Ashish Thukral
Ashish Thukral

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

Related Questions