SHaaD
SHaaD

Reputation: 139

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.

Upvotes: 3

Views: 6631

Answers (3)

v.ladynev
v.ladynev

Reputation: 19956

An explanation why we have such behavior.

Bank is a parent of the officeList, so that makes sense to delete officeListif 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; 

Upvotes: 0

SHaaD
SHaaD

Reputation: 139

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.

Upvotes: 1

svichkar
svichkar

Reputation: 1856

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.

Upvotes: 1

Related Questions