This issue might be a linked to [https://hibernate.atlassian.net/browse/HHH-16810|https://hibernate.atlassian.net/browse/HHH-16810|smart-link] as since this issue has been resolved, I have another problem.
h2. Entities
{code:java}@Getter @Entity @ToString(onlyExplicitlyIncluded = true) @EqualsAndHashCode(onlyExplicitlyIncluded = true) @IdClass(SpecialOperator.SpecialOperatorPK.class) @Table(name = "SPECIAL_OPERATORS") @Cacheable @Cache(usage = READ_WRITE) @NoArgsConstructor(access = PROTECTED) public class SpecialOperator {
@EqualsAndHashCode.Include @ToString.Include @Id private Provider provider;
@EqualsAndHashCode.Include @ToString.Include @Id private String operatorId;
@OneToMany(mappedBy = "operator", cascade = { PERSIST, MERGE, REMOVE }, orphanRemoval = true) private final Set<SpecialPricePoint> pricePoints = new HashSet<>();
@CreationTimestamp @Column(name = "CREATION_DATE", nullable = false, updatable = false) private Instant creationDate;
@UpdateTimestamp @Column(name = "MODIFICATION_DATE", nullable = false) private Instant modificationDate;
public void addPricePoint(SpecialPricePoint pricePoint) { pricePoint.setOperator(this); pricePoints.add(pricePoint); }
public SpecialOperator(Provider provider, String operatorId) { this.provider = provider; this.operatorId = operatorId; }
@EqualsAndHashCode @ToString @Getter @NoArgsConstructor(access = PROTECTED) @AllArgsConstructor @Embeddable public static class SpecialOperatorPK implements Serializable { @Enumerated(EnumType.STRING) @Column(name = "PROVIDER_ID", nullable = false) Provider provider;
@Column(name = "OPERATOR_ID", nullable = false) String operatorId; } }{code}
{code:java}@Getter @Entity @EqualsAndHashCode(onlyExplicitlyIncluded = true) @ToString(onlyExplicitlyIncluded = true) @Table(name = "SPECIAL_OPERATOR_PRICES_POINTS") @IdClass(SpecialPricePoint.SpecialPricePointPK.class) @NoArgsConstructor(access = PROTECTED) public class SpecialPricePoint {
public SpecialPricePoint(SpecialOperator operator, String wholesalePrice) { this.operator = operator; this.wholesalePrice = wholesalePrice; }
@ManyToOne @ToString.Include @Setter(PACKAGE) @EqualsAndHashCode.Include @JoinColumn(name = "PROVIDER_ID", referencedColumnName = "PROVIDER_ID") @JoinColumn(name = "OPERATOR_ID", referencedColumnName = "OPERATOR_ID") @MapsId private SpecialOperator operator;
@Id @Column(name = "PRICE_POINT", nullable = false) @ToString.Include @EqualsAndHashCode.Include String wholesalePrice;
@OneToOne(mappedBy = "wholesalePrice", cascade = { PERSIST, MERGE, REMOVE }, orphanRemoval = true) @Cache(usage = READ_WRITE) private SpecialProduct product;
public void setProduct(SpecialProduct product) { product.setWholesalePrice(this); this.product = product;
}
@Value @Embeddable @NoArgsConstructor(access = PROTECTED) @AllArgsConstructor public static class SpecialPricePointPK implements Serializable { @Embedded @NonFinal @AttributeOverride(name = "provider", column = @Column(name = "PROVIDER_ID", nullable = false)) @AttributeOverride(name = "operatorId", column = @Column(name = "OPERATOR_ID", nullable = false)) SpecialOperatorPK operator;
@NonFinal String wholesalePrice; } }{code}
{code:java} @Getter @EqualsAndHashCode(onlyExplicitlyIncluded = true) @ToString(onlyExplicitlyIncluded = true) @NoArgsConstructor(access = PROTECTED) @Table(name = "SPECIAL_PRODUCTS") @Entity @IdClass(SpecialProduct.SpecialProductPK.class) @Cacheable @Cache(usage = READ_WRITE) @OptimisticLocking(type = OptimisticLockType.DIRTY) @DynamicUpdate public class SpecialProduct { public SpecialProduct(String productId, SpecialPricePoint wholesalePrice) { this.productId = productId; this.wholesalePrice = wholesalePrice; }
@Id @EqualsAndHashCode.Include
@ToString.Include @Column(name = "PRODUCT_ID", nullable = false) private String productId;
@Setter @ToString.Include @EqualsAndHashCode.Include @OneToOne(optional = false, cascade = { PERSIST, MERGE }) @JoinColumn(name = "WHOLESALE_PRICE_AMOUNT", referencedColumnName = "PRICE_POINT", updatable = false, insertable = false) @JoinColumn(name = "OPERATOR_ID", referencedColumnName = "OPERATOR_ID", updatable = false, insertable = false) @JoinColumn(name = "PROVIDER_ID", referencedColumnName = "PROVIDER_ID", updatable = false, insertable = false) @MapsId private SpecialPricePoint wholesalePrice;
@CreationTimestamp @Column(name = "CREATION_DATE", nullable = false, updatable = false) private Instant creationDate;
@OptimisticLock(excluded = true) @UpdateTimestamp @Column(name = "MODIFICATION_DATE", nullable = false) private Instant modificationDate;
@Value @Embeddable @NoArgsConstructor(access = PROTECTED) @AllArgsConstructor public static class SpecialProductPK implements Serializable { @Embedded @NonFinal @AttributeOverride(name = "operator.provider", column = @Column(name = "PROVIDER_ID", nullable = false)) @AttributeOverride(name = "operator.operatorId", column = @Column(name = "OPERATOR_ID", nullable = false)) @AttributeOverride(name = "wholesalePrice", column = @Column(name = "WHOLESALE_PRICE_AMOUNT", nullable = false)) SpecialPricePointPK wholesalePrice;
@NonFinal String productId; } }{code}
h2. Tests
h3. Delete by Id
I run the following test :
{noformat} @Test void shouldDeleteProduct() { // given String operatorId = "OPERATOR_1"; Provider provider = A; SpecialOperator specialOperator = new SpecialOperator(provider, operatorId); specialOperatorService.addOperator(specialOperator); String wholesalePrice = "1 EUR"; SpecialPricePoint specialPricePoint = new SpecialPricePoint(specialOperator, wholesalePrice); specialPricePointService.addPricePoint(specialPricePoint); String productId = "PRODUCT_1"; SpecialProduct specialProduct = new SpecialProduct(productId, specialPricePoint);
Optional<SpecialPricePoint> pricePoint = specialPricePointService.getPricePoint(provider, operatorId, wholesalePrice); assertThat(pricePoint).isNotEmpty(); specialProductService.addProduct(specialProduct); SpecialProduct product = specialProductService.getProduct(provider, operatorId, wholesalePrice, productId); assertThat(product).isNotNull();
// when specialProductService.deleteProduct(provider, operatorId, wholesalePrice, productId);
// then SpecialProduct product1 = specialProductService.getProduct(provider, operatorId, wholesalePrice, productId); assertThat(product1).isNull(); }{noformat}
When I run it with L2 cache enabled ( see {{SpecialProductServiceTest}} in the sources) the product is deleted but when I run this test without cache (see {{SpecialProductServiceWithoutCacheTest}} in the sources) the product is not being deleted.
h3. Delete All
{noformat} @Test void shouldDeleteAllProducts() { // given String operatorId = "OPERATOR_1"; Provider provider = A; SpecialOperator specialOperator = new SpecialOperator(provider, operatorId); specialOperatorService.addOperator(specialOperator); String wholesalePrice = "1 EUR"; SpecialPricePoint specialPricePoint = new SpecialPricePoint(specialOperator, wholesalePrice); specialPricePointService.addPricePoint(specialPricePoint); String productId = "PRODUCT_1"; SpecialProduct specialProduct = new SpecialProduct(productId, specialPricePoint);
Optional<SpecialPricePoint> pricePoint = specialPricePointService.getPricePoint(provider, operatorId, wholesalePrice); assertThat(pricePoint).isNotEmpty(); specialProductService.addProduct(specialProduct); SpecialProduct product = specialProductService.getProduct(provider, operatorId, wholesalePrice, productId); assertThat(product).isNotNull();
// when specialProductService.deleteAllProducts();
// then SpecialProduct product1 = specialProductService.getProduct(provider, operatorId, wholesalePrice, productId); assertThat(product1).isNull(); }{noformat}
This time whether cache is enabled or not (test is present in {{SpecialProductServiceTest}} and {{SpecialProductServiceWithoutCacheTest}}) , the product is not deleted.
h2. Sources
Sources can be found in branch {{reversdOneToOne}} on [https://github.com/emouty/hibernate-issues/tree/reversedOneToOne|https://github.com/emouty/hibernate-issues/tree/reversedOneToOne|smart-link] |
|