使用Spring Data JPA在SpringBoot 2.0.5.RELEASE应用程序中删除对象

时间:2018-09-22 07:51:00

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

我有一个基本的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=?

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

4 个答案:

答案 0 :(得分:1)

我可以在这里想到2个案例

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

    尝试更改删除电子钱包的方法

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

    walletRepository.delete(wallet);

    也应该删除Set<Purchase>

答案 1 :(得分:1)

在控制器中尝试:

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

问题描述

  

当您尝试通过以下方式删除每个孩子时,就会出现问题   本身(而父母(即父母))仍对其进行引用,并且   因为参考上已设置了所有的级联(包括持久性)   并合并),这会使子项(即购买项)在   撤消删除操作。

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

源: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);即可完全删除父母和子女。