CascadeType不适用于内存数据库

时间:2014-04-01 10:09:19

标签: java hibernate jpa

我有一个带数据库的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参数

1 个答案:

答案 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)。让这成为每个人(尤其是我)的一课,要仔细考虑哪些操作需要单独的交易,哪些操作可以作为一个执行。