【问题标题】:Hibernate is using wrong table for join when inheritence strategy is InheritanceType.JOINED当继承策略为 InheritanceType.JOINED 时,Hibernate 使用错误的表进行连接
【发布时间】:2021-11-20 21:21:08
【问题描述】:

我有一个这样定义的基本 JPA 实体(我正在使用 Hibernate 5.4.25.final 实现):

@Entity
@Table(name = "Attributes")
@Inheritance(strategy = InheritanceType.JOINED)
public class BaseAttributeEntity {

    @Id
    private UUID id;

    @Column
    private String name;

    @ManyToOne
    @JoinColumn(name = "containerId")
    private ContainerEntity containerEntity;
}

还有2个继承实体,都类似于下面:

@Entity
@Table(name = "SpecialAttributes")
public class SpecialAttributeEntity extends BaseAttributeEntity {
   // ... some more properties
}

表结构类似于hibernate documentation 中描述的结构,在所有 3 个表上都定义了 id 列。

我还有另一个实体,其中包含 2 个实体的集合,类似于:

@Entity
@Table(name = "Container")
public class ContainerEntity {

    @Id
    private UUID id;

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "containerEntity")
    private Set<SpecialAttributeEntity> specialAttributes = new HashSet<>();

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "containerEntity")
    private Set<AnotherSpecialAttributeEntity> anotherSpecialAttributes = new HashSet<>();
}

当我尝试运行一些搜索逻辑并获取 ContainerEntitys 时,我从底层 sql 中得到以下错误:

org.postgresql.util.PSQLException: ERROR: column specialattr0_.containerId does not exist
  Hint: Perhaps you meant to reference the column "specialattr0_1_.containerId".

Hibernate 用于获取的底层 sql(我只留下了 from 语句,因为这就是问题所在):

from 
  "Service"."SpecialAttributes" specialattr0_ 
  inner join "Service"."Attributes" specialattr0_1_ on specialattr0_."id" = specialattr0_1_."id" 
  left outer join "Service"."Containers" containeren1_ on customattr0_1_."containerId" = containeren1_."id"

基本上,问题是两个“属性”实体都使用containerId 列连接,该列在基类 DB 表中定义,但 Hibernate 尝试创建 join 但使用来自子项的列类数据库表(它显然不存在......)。

我试过了,但仍然没有找到解决方案。如何指示 Hibernate 使用正确的表?最好使用标准规范?

谢谢!

【问题讨论】:

  • 你的班级ContainerEntity 有两个同名的字段customAttributes 这是不可能的。
  • @SternK,编辑了 10 倍

标签: java hibernate jpa orm


【解决方案1】:

我认为在这种特殊情况下您根本不能使用@OneToMany(mappedBy),因为旧 Hibernate 版本的限制与使用子类型相结合。你应该切换到

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "containerEntity")
private Set<BaseAttributeEntity> attributes = new HashSet<>();

private Set<SpecialAttributeEntity> specialAttributes;
private Set<AnotherSpecialAttributeEntity> anotherSpecialAttributes;

// Put respective instances into separate collections on load
@PostLoad
void postLoad() {
    this.specialAttributes = attributes.stream().filter(a instanceof SpecialAttributeEntity).collect(toSet());
    this.anotherSpecialAttributes = attributes.stream().filter(a instanceof AnotherSpecialAttributeEntity).collect(toSet());
}

// Controlled write access
public void addAttribute(BaseAttributeEntity a) {
    if (a instanceof SpecialAttributeEntity) {
        specialAttributes.add(a);
    } else {
        anotherSpecialAttributes.add(a);
    }
    attributes.add(a);
}
public void removeAttribute(BaseAttributeEntity a) {
    if (a instanceof SpecialAttributeEntity) {
        specialAttributes.remove(a);
    } else {
        anotherSpecialAttributes.remove(a);
    }
    attributes.remove(a);
}

// Provide read-only access
public Set<SpecialAttributeEntity> getSpecialAttributes() {
    return Collections.unmodifiableSet(specialAttributes);
}
public Set<AnotherSpecialAttributeEntity> getAnotherSpecialAttributes() {
    return Collections.unmodifiableSet(anotherSpecialAttributes);
}

【讨论】:

    猜你喜欢
    • 2012-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多