【问题标题】:@OneToMany prevent deletion if is part of set@OneToMany 如果是集合的一部分,则阻止删除
【发布时间】:2017-11-07 15:23:00
【问题描述】:

我正在使用带有 Java JPQL 的古巴框架

我有以下关系:

  1. Transaction_Sets
  2. 交易

在哪里

Transaction Entity
      @ManyToOne
        @JoinColumn(name = "TRANSACTION_SET_ID")
        @OnDelete(DeletePolicy.DENY)
        protected Transaction_Set transaction_Set;
Transaction_Set entity  
        @OneToMany(mappedBy = "transaction_Set", cascade = CascadeType.REMOVE)
        @OnDeleteInverse(DeletePolicy.DENY)
        protected List<Transaction> transactions;

我尝试了很多 @ 的组合,但由于某种原因它不起作用。我想做的就是:

  1. 如果事务属于 Transaction_Set,则停止删除该事务。
    每当我尝试删除交易时 将其删除并从 transaction_set 中移除。
  2. 删除事务集时删除事务集的所有事务。

数字 (2) 有效。数(1)我解决不了……

过去一天我一直在为此烦恼。

我这样做对吗?我认为这可能与古巴框架的设置方式有关。

【问题讨论】:

    标签: java hibernate jpql cuba-platform


    【解决方案1】:

    一个明显的设置如下:

    // Transaction
    @OnDelete(DeletePolicy.DENY)
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "TRANSACTION_SET_ID")
    protected TransactionSet transactionSet;
    
    // TransactionSet
    @OnDelete(DeletePolicy.CASCADE) // won't work
    @OneToMany(mappedBy = "transactionSet")
    protected List<Transaction> transactions;
    

    但它不会起作用,因为您的要求是矛盾的:关于 Transaction 的 DENY 策略将防止从 TransactionSet 端删除 CASCADE。使用 @OnDelete@OnDeleteInverse 注释可能无法在 ORM 级别上解决问题,但您可以在 ORM 已经完成所有工作时运行的 AfterDeleteEntityListener 中实现其中一个限制。

    所以映射应该如下(只保留第一个限制):

    // Transaction
    @OnDelete(DeletePolicy.DENY)
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "TRANSACTION_SET_ID")
    protected TransactionSet transactionSet;
    
    // TransactionSet
    @OneToMany(mappedBy = "transactionSet")
    protected List<Transaction> transactions;
    

    还有实体监听器(不幸的是你必须在这里使用纯 SQL):

    package com.company.sample.listener;
    
    import com.haulmont.bali.db.QueryRunner;
    import com.haulmont.cuba.core.Persistence;
    import com.haulmont.cuba.core.global.TimeSource;
    import com.haulmont.cuba.core.global.UserSessionSource;
    import com.haulmont.cuba.core.sys.persistence.DbTypeConverter;
    import org.springframework.stereotype.Component;
    import com.haulmont.cuba.core.listener.AfterDeleteEntityListener;
    import java.sql.Connection;
    import java.sql.SQLException;
    
    import com.company.sample.entity.TransactionSet;
    
    import javax.inject.Inject;
    
    @Component("sample_TransactionSetEntityListener")
    public class TransactionSetEntityListener implements AfterDeleteEntityListener<TransactionSet> {
    
        @Inject
        private TimeSource timeSource;
    
        @Inject
        private UserSessionSource userSessionSource;
    
        @Inject
        private Persistence persistence;
    
        @Override
        public void onAfterDelete(TransactionSet entity, Connection connection) {
            QueryRunner queryRunner = new QueryRunner();
            DbTypeConverter dbTypeConverter = persistence.getDbTypeConverter();
            try {
                queryRunner.update(connection,
                        "update SAMPLE_TRANSACTION set DELETE_TS = ?, DELETED_BY = ? where TRANSACTION_SET_ID = ?",
                        new Object[]{
                                dbTypeConverter.getSqlObject(timeSource.currentTimestamp()),
                                userSessionSource.getUserSession().getCurrentOrSubstitutedUser().getLoginLowerCase(),
                                dbTypeConverter.getSqlObject(entity.getId())
                        });
            } catch (SQLException e) {
                throw new RuntimeException("Error deleting related transactions ", e);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-07-29
      • 2021-09-23
      • 2016-08-17
      • 1970-01-01
      • 2019-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多