【问题标题】:Deleting an object in a SpringBoot 2.0.5.RELEASE app using Spring Data JPA使用 Spring Data JPA 在 SpringBoot 2.0.5.RELEASE 应用程序中删除对象
【发布时间】:2019-02-26 12:11:17
【问题描述】:

我有一个基本的 SpringBoot 2.0.5.RELEASE 应用程序。使用 Spring Initializer、JPA、嵌入式 Tomcat、Thymeleaf 模板引擎,并打包为可执行的 JAR 文件。

我有这门课:

public class User implements Serializable {

    @OneToMany( cascade = CascadeType.ALL,orphanRemoval = true, 
                fetch = FetchType.EAGER,mappedBy = "user")
    @JsonIgnore
    private List<Wallet> wallets = new ArrayList<Wallet>();

..
}

还有这个:

public class Wallet implements Serializable {

@ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "invoice_id")
    @JsonIgnore
    @NotNull
    private Invoice invoice;



    @OneToMany(mappedBy = "wallet", 
               cascade = CascadeType.ALL, 
               orphanRemoval = true, fetch = FetchType.LAZY)
    @JsonIgnore
    private Set<Purchase> purchases = new HashSet<>();


    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "user_id" , nullable=false)
    @JsonIgnore
    private User user;

..
}

还有这个:

public class Purchase implements Serializable {

        @ManyToOne(fetch = FetchType.EAGER)
            @JoinColumn(name = "wallet_id")
            @JsonIgnore
            Wallet wallet;

        ...

    }

但是我从控制器中删除了一个具有发票和购买并且属于用户的钱包,该钱包没有从数据库中删除

walletService.delete(walletService.findById(id).get());

这是服务方法:

@Transactional
    public void delete(Wallet wallet) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("deleting Wallet [ " + wallet + " ]");
        }


        wallet
            .getPurchases()
            .parallelStream()
            .forEach(p -> purchaseService.delete(p));

        walletRepository.delete(wallet);

    }

 @Transactional
     public void delete (Purchase purchase ) {
         purchaseRepository.delete (purchase);
     }

在属性文件中:

spring.jpa.show-sql=true

我在控制台中看到的最后一个查询是这个:

select
    purchases0_.wallet_id as wallet_i8_13_0_,
    purchases0_.id as id1_13_0_,
    purchases0_.id as id1_13_1_,
    purchases0_.amount as amount2_13_1_,
    purchases0_.wallet_id as wallet_i8_13_1_ 
from
    t_purchase purchases0_ 
where
    purchases0_.wallet_id=?

没有删除也没有例外!!! !

【问题讨论】:

  • 1) 你有什么例外吗? 2)你能看到删除的SQL语句吗?
  • 尝试使用级联以及为什么要这样做 walletService.delete(walletService.findById(id).get());,只有 walletService.findById(id) 会得到你和反对,所以我不认为你需要做get(),
  • 钱包存储库从哪个 jpa 接口扩展而来?

标签: hibernate spring-mvc spring-boot spring-data-jpa spring-data


【解决方案1】:

这里我能想到2个案例

  1. 您在Wallet 类中添加了mappedBy,因此Purchase 是所有者实体,您需要从Purchases 中删除

    尝试像这样更改删除钱包方法

    @Transactional
    public void delete(Wallet wallet) {
        if (LOG.isDebugEnabled()) {
            LOG.debug("deleting Wallet [ " + wallet + " ]");
        }
    
        wallet.getPurchases().removeAll();
    walletRepository.delete(wallet);
    
    }
    
  2. 理想情况下,您已经在Wallet 中配置了CascadeType.ALL,这样做

    walletRepository.delete(钱包);

    也应该删除Set&lt;Purchase&gt;

【讨论】:

    【解决方案2】:

    这可能是解决方案吗:Hibernate 配置 -> orphanRemoval = true 将仅在删除用户实体的情况下删除钱包?

    【讨论】:

    • 我的意思是用户是所有者实体?
    【解决方案3】:

    问题描述

    当您尝试通过以下方式删除每个孩子时会出现问题 本身,而父级(即父级)仍然具有对它的引用,并且 因为引用有一个级联全部设置在它上面(包括持久化 和合并),它会导致子(即购买)在 撤消删除的上下文。

    • 请记住,引用反映了数据库中应该发生的情况,因此您应该取消对要删除的对象的引用,否则您将无法达到预期的状态

    来源:JPA / Hibernate removing "child" entities


    解决方案

    通过在父级上创建一个流并更改钱包类以在购买关系上具有级联删除类型来摆脱子级:

    @OneToMany(mappedBy = "wallet", 
               cascade = CascadeType.REMOVE,  // <--- here should be changed
               orphanRemoval = true, fetch = FetchType.LAZY)
    @JsonIgnore
    private Set<Purchase> purchases = new HashSet<>();
    

    那么你只需要调用walletRepository.delete(wallet);就可以完全删除父母和孩子。

    【讨论】:

      【解决方案4】:

      在控制器中试试这个:

          user.getWallets().remove(wallet);
          walletService.delete(wallet);       
          userService.save(user);
      

      【讨论】:

      • userService.save(user);充其量是多余的,因为 @transactional 负责对托管实体(例如用户)所做的持久更改
      猜你喜欢
      • 2019-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-07
      • 2018-09-17
      • 1970-01-01
      • 2019-07-17
      • 1970-01-01
      相关资源
      最近更新 更多