From 7223a5eb53b119eab6098b92f314938c67ffc2f5 Mon Sep 17 00:00:00 2001 From: gtoison Date: Sat, 3 Jun 2023 22:48:27 +0200 Subject: [PATCH] HHH-16474 issue reproducer --- .../cache/ManyToOneTestReusedColumn.java | 268 ++++++++++++++++++ 1 file changed, 268 insertions(+) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/cache/ManyToOneTestReusedColumn.java diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/cache/ManyToOneTestReusedColumn.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/cache/ManyToOneTestReusedColumn.java new file mode 100644 index 0000000000..af2b051249 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/cache/ManyToOneTestReusedColumn.java @@ -0,0 +1,268 @@ +package org.hibernate.orm.test.bytecode.enhancement.cache; + +import java.util.HashSet; +import java.util.Set; + +import org.hibernate.annotations.BatchSize; +import org.hibernate.annotations.Cache; +import org.hibernate.annotations.CacheConcurrencyStrategy; +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.cfg.Configuration; + +import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.hibernate.testing.orm.junit.JiraKey; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import jakarta.persistence.Cacheable; +import jakarta.persistence.DiscriminatorColumn; +import jakarta.persistence.DiscriminatorType; +import jakarta.persistence.DiscriminatorValue; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.Inheritance; +import jakarta.persistence.InheritanceType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + + +@RunWith(BytecodeEnhancerRunner.class) +@JiraKey("HHH-16744") +public class ManyToOneTestReusedColumn extends BaseCoreFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] { + Fridge.class, + Container.class, + CheeseContainer.class, + FruitContainer.class, + Food.class, + Fruit.class, + Cheese.class + }; + } + + @Override + protected void configure(Configuration configuration) { + configuration.setProperty( AvailableSettings.USE_SECOND_LEVEL_CACHE, "true" ); + } + + @Before + public void setUp() { + inTransaction( + session -> { + Fridge fridge = new Fridge(); + FruitContainer fruitContainer = new FruitContainer(); + CheeseContainer cheeseContainer = new CheeseContainer(); + + Fruit fruit = new Fruit(); + Cheese cheese = new Cheese(); + + Fruit otherFruit = new Fruit(); + Cheese otherCheese = new Cheese(); + + fruit.bestPairedWith = otherFruit; + cheese.bestPairedWith = otherCheese; + + fruitContainer.fruit = fruit; + cheeseContainer.cheese = cheese; + + fridge.addToFridge( fruitContainer ); + fridge.addToFridge( cheeseContainer ); + + session.persist( fridge ); + session.persist( otherFruit ); + session.persist( otherCheese ); + session.persist( fruit ); + session.persist( cheese ); + session.persist( fruitContainer ); + session.persist( cheeseContainer ); + } + ); + } + + @Test + public void testSelect() { + inTransaction( + session -> { + Fridge fridge = session.getReference( Fridge.class, 1 ); + + for ( Container container : fridge.getContainers() ) { + if ( container instanceof FruitContainer ) { + Fruit f = ( (FruitContainer) container ).getFruit(); + assertThat( f.toString() ).isNotNull(); + assertThat( f.getBestPairedWith() ).isNotNull(); + } + else if ( container instanceof CheeseContainer ) { + Cheese c = ( (CheeseContainer) container ).getCheese(); + assertThat( c.toString() ).isNotNull(); + assertThat( c.getBestPairedWith() ).isNotNull(); + } + } + } + ); + } + + @Entity + @Cacheable + @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) + public static class Fridge { + @Id + @GeneratedValue + private Long id; + + @OneToMany(mappedBy = "fridge") + private Set containers = new HashSet<>(); + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Set getContainers() { + return containers; + } + + public void setContainers(Set containers) { + this.containers = containers; + } + + public void addToFridge(Container container) { + container.setFridge( this ); + containers.add( container ); + } + } + + @Entity + @BatchSize(size = 500) + @Inheritance(strategy = InheritanceType.SINGLE_TABLE) + @Cacheable + @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) + @DiscriminatorColumn(discriminatorType = DiscriminatorType.STRING, name = "type") + @DiscriminatorValue(value = "CONTAINER") + public static class Container { + @Id + @GeneratedValue + private Long id; + + @ManyToOne + private Fridge fridge; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Fridge getFridge() { + return fridge; + } + + public void setFridge(Fridge fridge) { + this.fridge = fridge; + } + } + + @Entity + @DiscriminatorValue(value = "FRUIT_CONTAINER") + public static class FruitContainer extends Container { + @ManyToOne + @JoinColumn(name = "food_id") + @Fetch(FetchMode.SELECT) + private Fruit fruit; + + public Fruit getFruit() { + return fruit; + } + + public void setFruit(Fruit fruit) { + this.fruit = fruit; + } + } + + @Entity + @DiscriminatorValue(value = "CHEESE_CONTAINER") + public static class CheeseContainer extends Container { + @ManyToOne + @JoinColumn(name = "food_id") + @Fetch(FetchMode.SELECT) + private Cheese cheese; + + public Cheese getCheese() { + return cheese; + } + + public void setCheese(Cheese cheese) { + this.cheese = cheese; + } + } + + @Entity + @BatchSize(size = 500) + @Inheritance(strategy = InheritanceType.SINGLE_TABLE) + @Cacheable + @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) + @DiscriminatorColumn(discriminatorType = DiscriminatorType.STRING, name = "type") + @DiscriminatorValue(value = "FOOD") + public static class Food { + @Id + @GeneratedValue + private Long id; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + } + + @Entity + @BatchSize(size = 500) + @DiscriminatorValue(value = "FRUIT") + public static class Fruit extends Food { + @ManyToOne + @Fetch(FetchMode.SELECT) + private Fruit bestPairedWith; + + public Fruit getBestPairedWith() { + return bestPairedWith; + } + + public void setBestPairedWith(Fruit bestPairedWith) { + this.bestPairedWith = bestPairedWith; + } + } + + @Entity + @BatchSize(size = 500) + @DiscriminatorValue(value = "CHEESE") + public static class Cheese extends Food { + @ManyToOne + @Fetch(FetchMode.SELECT) + private Cheese bestPairedWith; + + public Cheese getBestPairedWith() { + return bestPairedWith; + } + + public void setBestPairedWith(Cheese bestPairedWith) { + this.bestPairedWith = bestPairedWith; + } + } +}