Java Spring jpa多对多延迟删除

Java Spring jpa多对多延迟删除,java,mysql,spring,hibernate,jpa,Java,Mysql,Spring,Hibernate,Jpa,我使用的是SpringJPA和mysql,我在删除实体方面遇到了问题,如何以最佳方式进行删除 我的实体用户: @ManyToMany(cascade = CascadeType.REMOVE) @JoinTable(name = "users_tasks", joinColumns = {@JoinColumn(name = "user_id")}, inverseJoinColumns = {@JoinColumn(name = "task_id")}) pri

我使用的是SpringJPA和mysql,我在删除实体方面遇到了问题,如何以最佳方式进行删除

我的实体用户:

@ManyToMany(cascade = CascadeType.REMOVE)
@JoinTable(name = "users_tasks",
        joinColumns = {@JoinColumn(name = "user_id")},
        inverseJoinColumns = {@JoinColumn(name = "task_id")})
private List<Task> tasks;
删除taskServiceImpl中的任务(它不工作):

例外情况:

java.sql.SQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`testdb`.`users_tasks`, CONSTRAINT `FK7todmyl52eiddpi6hc2nfgvbs` FOREIGN KEY (`task_id`) REFERENCES `tasks` (`task_id`))
我的jpa配置:

@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();    
dataSource.setDriverClassName(
env.getRequiredProperty("database.driver");
dataSource.setUrl(env.getRequiredProperty("database.url"));
dataSource.setUsername(env.getRequiredProperty("database.password"));
dataSource.setPassword(env.getRequiredProperty("database.username"));
return dataSource;
}

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
    factory.setDataSource(dataSource());
    factory.setPackagesToScan("com.taskmanager");
    factory.setJpaVendorAdapter(vendorAdapter);
    factory.setJpaProperties(additionalProperties());
    return factory;
}

@Bean
public JpaTransactionManager transactionManager() {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
    return transactionManager;
}

@Bean
public DataSourceInitializer dataSourceInitializer(DataSource dataSource) {
    DataSourceInitializer initializer = new DataSourceInitializer();
    initializer.setDataSource(dataSource);
    initializer.setDatabasePopulator(databasePopulator());
    return initializer;
}

private Properties additionalProperties() {
    Properties properties = new Properties();
    properties.put("hibernate.dialect", env.getRequiredProperty("hibernate.dialect"));
    properties.put("hibernate.show_sql", env.getRequiredProperty("hibernate.show_sql"));
    properties.put("hibernate.hbm2ddl.auto", env.getRequiredProperty("hibernate.hbm2ddl.auto"));
    properties.put("hibernate.enable_lazy_load_no_trans",
            env.getRequiredProperty("hibernate.enable_lazy_load_no_trans"));
    return properties;
}

private DatabasePopulator databasePopulator() {
    ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
    populator.addScript(dataScript);
    return populator;
}

帮助我找到最佳的删除方法,我的设置拼写正确吗?谢谢

在您的示例中,表
User
是关系的所有者,这就是为什么在更新用户的任务时,Hibernate会删除任务列表

解决此问题的一个方法是通过在任务实体上设置联接表,使两个实体都成为关系的所有者:

@ManyToMany(fetch=FetchType.LAZY)
@JoinTable(name = "users_tasks",
    joinColumns = {@JoinColumn(name = "task_id")},
    inverseJoinColumns = {@JoinColumn(name = "user_id")})
private List<User> users = new ArrayList<>();
@ManyToMany(fetch=FetchType.LAZY)
@JoinTable(name=“users\u tasks”,
joinColumns={@JoinColumn(name=“task_id”)},
inverseJoinColumns={@JoinColumn(name=“user\u id”)})
private List users=new ArrayList();
请注意,反向克隆是反向的,映射的被删除,表名是相同的


另一个值得一提的解决方法是直接在数据库上管理级联,方法是使用DELETE cascade

@alexuio上的
更改
用户任务
fk,然后将其标记为答案,在我的回答中,这是投票部分的勾号。你为什么要级联删除一个
@ManyToMany
关联?一个任务可能针对多个用户,但是如果任务只针对一个用户,如果用户被删除,那么该任务将对任何人都不可用,并且应该被删除…这意味着你永远不能依靠级联删除来完成它的工作,你总是需要手动删除内容我在问题中写道,我不确定这是否是最好的解决方案,你能提供正确的解决方案吗?
java.sql.SQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`testdb`.`users_tasks`, CONSTRAINT `FK7todmyl52eiddpi6hc2nfgvbs` FOREIGN KEY (`task_id`) REFERENCES `tasks` (`task_id`))
@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();    
dataSource.setDriverClassName(
env.getRequiredProperty("database.driver");
dataSource.setUrl(env.getRequiredProperty("database.url"));
dataSource.setUsername(env.getRequiredProperty("database.password"));
dataSource.setPassword(env.getRequiredProperty("database.username"));
return dataSource;
}

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
    JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
    factory.setDataSource(dataSource());
    factory.setPackagesToScan("com.taskmanager");
    factory.setJpaVendorAdapter(vendorAdapter);
    factory.setJpaProperties(additionalProperties());
    return factory;
}

@Bean
public JpaTransactionManager transactionManager() {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
    return transactionManager;
}

@Bean
public DataSourceInitializer dataSourceInitializer(DataSource dataSource) {
    DataSourceInitializer initializer = new DataSourceInitializer();
    initializer.setDataSource(dataSource);
    initializer.setDatabasePopulator(databasePopulator());
    return initializer;
}

private Properties additionalProperties() {
    Properties properties = new Properties();
    properties.put("hibernate.dialect", env.getRequiredProperty("hibernate.dialect"));
    properties.put("hibernate.show_sql", env.getRequiredProperty("hibernate.show_sql"));
    properties.put("hibernate.hbm2ddl.auto", env.getRequiredProperty("hibernate.hbm2ddl.auto"));
    properties.put("hibernate.enable_lazy_load_no_trans",
            env.getRequiredProperty("hibernate.enable_lazy_load_no_trans"));
    return properties;
}

private DatabasePopulator databasePopulator() {
    ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
    populator.addScript(dataScript);
    return populator;
}
@ManyToMany(fetch=FetchType.LAZY)
@JoinTable(name = "users_tasks",
    joinColumns = {@JoinColumn(name = "task_id")},
    inverseJoinColumns = {@JoinColumn(name = "user_id")})
private List<User> users = new ArrayList<>();