由于某些原因,当我试图删除有元素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();
}
(警告:我不知道设计者的想法是什么。)
对我来说,自动删除数据是很可怕的。 我稍有误解,就可能导致我没有想到的数据被删除。
当然,在一个精心设计的、教科书式的模式中,数据的结构将是完美的,什么该删,什么不该删,应该是显而易见的。
但教科书式的模式只限于教科书。
有几个变量在起作用。@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)
变化自 @ElementCollection
到 @OneToMany
与预期的级联选项。
移除 nativeQuery = true
并使用JPA查询来代替。它应该是这样的。
@Modifying
@Query("DELETE FROM ProductList list WHERE list.lastUpdated != 0")
void deleteOld();
在您的应用程序中使用Spring Data命名的查询 ProductListRepository
. 类似这样的问题。
deleteByLastUpdatedNot(Date date);
or
deleteByLastUpdatedLessThan(Date date);
在mysql shell中,你无法执行查询,因为你没有设置你的外键。ON DELETE CASCADE 在你的mysql中。添加 ON DELETE CASCADE 到你的外键,会让mysql的shell在删除时级联。
一旦产品的日志被删除,就删除它似乎不合逻辑。
我想结构必须是这样的。
products
(id
INT NOT NULL AUTO_INCREMENT。buy_price
浮动: sell_price
浮动: lastUpdateDate
DATETIME, PRIMARY KEY(id
));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);所以现在当你删除一个产品时,它的日志会被删除。