简体   繁体   中英

Hibernate many-to-one delete only child

Where are a lot of similar topics but i still can't handle it myself, sorry.

So, i have object "Bank" which is a parent of an "Office" .
I am trying to delete single Office, but then i do it, all offices of parent bank are being deleted.
Here's the code:
Bank

@Entity
@Table(name = "BANKS")
public class Bank {
    public Bank() {
    }

    public Bank(String name) {
        this.name = name;
    }

    @Id
    @Column(name = "ID")
    @GeneratedValue
    private int id;

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

    @OneToMany(mappedBy = "bank", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
    @JoinColumn(name = "BANK_ID")
    private List<Office> officeList;

Office

@Entity
@Table(name = "OFFICES")
public class Office {
    public Office() {
    }

    public Office(String city, String address, String workingHours, Bank bank) {
        this.city = city;
        this.address = address;
        this.workingHours = workingHours;
        this.bank = bank;
    }

    @Id
    @Column(name = "ID")
    @GeneratedValue
    private int id;

        @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.REMOVE)
    @JoinColumn(name = "BANK_ID")
    private Bank bank;

    @Column(name = "CITY")
    private String city;

    @Column(name = "ADDRESS")
    private String address;

    @Column(name = "WORKING_HOURS")
    private String workingHours;

And OfficeDAO

@Repository
@Transactional
public class OfficeDAOImpl implements OfficeDAO {

    @Autowired
    private SessionFactory sessionFactory;

    @Override
    public Office getByOffice_ID(int Office_ID) {
        return (Office) sessionFactory.getCurrentSession().get(Office.class, Office_ID);
    }

    @Override
    public List<Office> getAllOffice() {
        Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Office.class);
        return criteria.list();
    }

    @Override
    public int save(Office Office) {
        return (Integer) sessionFactory.getCurrentSession().save(Office);
    }

    @Override
    public void update(Office Office) {
        sessionFactory.getCurrentSession().merge(Office);
    }

    @Override
    public void view(Office Office) {
        sessionFactory.getCurrentSession().merge(Office);
    }

    @Override
    public void delete(int Office_ID) {
        Office s = getByOffice_ID(Office_ID);
        System.out.println("trying to delete" + Office_ID);
        sessionFactory.getCurrentSession().delete(s);
    }

}

Hibernate query trace then deleting only office:

Hibernate: delete from offices where id=?
Hibernate: delete from offices where id=?
Hibernate: delete from offices where id=?
Hibernate: delete from offices where id=?
Hibernate: delete from offices where id=?
Hibernate: delete from offices where id=?
Hibernate: delete from offices where id=?
Hibernate: delete from offices where id=?
Hibernate: delete from offices where id=?
Hibernate: delete from offices where id=?
Hibernate: delete from offices where id=?
Hibernate: delete from offices where id=?
Hibernate: delete from offices where id=?
Hibernate: delete from offices where id=?
Hibernate: delete from offices where id=?
Hibernate: delete from offices where id=?
Hibernate: delete from offices where id=?
Hibernate: delete from offices where id=?
Hibernate: delete from banks where id=?

What am i doing wrong? Any advice will be much appreciated.

UPDATE

If i delete cascade = CascadeType.REMOVE from office, hibernate won't send any delete request.

You should to configure CascadeType in wright way...

All - is not the best choice in your case. Try DETACH or REMOVE . It should help :)

More about CascadeType can be found here .

I've found the issue. It looks like hibernate can't remove child entity while it is in parent list, so just add this to delete method in office:

s.getBank().getOfficeList().remove(s);

And yeah, Cascade.Remove at office should not exist.

An explanation why we have such behavior.

Bank is a parent of the officeList , so that makes sense to delete officeList if we delete Bank .

@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.REMOVE)
@JoinColumn(name = "BANK_ID")
private Bank bank;

This annotation means that Office is a parent of Bank too

So if we delete Office -> we should delete Bank -> we should delete all offices of the Bank and the Bank itself.

We see it in the logs

Hibernate: delete from offices where id=?
Hibernate: delete from offices where id=?
Hibernate: delete from banks where id=?  

Also we can't use @JoinColumn here, if we have mappedBy (with Hibernate 5).

@OneToMany(mappedBy = "bank", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
@JoinColumn(name = "BANK_ID")
private List<Office> officeList; 

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