gpt4 book ai didi

java - Spring jpa多对多惰性删除

转载 作者:行者123 更新时间:2023-11-29 10:44:56 26 4
gpt4 key购买 nike

我正在使用 Spring jpa 和 mysql,我在删除实体时遇到问题,如何以最佳方式做到这一点?

我的实体用户:

@ManyToMany(cascade = CascadeType.REMOVE)
@JoinTable(name = "users_tasks",
joinColumns = {@JoinColumn(name = "user_id")},
inverseJoinColumns = {@JoinColumn(name = "task_id")})
private List<Task> tasks;

我的实体任务:

@ManyToMany(fetch=FetchType.LAZY, mappedBy = "tasks")
private List<User> users = new ArrayList<>();

删除 userServiceImpl 中的用户(我不确定这是否正确,但它有效):

user.setTasks(Collections.emptyList());
userRepository.save(user);
userRepository.delete(user);

删除taskServiceImpl中的任务(不起作用):

task.setUsers(Collections.emptyList());
taskRepository.save(task);
taskRepository.delete(task);

异常(exception):

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<>();

请注意,逆列颠倒了,映射的 by 被删除了,表名是相同的。

另一个值得一提的解决方法是通过使用 ON DELETE CASCADE 更改 users_tasks fks 直接在数据库上管理级联

关于java - Spring jpa多对多惰性删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44769703/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com