Я использую JPA с пружиной данных с спящим режимом. У меня очень сложная задача, чтобы мои сопоставления наследования и отношения работали правильно.Спящий режим: наследование и сопоставление отношений + обобщения
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Table(name="compound")
@DiscriminatorColumn(name="compound_type")
@DiscriminatorOptions(force=true)
public abstract class Compound<T extends Containable> {
@OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.compound",
cascade = CascadeType.ALL, orphanRemoval = true)
@LazyCollection(LazyCollectionOption.FALSE)
private List<CompoundComposition> compositions = new ArrayList<>();
@OneToMany(fetch = FetchType.EAGER, mappedBy="compound",
targetEntity=Containable.class, cascade = CascadeType.ALL)
@LazyCollection(LazyCollectionOption.FALSE)
private Set<T> containables = new HashSet<T>();
}
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Table(name="containable")
@DiscriminatorColumn(name="containable_type")
@DiscriminatorOptions(force=true)
public abstract class Containable<T extends Compound> {
@ManyToOne(optional=true, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private T compound;
}
Идея заключается в том, что определенная реализация AbstractCompound может быть связана только с одной конкретной реализацией Containable (и наоборот). Это приводит к следующему implementaions:
@Entity
@DiscriminatorValue("TestCompound")
public class TestCompound extends AbstractCompound<TestContainable> {
}
@Entity
@DiscriminatorValue("RegistrationCompound")
public class RegistrationCompound extends AbstractCompound<Batch> {
@Column(name = "reg_number", unique = true)
private String regNumber;
}
@Entity
@DiscriminatorValue("TestContainable")
public class TestContainable extends Containable<TestCompound> {
}
@Entity
@DiscriminatorValue("Batch")
public class Batch extends Containable<RegistrationCompound>{
@Column(name = "batch_number")
private Integer batchNumber;
}
Я играл со всеми стратегиями наследования и для соединения-иерархии одна таблицы является только один, что, по крайней мере, частично работает. В случае JOINED или таблицы _per_class hibernate создает непоследовательную и неправильную !!! внешние ключи, а именно от test_contable to registration_compound (но не от Batch to test_compound, здесь он корректно отображает только регистрационное_соединение).
Находящаяся сторона, похоже, не имеет значения, какую стратегию я использую.
Теперь актуальная проблема в моих тестах. Конкретный тестовый класс. имеет 3 теста. Все, что делает конкретный поиск экземпляра «TestCompound». Дело в том, что первый выполненный из этих 3 тестовых случаев всегда прошел, остальные 2 всегда терпят неудачу. Порядок, в котором они выполняются, кажется случайным (JUnit + @RunWith (SpringJUnit4ClassRunner.class)). Это означает, что любой из тестов проходит, если он запускается первым.
Испытания, которые не бросить следующие исключения:
org.hibernate.WrongClassException: Object with id: 1000 was not of the specified
subclass: RegistrationCompound (loaded object was of wrong class class TestCompound)
В случае первого теста, зимуют вопросы следующие правильно выбрать для выборки в Containables
Hibernate: select containabl0_.compound_id as compound8_1_1_, containabl0_.id as id0_1_,
containabl0_.id as id0_0_, containabl0_.created as created0_0_,
containabl0_.created_by as created4_0_0_, containabl0_.last_modified as last5_0_0_,
containabl0_.last_modified_by as last6_0_0_, containabl0_.compound_id as compound8_0_0_,
containabl0_.batch_number as batch7_0_0_, containabl0_.containable_type as containa1_0_0_
from containable containabl0_ where containabl0_.containable_type in ('Batch', 'TestContainable')
and containabl0_.compound_id=?
и List<CompoundComposition> compositions
выбирается другой выбор заявление. Таким образом, у них есть в общей сложности 3 заявления: Получите состав, получите сдерживающие способности, получите композиции.
Для второго и третьего теста SQL для извлечения сдерживаемых объектов объединен с включенным для извлечения композиций, и он построен таким образом, что он пытается выбрать RegistrationCompound вместо TestCompound, в качестве примера он содержит
registrati1_.reg_number as reg10_1_0_,
и reg_number является собственностью RegistrationCompound. В обоих случаях первый оператор выбора, который выбирает фактическое соединение правильно содержит следующее где положение:
testcompou0_.compound_type='TestCompound'
Так что это очень сбивает с толку. Почему это зависит от порядка выполнения теста? Почему, черт возьми, он пытается выбрать RegistrationCompound?
Вот самый простой тест из 3 тестов:
@Test
@Transactional
public void testFindByCompositionPkStructureId() {
System.out.println("findByCompositionPkStructureId");
Long structureId = 1000L;
TestCompound compound = new TestCompound();
compound.setId(1000L);
compound.setCas("9999-99-9");
compound.setCompoundName("Test Compound");
List<TestCompound> result =
testCompoundRepository.findByCompositionsPkStructureId(structureId);
assertEquals(compound, result.get(0));
}
Если этот тест запускается как второй или третий я получаю исключение неправильный класс !!! Кто-нибудь знает, что здесь происходит? Решение?
Ваши тесты Откат? – willome
Не те, которые ничего не меняют. однако оказывается, что удаление @Cache Annotation от всех entites решило эту проблему. Однако теперь я сталкиваюсь с новым, но очень похожим. –