软删除多对多关联 EclipseLink

Soft delete on many-to-many association EclipseLink

当我们仅使用 java 代码时,我想在 EclipseLink 发送的多对多关联上重写调用删除操作(在关联 table 上)。 让我解释一下目标。

我有 3 个 tables,person,unit 和一个关联的 PerInUnit,所以一个人可以在多个单位中,一个单位可以包含很多人。但是我对 PeInUnit table 有一些依赖(如果这个人在特定日期是否在场,另一个 table (参与)),所以我不能(而且我不想)删除记录。为此,我进行了软删除,这样我就可以保留记录以进行一些统计。

我已经阅读了有关 Customizer 和 AdditionalCriteria 的内容,并将它们设置为 PerInUnit class。它完美地工作 => 当我进行 em.remove(myPerInUnit); 时,发送到数据库的 sql 查询是 Update PER_IN_UNIT SET STATUS='delete' WHERE id = #id; 并且指定的行为 "delete" 状态。另外,当我阅读所有记录时,我没有状态为 "delete" 的记录。但是我明确使用了 PeeInUnit class.

这是代码:

@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"中的所有人,包括他们的地位'delete'。

是否可以更改 eclipseLink 中的某些 code/instructions/Customizer/etc 以更改来自 PerInunit table 的人员的删除调用,或者我必须自己进行查询并使用它们而不是使用强大的 orm ?

感谢您的回答,请原谅我糟糕的英语!

很棒

调用 myUnit.getPeople.remove(currentPerson) 时不应删除,除非使用 PER_IN_UNIT table 将 Unit 映射到具有 ManyToMany 的 Person。由于您有 PER_IN_UNIT table 的实体,这是错误的,因为它实际上应该是 Unit-> PerInUnit OneToMany 映射,然后是 PerInUnit -> Person ManyToOne 映射。 myUnit.getPeople.remove(currentPerson) 调用将简单地获取 PerInUnit 实例并将其状态标记为已删除,或者取消引用它并让 JPA 调用删除,从而使用您的软删除 SQL 查询。

通过为 PER_IN_UNIT table 使用 ManyToMany 映射,此映射完全独立于您的 PerInUnit 实体映射,并且对可能缓存的实体或删除所需的软删除一无所知他们。如果您不想将 PER_IN_UNIT table 映射为一个实体,请参阅 http://www.eclipse.org/forums/index.php/t/243467/,其中显示了如何为软删除配置 ManyToMany 映射。