我是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)
什么都不做?我认为,它们在逻辑上是等价的。或者我错了?
请告知。
提前致谢!
答案 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;