休止状態で spring-data 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 の 1 つの特定の実装にのみ関連付けることができます (逆も同様です)。これにより、次の実装が行われます。
@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 または table _per_class の場合、hibernate は一貫性がなく間違ったものを作成します!!! 外部キー、つまり test_containable から registration_compound へ (ただし、Batch から test_compound へではありません。ここでは、registration_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
が別の select ステートメントで選択されています。したがって、これらは合計 3 つのステートメントです: Get Compound、Get Containables、Get Composition です。
2 番目と 3 番目のテストでは、containables をフェッチするための SQL がコンポジションをフェッチするための SQL とマージされ、TestCompound の代わりに RegistrationCompound を選択しようとするような方法で構築されます。
registrati1_.reg_number as reg10_1_0_,
reg_number は、RegistrationCompound のみのプロパティです。どちらの場合も、実際の化合物を正しく選択する最初の select ステートメントには、where 句に次のものが含まれています。
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));
}
このテストが 2 番目または 3 番目に実行されると、間違ったクラス例外が発生します!!! ここで一体何が起こっているのか誰にも分かりませんか?解決?