Spring Data JPA奇怪的行为

时间:2018-01-26 12:43:27

标签: java spring hibernate spring-data-jpa

我是JPA和Hibernate的新手,遇到了奇怪的行为。请考虑以下代码。

License实体:

@Entity
@Data
public class License {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    @Enumerated(EnumType.STRING)
    private LicenseType type;
    @Column(unique = true)
    private String activationKey;
    @OneToMany(mappedBy = "id", cascade = CascadeType.REMOVE)
    private List<Payment> payments = new ArrayList<>();
    private long productId;
    private String productName;
    private long term;
    private long creationTimestamp;
    private boolean active;
}

LicenceType枚举:

public enum LicenseType {
    NAMED
}

Payment实体:

@Entity
@Data
public class Payment {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.REFRESH})
    private License license;
    private BigDecimal sum;
}

LicenceRepository

@Repository
public interface LicenseRepository extends CrudRepository<License, Long> {

}

PaymentRepository

@Repository
public interface PaymentRepository extends CrudRepository<Payment, Long> {

}

Bootstrap类:

@SpringBootApplication
public class LsPocApplication {

    public static void main(String[] args) {
        SpringApplication.run(LsPocApplication.class, args);
    }

    @Bean
    public CommandLineRunner demo(LicenseRepository licenseRepository, PaymentRepository paymentRepository) {
        return (args) -> {

            License license = new License();
            license.setActivationKey(UUID.randomUUID().toString());

            Payment payment = new Payment();
            payment.setSum(BigDecimal.valueOf(new Random().nextDouble()));
            payment.setLicense(license);

            paymentRepository.save(payment);

            // licenseRepository.delete(license); // This does nothing
            // licenseRepository.delete(license.getId()); // This deletes both licence and associated payment(s)
        };
    }
}

所以问题是为什么licenseRepository.delete(license.getId())按预期工作,但licenseRepository.delete(license)什么都不做?我认为,它们在逻辑上是等价的。或者我错了?

请告知。

提前致谢!

2 个答案:

答案 0 :(得分:1)

您的许可证是否实现Serializable?如果是这样,我认为两个调用都将调用相同的方法,即用于id参数的方法。但由于没有许可证有另一个许可证,因为ID不会被删除。

原因是在类型擦除之后,所有优秀的泛型的所有内容都是Serializable用于id,Object用于实体类型。如果实体类型也恰好实现Serializable,则使用该方法,因为它更具体。 (我不得不承认我的脑子里有一些手淫,但这个想法应该是正确的。)

这就是为什么从Spring Data 2.0(又名Kay)改变方法名称的原因,所以这种混乱不再发生。

答案 1 :(得分:0)

使用合并将 Payment 实体保存到数据库。因此,许可证未添加到会话中,因此 licenseRepository.delete(许可证)无法正常工作。

尝试在付款类中更改此行:

@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.REFRESH})
private License license;

@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
private License license;