我有一个参与者可以注册课程的情况。
基本上,我有以下实体配置(省略了getters和setters以及其他无用的属性) :
@Entity
@Table(name = "course")
public class Course {
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "course")
private Set<Registration> registrations;
}
@Entity
@Table(name = "participant")
public class Participant {
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "participant")
private Set<Registration> registrations;
}
@Entity
@Table(name = "registration")
public class Registration {
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "course_id")
private Course course;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "participant_id")
private Participant participant;
@PreRemove
private void removeRegistrationFromHolderEntities() {
course.getRegistrations().remove(this);
participant.getRegistrations().remove(this);
}
}
然后,我可以从视图模型中删除注册或课程(我还删除了不必要的内容):
@Command
public void deleteRegistration(Registration reg) {
registrationMgr.delete(reg);
}
@Command
public void deleteCourse(Course crs) {
courseMgr.delete(crs);
}
问题:
我也不能删除引用从delete注册
方法(而不是@PreRemove
),因为参与者注册是延迟加载(将引发未能延迟初始化角色的集合:…,无法初始化代理-没有会话
异常)。
这里最好的方法是什么?
我用Java 11搭配Spring Boot 1.0.4(还有spring-boot-starter-data-jpa)。
编辑:
管理器/存储库或以这种方式定义(对于注册
和参与者
也是如此),因此它应该是事务性的(我的主类上没有@EnableTransactionManagement
,但不应该是必需的,因为我不在存储库之外使用事务):
@Transactional
@Component("courseMgr")
public class CourseManager {
@Autowired
CourseRepository courseRepository;
public void saveOrUpdate(Course course) {
courseRepository.save(course);
}
public void delete(Course course) {
courseRepository.delete(course);
}
}
public interface CourseRepository extends CrudRepository<Course, Long> {
...
}
编辑2:
我想我找到了一个非常简单的解决方案:
我已经从实体中删除了@PreRemove
方法,然后没有在 deleteRegistration
方法中删除这样的引用(我已经尝试过但导致无法延迟初始化角色异常集合
):
@Command
html" target="_blank">public void deleteRegistration(Registration reg) {
reg.getCourse().getRegistrations().remove(reg);
reg.getParticipant.getRegistrations().remove(reg);
registrationMgr.delete(reg);
}
我只是将parents设置为null,我不在乎它会被删除...
@Command
public void deleteRegistration(Registration reg) {
reg.setCourse(null);
reg.setParticipant(null);
registrationMgr.delete(reg);
}
因此,现在我也可以删除课程,而无需触发@PreRemove
中的并发修改异常
。
编辑3:我的错,注册没有用上面的解决方案删除(仍然没有错误,但没有发生任何事情)。我以这样的方式结束,这终于奏效了:
@Command
public void deleteRegistration(Registration reg) {
// remove reference from course, else delete does nothing
Course c = getRegistration().getCourse();
c.getRegistrations().remove(getRegistration());
courseMgr.saveOrUpdate(c);
// delete registration from the database
registrationMgr.delete(reg);
}
无需从参与者中删除引用…
好的解决方案非常简单。
我确实需要从< code>deleteRegistration方法中移除引用。这是我曾经尝试过的,但导致< code >无法延迟初始化角色集合异常:
@Command
public void deleteRegistration(Registration reg) {
reg.getCourse().getRegistrations().remove(reg);
reg.getParticipant.getRegistrations().remove(reg);
registrationMgr.delete(reg);
}
诀窍在于,在尝试删除注册之前,我还必须保存课程实体。
这是有效的:
@Command
public void deleteRegistration(Registration reg) {
// remove reference from course, else delete does nothing
Course c = getRegistration().getCourse();
c.getRegistrations().remove(getRegistration());
courseMgr.saveOrUpdate(c);
// delete registration from the database
registrationMgr.delete(reg);
}
无需从参与者中删除引用…
< code>@PreRemove正在做这项工作,但这样我现在也可以删除课程,而不会触发< code > ConcurrentModificationException 。
您未正确设置存储库。您需要一个用于注册
的复合 PK,并且您需要了解双向映射实际上仅用于查询。此外,课程
和参与
中的双向映射带来了挑战,因为默认情况下,通过注册
实体的 ManyToOne
关系是 FetchType.EAGER
。有了所有的级联
和获取
注释,你要求JPA对事情进行复杂的组合,看起来你还没有全部解决。从基础知识开始,一定要打印你的SQL语句,如果你想尝试从JPA中获得更多的技巧,从那里开始。
@Entity
@Data
public class Course {
@Id
private Integer id;
private String name;
}
@Entity
@Data
public class Participant {
@Id
private Integer id;
private String name;
}
@Entity
@Data
public class Registration {
@EmbeddedId
private RegistrationPK id;
@ManyToOne
@MapsId("participant_id")
private Participant participant;
@ManyToOne
@MapsId("course_id")
private Course course;
}
@Embeddable
@Data
public class RegistrationPK implements Serializable {
private static final long serialVersionUID = 1L;
private Integer course_id;
private Integer participant_id;
}
是您的基本实体
。注册库
需要额外的查询。
public interface RegistrationRepository extends JpaRepository<Registration, RegistrationPK> {
Set<Registration> findByCourse(Course c);
}
在一个示例中使用所有这些:
@Override
public void run(String... args) throws Exception {
create();
Course c = courseRepo.getOne(1);
Set<Registration> rs = read(c);
System.out.println(rs);
deleteCourse(c);
}
private void create() {
Course c1 = new Course();
c1.setId(1);
c1.setName("c1");
courseRepo.save(c1);
Participant p1 = new Participant();
p1.setId(1);
p1.setName("p1");
participantRepo.save(p1);
Registration r1 = new Registration();
r1.setId(new RegistrationPK());
r1.setCourse(c1);
r1.setParticipant(p1);
registrationRepo.save(r1);
}
private Set<Registration> read(Course c) {
return registrationRepo.findByCourse(c);
}
private void deleteCourse(Course c) {
registrationRepo.deleteAll( registrationRepo.findByCourse(c) );
courseRepo.delete(c);
}
我正在这里学习“带有链接实体生命周期的双向多对多”教程https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/hibernate_user_guide.html#associations-many-to-many。但是,我使用的是Spring JPA而不是实体管理器。当我使用repository接口删除一个地址时,这并不是不删除
Im使用JPA、MySQL和Spring boot 我一辈子都搞不清楚如何应用级联,文档似乎没有应用我的意图: 例如。https://hellokoding.com/deleting-data-with-jpa-hibernate/使用CascadeType。ALL或CascadeType。删除父实体时,删除子实体的REMOVE属性。它们可以在@OneToOne、@OneTo很多、@ManyToO
我的实体。ValidationStep与documentDetail有一对一的关系,documentDetail与documentValidations有一个完全的关系 我的删除查询 父ValidationStep被删除,但是docDetail和documentValidations仍然在数据库中。
在我的项目中,我使用Spring数据jpa。我有多对多关系的表格。我的实体: 和零件: 现在在Controller中,我尝试从表部分中删除一行: 但我有例外: 区分完整性约束冲突:“FK9Y4MKICYBLJWPENACP4298I49:PUBLIC.PARTS外键(ID\u导出)引用PUBLIC.EXPORT(ID)(1)”;SQL语句:/*删除com.aleksandr0412.demo.en
DataUpload实体 DataUpload存储库 为了删除数据上传,我尝试执行存储库的两个查询方法:
问题内容: 假设我们有3个Entities对象类: 如何使用JPA2.x(或hibernate)批注来: 父级删除时(一对多)自动删除所有子级 删除后自动从子级列表中删除子级(多对一) 儿童删除时(一对一)自动删除玩具 我正在使用Hibernate 4.3.5和mysql 5.1.30。 谢谢 问题答案: 如本文所述, 实体状态转换应从父级到子级联,而不是相反。 您需要这样的东西: