我有一个实体层次结构:
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
class A {
@Id
private Long id;
}
@Entity
@PrimaryKeyJoinColumn(name = "id", referencedColumnName = "id")
class B extends A {
}
当表B中的记录不存在时检索A实体的查询和其他情况下的B实体。我创建了JPQL查询,它工作得很好,但查询在数据库端的成本太高。所以我决定创建本机查询并将其映射到实体。我想知道如何让Hibernate知道应该返回哪个实体,我找到了一些解决方案:
JPA Native Query for Entity with Inheritance
entityManager.createNativeQuery("select a.*, b*, 1 as clazz_, from A a LEFT OUTER JOIN B b on id = a.id where procedure(f)",A.class).getResultList()
看起来有一个特殊的人工柱来区分类型。转换为SQL时,我的JPQL查询也有此列。在上面的示例中,此列的值始终为1
。在我的JPQL查询中,它看起来像:
case when cim.id is not null then 1 when ci.id is not null then 0 end as clazz_
我可以将其重写为我的原生查询,但是如何确保将值0
和1
映射到给定类型下次不会更改?如果我添加另一个扩展A的类
答案 0 :(得分:0)
JoinedSubclassEntityPersister定义IMPLICIT_DISCRIMINATOR_ALIAS
属性:
private static final String IMPLICIT_DISCRIMINATOR_ALIAS = "clazz_";
当您未指定显式鉴别器值时使用:
explicitDiscriminatorColumnName = null;
discriminatorAlias = IMPLICIT_DISCRIMINATOR_ALIAS;
discriminatorType = StandardBasicTypes.INTEGER;
try {
discriminatorValue = persistentClass.getSubclassId();
discriminatorSQLString = discriminatorValue.toString();
}
catch ( Exception e ) {
throw new MappingException( "Could not format discriminator value to SQL string", e );
}
0
和1
值来自persistentClass.getSubclassId();
,它是由Hibernate在运行时分配的:
public Subclass(PersistentClass superclass) {
this.superclass = superclass;
this.subclassId = superclass.nextSubclassId();
}
RootClass默认ID为0
:
@Override
public int getSubclassId() {
return 0;
}
因为标识符是在运行时分配的,所以不清楚如果添加一个新的子类并且在某些已经存在的子类之前加载它会发生什么,所以你最好明确设置这个值并绕过隐式子类id:< / p>
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "discriminator", discriminatorType = DiscriminatorType.INTEGER)
class A {
@Id
private Long id;
}
@Entity
@PrimaryKeyJoinColumn(name = "id", referencedColumnName = "id")
@DiscriminatorValue(value = 1)
class B extends A {
}
甚至更好,指定一个STRING
鉴别器:
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "discriminator", discriminatorType = DiscriminatorType.STRING)
@DiscriminatorValue(value = "A")
class A {
@Id
private Long id;
}
@Entity
@PrimaryKeyJoinColumn(name = "id", referencedColumnName = "id")
@DiscriminatorValue(value = "B")
class B extends A {
}