简体   繁体   中英

how to delete or save a many to many relationship in hibernate & spring

i have a many to many relationship between 2 tables. below are the two tables with mappings. StaffSearchCriteria is used to search staffs having skills selected. this search criteria is persisted in DB so that we can again lookup it later.

the issue i am facing is that i am not able to properly save this data. i am not understanding the "cascade" part of the mapping. due to which, if i do " Cascade.ALL ", the data is saved properly, but when i delete the search criteria, then it also deletes the Skill entries associated with it, which is wrong. i just want that if i delete Skill, StaffSearchCriteria entry should not get deleted and similarly for the Skill ; Only the selected data should be deleted and its entry in the mapping table. the other table should not be affected by that action.

StaffSearchCriteria

    @Entity
@Table(name = "staff_search_criteria")
@NamedQueries({
    @NamedQuery(name = "StaffSearchCriteria.findAll", query = "SELECT s FROM StaffSearchCriteria s")})
public class StaffSearchCriteria implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Long id;

    @Basic(optional = false)
    @NotNull
    @Column(name = "version")
    private long version;

    @Lob
    @Size(max = 2147483647)
    @Column(name = "description")
    private String description;

    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 200)
    @Column(name = "name")
    private String name;

    @ManyToMany(mappedBy = "staffSearchCriteriaCollection", cascade = {CascadeType.MERGE, CascadeType.PERSIST}, fetch = FetchType.LAZY)
    private Collection<Skill> skillCollection;

==================================================

Skill

@Entity
@Table(name = "skill")
@NamedQueries({
    @NamedQuery(name = "Skill.findAll", query = "SELECT s FROM Skill s")})
public class Skill implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Long id;

    @Basic(optional = false)
    @NotNull
    @Column(name = "version")
    private long version;

    @Lob
    @Size(max = 2147483647)
    @Column(name = "description")
    private String description;

    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 100)
    @Column(name = "name")
    private String name;

    @JoinTable(name = "mission_skill", joinColumns = {
        @JoinColumn(name = "skill_id", referencedColumnName = "id")}, inverseJoinColumns = {
        @JoinColumn(name = "mission_skills_id", referencedColumnName = "id")})
    @ManyToMany(fetch = FetchType.LAZY)
    private Collection<Mission> missionCollection;

    @JoinTable(name = "staff_search_criteria_skill", joinColumns = {
        @JoinColumn(name = "skill_id", referencedColumnName = "id")}, inverseJoinColumns = {
        @JoinColumn(name = "staff_search_criteria_skills_id", referencedColumnName = "id")})
    @ManyToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST}, fetch = FetchType.LAZY)
    private Collection<StaffSearchCriteria> staffSearchCriteriaCollection;

Save method

public StaffSearchCriteria saveStaffSearchCriteria(StaffSearchCriteria staffSearchCriteria) {
        logger.info(" [StaffSearchCriteriaDAOImpl] saveStaffSearchCriteria method called. - staffSearchCriteria = " + staffSearchCriteria);
        Session session = sessionFactory.getCurrentSession();
        session.saveOrUpdate(staffSearchCriteria);
        return staffSearchCriteria;
    }

delete method

 public void deleteStaffSearchCriteria(Long id) {
            logger.info(" [StaffSearchCriteriaDAOImpl] deleteStaffSearchCriteria method called. - id = " + id);
            Session session = sessionFactory.getCurrentSession();
            Query query = session.createQuery("FROM StaffSearchCriteria ssc where ssc.id = " + id);
            if(null != query.uniqueResult()){
                StaffSearchCriteria staffSearchCriteria = (StaffSearchCriteria)query.uniqueResult();
                session.delete(staffSearchCriteria);
            }
        }

Please help me here.What am i doing wrong?

Finally i solved it. what i did was as follows.
1. In controller, i found out which skills were removed from previous saved data.
2. passed that list of Skill as well as the StaffSearchCriteria to the service save method.
3. in Service, i iterated over each skill to be removed and removed the staffSearchCriteria object from it and saved it.
4. then passed the staff search criteria to dao and used saveOrUpdate method.
Below are the code snippets.
1.Controller

List<Skill> skillList2 = new ArrayList<Skill>();
        if(null != request.getParameterValues("skillCollection")){
            for(String skillId : request.getParameterValues("skillCollection")){
                if((!skillId.equals(null)) && skillId.length() > 0){
                    Skill skill = skillService.findSkillById(Long.parseLong(skillId));
                    // skill will be lazily initialized :(
                    // initialize it
                    skill.setStaffSearchCriteriaCollection(staffSearchCriteriaService.getAllStaffSearchCriteriaBySkillId(skill.getId()));
                    // set staff search criteria in each skill. because it is the owner
                    if(null != skill.getStaffSearchCriteriaCollection()){
                        skill.getStaffSearchCriteriaCollection().add(staffSearchCriteria);
                    }else{
                        List<StaffSearchCriteria> staffSearchCriteriaList = new ArrayList<StaffSearchCriteria>();
                        staffSearchCriteriaList.add(staffSearchCriteria);
                        skill.setStaffSearchCriteriaCollection(staffSearchCriteriaList);
                    }
                    skillList2.add(skill);
                }
            }
        }

        staffSearchCriteria.setSkillCollection(skillList2);
        // Remove OLD skills also. plz. :)
        List<Skill> skillList3 = null;
        if(null != staffSearchCriteria && staffSearchCriteria.getId() != null && staffSearchCriteria.getId() > 0){
            // this skillList3 will contain only those which are removed.
            skillList3 = skillService.getAllSkillByStaffSearchCriteriaId(staffSearchCriteria.getId());
            skillList3.removeAll(skillList2);
        }
        // now set staffSearchCriteriacollection and then pass it.
        List<Skill> removedskillList = new ArrayList<Skill>();
        if(null != skillList3){
            for(Skill skill : skillList3){
                skill.setStaffSearchCriteriaCollection(staffSearchCriteriaService.getAllStaffSearchCriteriaBySkillId(skill.getId()));
                removedskillList.add(skill);
            }
        }
        // now pass to service and save these skills after removing this staff search criteria from them.
        staffSearchCriteria = staffSearchCriteriaService.saveStaffSearchCriteria(staffSearchCriteria, removedskillList);

2.Service

if(null != removedskillList && removedskillList.size() > 0){
    for(Skill skill : removedskillList){
        skill.getStaffSearchCriteriaCollection().remove(staffSearchCriteria);
        skillDAO.saveSkill(skill);
    }
}

return staffSearchCriteriaDAO.saveStaffSearchCriteria(staffSearchCriteria);

3.DAO

Session session = sessionFactory.getCurrentSession();
session.saveOrUpdate(staffSearchCriteria);

4.Entity Class - Skill

@JoinTable(name = "staff_search_criteria_skill", joinColumns = {
        @JoinColumn(name = "skill_id", referencedColumnName = "id")}, inverseJoinColumns = {
        @JoinColumn(name = "staff_search_criteria_skills_id", referencedColumnName = "id")})
    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
    private Collection<StaffSearchCriteria> staffSearchCriteriaCollection = new ArrayList<StaffSearchCriteria>();

5.Entity Class - StaffSearchCriteria

@ManyToMany(mappedBy = "staffSearchCriteriaCollection", fetch = FetchType.LAZY, cascade = {CascadeType.ALL})
    private Collection<Skill> skillCollection = new ArrayList<Skill>();

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM