在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")
在休眠状态下,员工对教育的批量删除工作正常:
尽管教育只是反转方面,它甚至在数据库中正确删除了关联......
在 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;
}