0

我的领域模型:支付和账户之间的单向多对一映射。

@Inheritance(strategy = InheritanceType.JOINED) 
@DiscriminatorColumn(name = "ACCOUNT_TYPE")
public abstract class Account { … }

@Entity
@DiscriminatorValue(Account.Constants.BANK_ACCOUNT)
public class BankAccount extends Account { … }

@Entity
public class Payment {
  @ManyToOne
  private Account receiver;
  ...
}

我的测试用例(扩展 AbstractJUnit4SpringContextTests):

@Test(expected=DataIntegrityViolationException.class)
public void deleteAccountReferencedByPayment() {
  createPayment();
  getTransactionTemplate().execute(new TransactionCallback<Object>() {
    @Override
    public Object doInTransaction(TransactionStatus status) {
      Account receiver = accountRepository.findAllByEmail(email1).get(0);
      accountRepository.remove(receiver);
      return null;
    }
  });
}

这会导致 DataIntegrityViolationException,因为在启动事务提交后执行的 SQL 是:

  • 从 ID=? 的 BankAccount 中删除
  • 从 ID=? 的帐户中删除 和版本=?

现在我有一个奇怪的“特征”,当我

  • 更改域以在 ManyToOne 映射上添加级联(尤其是 ALL 或 PERSIST)
  • 并更改测试以在删除帐户时读取同一交易中创建的付款

进一步来说:

@Entity
public class Payment  {
  @ManyToOne(cascade = {CascadeType.PERSIST})
  private Account receiver;
  ...
}

@Test(expected=DataIntegrityViolationException.class)
public void deleteAccountReferencedByPaymentStrangeBehaviour() {
  final Long paymentId = createPayment();
  getTransactionTemplate().execute(new TransactionCallback<Object>() {
    @Override
    public Object doInTransaction(TransactionStatus status) {
      paymentRepository.find(paymentId);
      Account receiver = accountRepository.findAllByEmail(email1).get(0);
      accountRepository.remove(receiver);
      return null;
    }
  });
}

这不会导致 DataIntegrityViolationException,因为在启动事务提交后没有执行任何 SQL。

任何想法是什么导致了这种行为?PERSIST 与查找付款或删除帐户有什么关系?这可能是 JPA 标准实施中的错误吗?顺便说一句,我将 JPA2 与 Hibernate 4.1.3.Final 一起使用。

4

1 回答 1

0

通过读入 Payment 对象,它成为托管对象。当您删除 Account 并调用 commit 时,JPA 提供程序会找到从托管 Payment 引用的完全相同的 Account 对象,并且由于关系标记为 cascade persist,因此必须保留 Account。因此,最终效果是它取消了您的删除尝试。

JPA 需要维护关系,以便您的对象模型反映您希望数据库的外观。在这种情况下,您必须先从付款中删除帐户参考,然后才能将其删除,或者在同一交易中删除付款。

于 2012-06-11T17:51:12.330 回答