Java Spring级联元素集合删除

问题描述 投票:1回答:2

由于某些原因,当我试图删除有元素collection的父元素时,我的delete没有级联,这两个类如下。

@Entity
@Table(name="Timestamps")
@JsonIgnoreProperties(ignoreUnknown = true)
public class ProductList {
    private boolean success;
    @Id
    private Date lastUpdated;

    private String time = "minute";

    @ElementCollection
    @MapKeyColumn(name="product_id")
    @CollectionTable(name="Products")
    private Map<String,Product> products;

And:

@Embeddable
@JsonIgnoreProperties(ignoreUnknown = true)
public class Product{
    @Embedded
    private Status quick_status;

目前这是我在这个类中唯一的字段 因为我已经删除了所有其他的字段 我想弄清楚为什么当我试图删除一个父对象的时候 下面是我正在运行的查询。

DELETE FROM Timestamps list WHERE list.last_updated !=0;

last_updated的值永远是非零,所以我只是用这个查询来测试删除,但即使我在mysql shell中运行查询,我也得到 "Cannot delete or update a parent row: a foreign key constraint fails"(无法删除或更新父对象的行:一个外键约束失败),我想元素集注解应该是自动级联的,是不是我遗漏了什么?

EDIT,当下面是Hibernate发送的sql命令时,你会注意到在第三条命令中缺少了级联。

Hibernate: create table products (product_list_last_updated datetime(6) not null, buy_price float not null, sell_price float not null, product_id varchar(255) not null, primary key (product_list_last_updated, product_id)) engine=InnoDB
Hibernate: create table timestamps (last_updated datetime(6) not null, success bit not null, time varchar(255), primary key (last_updated)) engine=InnoDB
Hibernate: alter table products add constraint FKo31ur4gpvx1d5720rgs3qaawi foreign key (product_list_last_updated) references timestamps (last_updated)

EDIT 2:下面是我对ProductListRepository类的@Query,我在查询上包含了删除的相关内容。

@Repository
public interface ProductListRepository extends CrudRepository<ProductList, Integer>{
    @Modifying
    @Query(value = "DELETE FROM Timestamps list WHERE list.last_updated !=0", nativeQuery = true)
    void deleteOld();
}
mysql spring spring-boot cascade cascading-deletes
2个回答
0
投票

(警告:我不知道设计者的想法是什么。)

对我来说,自动删除数据是很可怕的。 我稍有误解,就可能导致我没有想到的数据被删除。

当然,在一个精心设计的、教科书式的模式中,数据的结构将是完美的,什么该删,什么不该删,应该是显而易见的。

但教科书式的模式只限于教科书。


0
投票

有几个变量在起作用。@ElementCollection 有一定的局限性。请看。https:/en.wikibooks.orgwikiJava_PersistenceElementCollection。

使用 ElementCollection 而不是 OneToMany 的局限性在于,目标对象不能独立于其父对象进行查询、持久化、合并。它们是严格的私有(依赖)对象,与嵌入式映射相同。 ElementCollection上没有级联选项,目标对象总是和父对象一起被持久化、合并、删除。 ElementCollection仍然可以使用获取类型,并且和其他集合映射一样,默认为LAZY。

它的工作原理是 productRepository.deleteAll() 工作。

为什么用原生查询不能用?因为本地查询是 "原样 "执行的,这意味着它不会考虑实体中的注释。

另外,因为它被注解了以下内容 @ElementCollection 它不包括任何 ON DELETE CASCADE 在你 constraint foreign key

也就是这个 alter table... 没有 ON DELETE CASCADE

alter table products add constraint FKo31ur4gpvx1d5720rgs3qaawi foreign key (product_list_last_updated) references timestamps (last_updated)

建议的解决办法1

变化自 @ElementCollection@OneToMany 与预期的级联选项。

建议的解决方案2

移除 nativeQuery = true 并使用JPA查询来代替。它应该是这样的。

@Modifying
@Query("DELETE FROM ProductList list WHERE list.lastUpdated != 0")
void deleteOld();

建议的解决方案3

在您的应用程序中使用Spring Data命名的查询 ProductListRepository. 类似这样的问题。

deleteByLastUpdatedNot(Date date);
or 
deleteByLastUpdatedLessThan(Date date);

0
投票

在mysql shell中,你无法执行查询,因为你没有设置你的外键。ON DELETE CASCADE 在你的mysql中。添加 ON DELETE CASCADE 到你的外键,会让mysql的shell在删除时级联。

一旦产品的日志被删除,就删除它似乎不合逻辑。

我想结构必须是这样的。

  • CREATE TABLE products(id INT NOT NULL AUTO_INCREMENT。buy_price 浮动: sell_price 浮动: lastUpdateDate DATETIME, PRIMARY KEY(id));
  • CREATE TABLE timestamps(id INT NOT NULL AUTO_INCREMENT。product INT非空。success BIT NOT NULL。updateDate DATETIME NOT NULL,PRIMARY KEY (id)、 FOREIGN KEY (product) 参考文献 products(id) ON DELETE CASCADE);

所以现在当你删除一个产品时,它的日志会被删除。

© www.soinside.com 2019 - 2024. All rights reserved.