当我们只使用java代码时,我想重写EclipseLink发送的多对多关联上的调用删除操作(在关联表上)。 让我解释一下目标。
我有3个表,人,单位和一个关联的表:PerInUnit,所以一个人可以在多个单位,一个单位可以包含很多人。但是我对PeInUnit表有一些依赖(如果这个人在特定日期存在或不存在,另一个表(参与)),所以我不能(我不想)删除记录。为此,我将软件删除,因此我可以保留记录以进行一些统计。
我已经阅读了Customizer和AdditionalCriteria,并将它们设置为PerInUnit类。它完美地工作=>当我发出em.remove(myPerInUnit);
时,发送到数据库的sql查询是Update PER_IN_UNIT SET STATUS='delete' WHERE id = #id;
而指定的行是“删除”状态。此外,当我读取所有记录时,我没有状态为“删除”。但是我明确地使用了PeeInUnit类。
以下是代码:
@Entity
@Table(name = "PER_IN_UNIT")
@AdditionalCriteria("this.status is null")
@Customizer(PIUCustomizer.class)
public class PerInUnit implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "GEN_SEQ_PIU")
@SequenceGenerator(name = "GEN_SEQ_PIU", sequenceName = "SEQ_PIU", initialValue = 1, allocationSize = 1)
@Column(name = "ID")
private Long id;
@ManyToOne(cascade=javax.persistence.CascadeType.PERSIST)
@JoinColumn(name = "PER_ID")
private Person person;
@ManyToOne(cascade=javax.persistence.CascadeType.PERSIST)
@JoinColumn(name = "UNI_ID")
private Unit unit;
@Column(name = "STATUS")
private String status;
//Constructor, getters, setters
}
PIUCustomizer的代码:
public class PIUCustomizer implements DescriptorCustomizer {
@Override
public void customize(ClassDescriptor descriptor) {
descriptor.getQueryManager().setDeleteSQLString("UPDATE PER_IN_UNIT SET STATUS = 'delete' WHERE ID = #ID");
}
}
问题出现了:当我使用带有双向关系的EclipseLink时,我想做一些像myUnit.getPeople.remove(currentPerson);
这样的指令(从单元“myUnit”中删除当前人员)。但EclipseLink发送了以下指令(在提交期间!):
DELETE FROM PER_IN_UNIT WHERE ((UNI_ID = ?) AND (PER_ID = ?))
而不是
Update PER_IN_UNIT SET STATUS='delete' WHERE ((UNI_ID = ?) AND (PER_ID = ?))
我期望并提高(显然,因为依赖性(FKs))以下异常:
Query: DataModifyQuery(sql="DELETE FROM PER_IN_UNIT WHERE ((UNI_ID = ?) AND (PER_ID = ?))")
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:157)
at test.Crud.update(Crud.java:116)
at test.Test.runTest(Test.java:96)
at test.Test.main(Test.java:106)
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: ORA-02292: integrity constraint (PEOPLE.FK_PAR_PIU) violated - child record found
其他问题(同一类型),当我制作类似System.out.prinln(myUnit.getPeople())
的内容时,我会让单位中的所有人“myUnit”,包括他们的状态为“删除”。
是否可以在eclipseLink中更改一些代码/指令/定制器/等来更改PerInunit表的人员删除调用,或者我必须自己创建查询并使用它们而不是使用强大的orm?
感谢您的回答,请原谅我的英语不好!
的Fab
答案 0 :(得分:0)
调用myUnit.getPeople.remove(currentPerson)时不应该删除,除非使用PER_IN_UNIT表将Unit设置为具有ManyToMany的Person。由于你有一个PER_IN_UNIT表的实体,这是错误的,因为它确实应该是一个单元 - > PerInUnit OneToMany映射,然后是PerInUnit - > Person ManyToOne映射。然后myUnit.getPeople.remove(currentPerson)调用只是获取PerInUnit实例并将其状态标记为已删除,或者取消引用它并让JPA调用remove,从而使用您的软删除SQL查询。
通过对PER_IN_UNIT表使用ManyToMany映射,此映射完全独立于PerInUnit实体映射,并且不知道可能缓存的实体或删除它们所需的软删除。如果您不想将PER_IN_UNIT表映射为实体,请参阅http://www.eclipse.org/forums/index.php/t/243467/,其中显示了如何为软删除配置ManyToMany映射。