我有一个带数据库的webapp,其中两个实体具有多对多关系,但我手动实现了连接表。当其中一个实体被删除时,它会删除连接表中的所有条目并更新另一个实体,这样所有条目都可以正常工作,但现在我应该为此功能编写一个测试。对于测试,我使用的是内存数据库,这是唯一的区别,相同的注释(和级联类型)的相同方法被调用,但我一直在:
org.hibernate.exception.ConstraintViolationException: integrity constraint violation: foreign key no action; FKC17477FD8940DF2B table ENTITY1_ENTITY2
我没有粘贴任何代码,因为我不相信它有任何问题,因为它正在工作。我没有要求为我解决这个问题,我只需要知道可能会导致这种行为的原因,因为我的想法已经用完了,我不知道还有什么可以搜索为...谢谢
编辑:这里有一些代码:@Entity
@Table(name = "interviewer")
public class Interviewer implements Identifiable {
@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name = "interviewer_id")
private Collection<InterviewerTechnology> technologies;
}
@Entity
@Table(name = "technology")
public class Technology implements Identifiable {
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "technology_id")
private Collection<InterviewerTechnology> technologies;
}
@Entity
@Table(name = "interviewer_technology")
public class InterviewerTechnology implements Identifiable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@ManyToOne(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
private Interviewer interviewer;
@ManyToOne(cascade = CascadeType.MERGE, fetch = FetchType.EAGER)
private Technology technology;
}
@Component
public class TechnologyDao extends AbstractEntityDao<Technology> {
public void remove(Integer id) {
Technology technology = find(id);
em.remove(technology);
}
}
这段代码完全符合我的要求,看起来用于测试的数据库看起来没有看到完成所有工作的CascadeType参数
答案 0 :(得分:0)
我发现了问题,它是@Transactional
注释。我的所有测试DAOs
都扩展了使用DAO
注释的通用测试@Transactional
,并且我再次使用它盲目地注释每个DAO
。这里的问题是某些操作需要作为单个事务执行(执行后可能需要flush()
),以便数据可以立即用于其他操作。请考虑以下示例:
@Transactional
public abstract class AbstractEntityDao<E> {
@PersistenceContext(unitName = "some-persistence")
protected EntityManager em;
public E create(E e) {
em.persist(e);
return e;
}
(...)
}
表示此类中的每个方法都是一个事务。现在,如果我们使用@Transactional
注释另一个扩展此类的类,则每个方法都将是另一个事务,这意味着如果我们在一个方法中删除了几个东西,它应该需要多个事务(它们都需要flush()
方法调用以执行级联)但是它们将作为一个事务运行(除非我们指定Propagation
)。让这成为每个人(尤其是我)的一课,要仔细考虑哪些操作需要单独的交易,哪些操作可以作为一个执行。