在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)
UPDATE 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
在线教育.Facade.create(santaClaraUniversity);
UPDATE 2 在 utx.begin() 和 utx.commit() 中的facade.create()代码上面包装之后,似乎是持久化实体,但是删除的另一个问题如下所示
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")
在休眠中,员工对Educations的批量删除工作正常:
尽管教育只是反转方面,它甚至在数据库中正确删除了关联......
并且在 EclipseLink 中有0行被删除,我想有一些与约束相关的问题(即多对多关联不能被删除?)教育是关系的反面(使用mappedBy元素)而Employee是拥有方
UPDATE 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
UPDATE 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;
}
UPDATE 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;
}