JPA @ManyToMany关系和Eclipse Link

时间:2015-08-31 11:25:32

标签: hibernate jpa eclipselink entitymanager

在Eclipse链接中我遇到了这样的错误:

Caused by: java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: pl.salonea.entities.Education@9a07c360

在数据库中持久保存@ManyToMany关系。

 // wire up both Employee and Education entities
            employee1.getEducations().add(santaClaraUniversity);
            employee1.getEducations().add(stanfordUniversity);
            employee2.getEducations().add(massachusettsInstituteOfTechnology);
            employee3.getEducations().add(massachusettsInstituteOfTechnology);

            santaClaraUniversity.getEducatedEmployees().add(employee1);
            stanfordUniversity.getEducatedEmployees().add(employee1);
            massachusettsInstituteOfTechnology.getEducatedEmployees().add(employee2);
            massachusettsInstituteOfTechnology.getEducatedEmployees().add(employee3);

            // persist employees and educations in database
            employeeFacade.create(employee1);
            employeeFacade.create(employee2);
            employeeFacade.create(employee3);

            educationFacade.create(stanfordUniversity);
            educationFacade.create(santaClaraUniversity);
            educationFacade.create(massachusettsInstituteOfTechnology);

employeeFacade.create(employee1);

的第一行引发错误

这段代码在Hibernate和EclipseLink中运行得非常好,存在这样的问题。我尝试添加CascadeType.PERSIST,但不知道为什么在Hibernate中它可以工作,为什么在EclipseLink中它没有。

我有点困惑如何正确地坚持@OneToMany,@ ManyToOne关系?我应该始终设置关系的双方,然后在两边坚持实体吗?我应该在单独的事务中坚持这样,还是应该将它包装在UserTransaction中? (因为这是JTA + Arquillian)

更新1 在双方上面添加后,CascadeTyp.PERSIST上面的代码抛出了这样的错误

   Caused by: javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'Bachelor of Computer Science-Stanford University' for key 'UNQ_education_0'
Error Code: 1062

On line educationFacade.create(santaClaraUniversity);

更新2 utx.begin() utx.commit()上面的facade.create()代码上面包装之后,似乎是持久化实体,但是下面的删除是另一个问题< / p>

 assertTrue(educationFacade.deleteByEmployee(employee1) == 2);

并且此方法实现为:

@Override
public Integer deleteByEmployee(Employee employee) {

    // select educations for given employee that will be deleted in the following query
    List<Education> educations = findByEmployee(employee);

    return deleteByEducations(educations);
}

@Override
public Integer deleteByEducations(List<Education> educations) {

    Query query = getEntityManager().createNamedQuery(Education.DELETE_BY_EDUCATIONS);
    query.setParameter("educations", educations);
    return query.executeUpdate();
}

我已命名查询:

@NamedQuery(name = Education.DELETE_BY_EDUCATIONS, query = "DELETE FROM Education e WHERE e IN :educations")

在休眠状态下,员工对教育的批量删除工作正常:

in hibernate it works but in eclipse link not

尽管教育只是反转方面,它甚至在数据库中正确删除了关联......

enter image description here

EclipseLink 中有0行被删除,我想有一些与约束相关的问题(即多对多关联不能被删除?)教育是关系的反面(使用mappedBy元素) )和员工是拥有方

更新3 我在deleteByEducations methdod(教育实体)中添加了这样的代码:

for(Education edu : educations) {
        for(Employee empl :edu.getEducatedEmployees()) {
            empl.getEducations().remove(edu);
            getEntityManager().merge(empl);
        }
    }

在连接表的数据库中(对于ManyToMany关系)已删除与此教育相关联的记录(我要删除)。但教育实体并未被连续删除。也许上面这个命名查询有什么东西?:

DELETE FROM Education e WHERE e IN :educations 

更新4 以这种方式实现deleteByEducations()方法是正常的,因此可能存在具有命名查询的内容,这样的构造可能与EclipseLink不兼容(但在Hibernate中有效)。 但是这个新的解决方案相当麻烦。

@Override
    public Integer deleteByEducations(List<Education> educations) {

        Integer deletedCount = 0;

        for(Education edu : educations) {
            for(Employee empl :edu.getEducatedEmployees()) {
                empl.getEducations().remove(edu);
                getEntityManager().merge(empl);
            }

            Query query = getEntityManager().createNamedQuery(Education.DELETE_BY_EDUCATION);
            query.setParameter("education", edu);
            deletedCount += query.executeUpdate();
        }

        return deletedCount;
    }

更新5 此外,此解决方案无需从连接表中删除关联记录也可正常工作。

@Override
    public Integer deleteByEducations(List<Education> educations) {

        Integer deletedCount = 0;

        for(Education edu : educations) {

            Query query = getEntityManager().createNamedQuery(Education.DELETE_BY_EDUCATION);
            query.setParameter("education", edu);
            deletedCount += query.executeUpdate();
        }

        return deletedCount;
    }

0 个答案:

没有答案
相关问题