提问者:小点点

使用HibernateSINGLE_TABLE策略从同一个Spring JPA存储库读取不同的实体


我在同一个表中有基本抽象类和2个实体,在Hibernate中使用了去罪器类型继承。

@MappedSuperclass()
@DiscriminatorColumn(name="type", discriminatorType = DiscriminatorType.INTEGER)
public abstract class Relation {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(columnDefinition = "bigint unsigned", name = "id")
    public long id;
    @Enumerated(EnumType.ORDINAL)
    RelationType type;
}

@Table(name = "relation")
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorValue("0")
public class Ban extends Relation {
    // ...
    public RelationType type = RelationType.BAN;
}

第二个实体相同,但使用@歧视值("1")。

问题是:当通过单个存储库读取这些实体时,SQL在“where”条件下不包含鉴别器值。

每个实体的单独存储库是必须的吗?

更新:即使使用分离的存储库也不起作用

@NoRepositoryBean
public interface BaseRelationRepository<T extends Relation> extends JpaRepository<T, Long> {
}


public interface BanRepository extends BaseRelationRepository<Ban> {
@Query("from Ban b where b.user = :user")
List<Ban> findAllByUser(@Param("user") User user);

此方法/查询读取所有记录,而不受@歧视值的限制。


共1个答案

匿名用户

您还没有解释为什么在Hibernate认为不必要的情况下要通过鉴别器列进行限制,因此很难明确回答您的问题。

但是Hibernate提供了一些东西:

  • 注释@歧视选项(force=true),通常用于表包含未映射到实体类的额外数据的情况。
  • HQLtype()函数,您可以在留档中找到示例。

更新

我没有立即注意到,但您在这里的错误是使用@MappdSuperclass而不是@Entity作为SINGLE_TABLE继承层次结构的超类。

如果您仔细查看日志,您会发现Hibernate记录的以下警告消息:

一个类不应该同时使用@In的继承和@MappdSuperclass进行注释。@继承将被忽略:关系。

所以:

  1. 在JPA中编写@MappdSuperclass@In的继承(SINGLE_TABLE)是没有意义的,因为映射的超类从来都不是实体层次结构的一部分。
  2. 您在这里所做的是将三个类映射到同一个表,就JPA/Hibernate而言,这三个类是不相关的实体类。

所以解决方法是:

  • 只需将@MappdSuperclass替换为@Entity,如您可以在网上找到的数千个示例所示,或者,
  • 在每个子类上使用@判别器选项(force=true)(尽管它们每个都需要显式声明判别器列),正如我上面已经提到的。