【问题标题】:@OneToMany delete children@OneToMany 删除孩子
【发布时间】:2017-09-22 11:06:22
【问题描述】:

我有两个这样的实体:

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;
  ...
}

公司合同:

public class CompanyContract {

...

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

...
}

我想像这样删除公司合同:

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

但删除过程没有发生

我做错了什么?

编辑

这是我的 DAO 中的 updateClient 方法:

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

    return entityManager.merge(client);
}

【问题讨论】:

  • 你必须让双方同步,设置CompanyContract.client为null。
  • 那么我需要做的是从列表中删除 CompanyContract ,然后将 CompanyContract.client 设置为 null 然后更新 Client ?
  • 是的,orphanRemoval 将负责删除 CompanyContract 条目
  • 我认为orphanRemoval 在这种情况下与此无关。因为他想删除Client 对象中的CompanyContract 之一。不是来自CompanyContracts 的客户和孤儿,也不是CompanyContract 和孤儿Client

标签: java spring hibernate


【解决方案1】:

首先,您不需要设置cascadeTypes@Cascade。我认为这可能是您问题的根源。

override equalshashCodeContractCompany 吗?因为也许您没有从 List&lt;ContactCompany&gt; 中删除所需的对象

看看这个

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

mappedBy 通知 hibernate 客户端是这个关系的所有者,所以你需要获取client,获取clientContracts 的列表,删除一个(确保它已从列表),更新客户端和对象被删除。

下面的示例源代码

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

保存两个对象,toBeRemovedclient

【讨论】:

  • 我已经覆盖了 Equals() 并且我现在覆盖了 hashCode() 但它是同一件事,没有任何反应
  • 您确定要从列表中删除对象吗?您是否尝试删除负责级联的注释?
  • 是的,我确定,我在删除前后检查了列表的大小,是的,我已经删除了你提到的级联(我只留下了 cascadeTypes 并删除了 @Cascade 注释)
  • 也删除cascadeTypes,如果您省略级联类型参数,它们默认设置为全部。您也可以尝试将要删除的companyContract 中的client 设置为null。那你还需要更新companyContract
  • 这是金子!我挣扎了三天 - 谢谢!
【解决方案2】:

级联删除-孤儿示例 如果您只想删除两个引用的“stockDailyRecords”记录?这称为孤儿删除,请参见示例……

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. 使用删除孤儿级联 在 ‘stockDailyRecords’ 中声明了 cascade="delete-orphan" 以启用删除孤儿级联效果。当您保存或更新 Stock 时,它将删除那些已标记为已删除的“stockDailyRecords”。

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

    输出

    休眠: 从 mkyong.stock_daily_record 中删除 DAILY_RECORD_ID=? 休眠: 从 mkyong.stock_daily_record 中删除 DAILY_RECORD_ID=?

简而言之,delete-orphan 允许父表在其子表中删除少量记录(delete orphan)。

您应该使用 cascade=”delete-orphan” 来执行这样的任务。

Reference

【讨论】:

  • 但是我用的是orphanRemoval = true,不一样吗?
【解决方案3】:

试试这些注释:

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

【讨论】:

  • 同样的,删除过程没有发生
  • 去掉@Fetch注解试试
猜你喜欢
  • 2011-01-01
  • 2015-05-05
  • 2017-06-23
  • 2015-11-03
  • 1970-01-01
  • 2020-11-14
  • 2022-08-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多