5

I have two entities like this :

public class Client {
  ...
@OneToMany(mappedBy = "client", cascade = { CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.REMOVE },orphanRemoval = true, fetch=FetchType.EAGER)
@Fetch(value = FetchMode.SUBSELECT)
@Cascade({ org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
private List<CompanyContract> companyContracts;
  ...
}

CompanyContract :

public class CompanyContract {

...

@ManyToOne
@JoinColumn(name = "IDCLIENT")
private Client client;

...
}

And I want to delete a companyContract like this :

client.getCompanyContracts().remove(companyContract)
client = clientService.updateClient(client);

But the delete process is not happening

What am I doing wrong ?

EDIT

This is my updateClient method in my DAO :

@Override
@Transactional
public Client updateClient(Client client) {

    return entityManager.merge(client);
}
OddDev
  • 1,521
  • 7
  • 23
  • 45
  • Seems similar https://stackoverflow.com/questions/25125210/hibernate-persistentset-remove-operation-not-working – Chacko Sep 22 '17 at 11:25
  • You have to have both sides in-sync, set `CompanyContract.client` to null. – Chacko Sep 22 '17 at 11:31
  • So what I need to do is remove CompanyContract from the list and then CompanyContract.client to null and Then update the Client ? – OddDev Sep 22 '17 at 11:36
  • Yes, `orphanRemoval` will take care of deleting `CompanyContract` entry – Chacko Sep 22 '17 at 11:46
  • I think `orphanRemoval` has nothing to do in this case. Becasue he want to delete one of `CompanyContract` in `Client` object. Not client and orphans from `CompanyContracts` neither `CompanyContract` and orphan `Client` – Jakub Pomykała Sep 22 '17 at 11:52
  • yes, I have a transaction – OddDev Sep 22 '17 at 15:58

3 Answers3

8

First of all, you don't need set cascadeTypes and @Cascade. I think it might be a source of your problems.

Did you override equals and hashCode in ContractCompany? because maybe you are not removing the desired object from List<ContactCompany>

Look at this

@OneToMany(mappedBy = "client", ...)

mappedBy informs hibernate that client is the owner of this relation, so you need to get client, get a list of clientContracts, remove one (make sure it's removed from the list), update client and object is removed.

Example source code below

CompanyContract toBeRemoved = //companyContract which you want to delete
client.getCompanyContracts().remove(toBeRemoved);
toBeRemoved.client = null;

save both objects, toBeRemoved and client

Jakub Pomykała
  • 2,082
  • 3
  • 27
  • 58
  • I already overrided Equals() and I overrided hashCode() now but it's the same thing, nothing happens – OddDev Sep 22 '17 at 11:35
  • Are you sure that you removing object from the list? Did you tried to remove annotations responsible for cascades? – Jakub Pomykała Sep 22 '17 at 11:40
  • Yes I'm sure, I checked the size of the list before and after the removal, And Yes i've deleted the cascades as you mentionned (I left only the cascadeTypes and deleted @Cascade annotation ) – OddDev Sep 22 '17 at 11:41
  • Remove `cascadeTypes` too, if you omit cascade types argument they are set to all by default. You can also try to set `client` to `null` in `companyContract` which you want to delete. Then you also need to update `companyContract` – Jakub Pomykała Sep 22 '17 at 11:44
  • CompanyContract toBeRemoved = //companyContract which you want to delete client.getCompanyContracts().remove(toBeRemoved); toBeRemoved.client = null; save both object, `toBeRemoved` and `client` – Jakub Pomykała Sep 22 '17 at 11:49
  • Add your last comment to your answer and I'll accept it – OddDev Sep 22 '17 at 15:57
  • Done I also added some more for future viewers :) – Jakub Pomykała Sep 22 '17 at 18:46
  • 1
    This is gold! I was struggling for three days - Thanks! – extensa5620 Oct 20 '20 at 12:50
1

Cascade delete-orphan example If you just want to delete two referenced ‘stockDailyRecords’ records? This is called orphan delete, see example…

1. No delete-orphan cascade
You need to delete the ‘stockDailyRecords’ one by one.

StockDailyRecord sdr1 = (StockDailyRecord)session.get(StockDailyRecord.class,
                                            new Integer(56));
StockDailyRecord sdr2 = (StockDailyRecord)session.get(StockDailyRecord.class,
                                            new Integer(57));

session.delete(sdr1);
session.delete(sdr2);
Output

Hibernate:
    delete from mkyong.stock_daily_record
    where DAILY_RECORD_ID=?
Hibernate:
    delete from mkyong.stock_daily_record
    where DAILY_RECORD_ID=?
  1. With delete-orphan cascade The cascade=”delete-orphan” is declared in ‘stockDailyRecords’ to enable the delete orphan cascade effect. When you save or update the Stock, it will remove those ‘stockDailyRecords’ which already mark as removed.

    Stock stock = (Stock)session.get(Stock.class, new Integer(2));
    stock.getStockDailyRecords().remove(sdr1);
    stock.getStockDailyRecords().remove(sdr2);
    
    session.saveOrUpdate(stock);
    

    Output

    Hibernate: delete from mkyong.stock_daily_record where DAILY_RECORD_ID=? Hibernate: delete from mkyong.stock_daily_record where DAILY_RECORD_ID=?

In short, delete-orphan allow parent table to delete few records (delete orphan) in its child table.

You should be using cascade=”delete-orphan” in order to perform such a task.

Reference

Sadiq Ali
  • 1,272
  • 2
  • 15
  • 22
0

Try it with these annotations:

@OneToMany(mappedBy = "client", cascade = CascadeType.ALL,orphanRemoval = true, fetch=FetchType.EAGER)
private List<CompanyContract> companyContracts;
Asarudeen A
  • 59
  • 1
  • 11