【问题标题】:JPA: fetch field from child class in JOINED inheritanceJPA:从 JOINED 继承中的子类中获取字段
【发布时间】:2016-04-09 12:00:13
【问题描述】:

我的超类是:

@Entity
@Table(name = "TEST_VEHICLE")
@ChangesListener
@AttributeOverride(name = "id", column = @Column(name = "VEHICLE_ID"))
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "VEHICLE_TYPE_ID", discriminatorType = DiscriminatorType.INTEGER)
public abstract class Vehicle extends ParentEntity {
    @Column(name = "MAX_SPEED", nullable = false)
    private Integer maxSpeed;

    public Integer getMaxSpeed() {
        return maxSpeed;
    }

    public void setMaxSpeed(Integer maxSpeed) {
        this.maxSpeed = maxSpeed;
    }
}

子类是:

@Entity
@Table(name = "TEST_BUS")
@DiscriminatorValue("2")
public class Bus extends Vehicle {
    @Column(name = "PASSENGER_NUMBER", nullable = false)
    private Short passengerNumber;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "FOO_OF_VEHICLE")
    private Foo foo;

    public Short getPassengerNumber() {
        return passengerNumber;
    }

    public void setPassengerNumber(Short passengerNumber) {
        this.passengerNumber = passengerNumber;
    }

    public Foo getFoo() {
        return foo;
    }

    public void setFoo(Foo foo) {
        this.foo = foo;
    }
}

在标准中对Root<Vehicle> 使用foo 提取:

root.fetch("foo", JoinType.LEFT);

导致此错误:

java.lang.IllegalArgumentException: Unable to locate Attribute  with the the given name [foo] on this ManagedType ...

如何从子类中获取字段?

更新:

使用treat并不能解决我的问题:

Root<Bus> busRoot = builder.treat(root, Bus.class);
busRoot.fetch("foo", JoinType.INNER);

我没有收到任何错误,但 foo 尚未获取。 生成的 SQL 是:

SELECT vehicle0_.VEHICLE_ID    AS VEHICLE_2_72_,
  vehicle0_.ATTACHMENT_COUNT   AS ATTACHME3_72_,
  vehicle0_.COMMENTS           AS COMMENTS4_72_,
  vehicle0_.CREATE_TIMESTAMP   AS CREATE_T5_72_,
  vehicle0_.CREATOR_USER_ID    AS CREATOR_8_72_,
  vehicle0_.MODIFIER_USER_ID   AS MODIFIER9_72_,
  vehicle0_.UPDATE_TIMESTAMP   AS UPDATE_T6_72_,
  vehicle0_.MAX_SPEED          AS MAX_SPEE7_72_,
  vehicle0_1_.FOO_OF_VEHICLE   AS FOO_OF_V3_70_,
  vehicle0_1_.PASSENGER_NUMBER AS PASSENGE1_70_,
  vehicle0_2_.ENGINE_TYPE      AS ENGINE_T1_71_,
  vehicle0_.VEHICLE_TYPE_ID    AS VEHICLE_1_72_
FROM TEST_VEHICLE vehicle0_
LEFT OUTER JOIN TEST_BUS vehicle0_1_
ON vehicle0_.VEHICLE_ID=vehicle0_1_.VEHICLE_ID
LEFT OUTER JOIN TEST_CAR vehicle0_2_
ON vehicle0_.VEHICLE_ID   =vehicle0_2_.VEHICLE_ID
WHERE vehicle0_.VEHICLE_ID=105

【问题讨论】:

  • 车辆不一定是公共汽车;基本多态性。如果想要子类字段访问,则进行转换(处理),就像使用基本 java 一样
  • 这里是 JPA 规范的摘录:` 查询的根对象是实体,其他类型可以通过导航到达。` 这意味着要么将 foo 移动到Vehicle 类,或者您将 Bus 类作为查询的根。
  • @NeilStockton 是的。绝对地。但如果是 Bus,我想获取 foo 字段。喜欢:root.fetch("bus",JoinType.LEFT).fetch("foo", JoinType.LEFT);,但这个解决方案也不起作用。
  • 作为一个基本问题,您必须使用Discriminator 列吗?如果有一个抽象基类,我会期待一个@MappedSupersclass
  • @Nicholas 是的,在某些情况下我需要为 SuperClass 创建外键

标签: java hibernate jpa criteria


【解决方案1】:

这个问题可以使用元模型来解决。

public abstract class Bus_ extends com.rh.cores.architecture.tests.models.Vehicle_ {

    public static volatile SingularAttribute<Bus, Foo> foo;
    public static volatile SingularAttribute<Bus, Short> passengerNumber;
}

意思是:

root.fetch(Bus_.foo, JoinType.LEFT);

但是由于 JPA 中的 fetch 签名是这样的:

<Y> Fetch<X, Y> fetch(SingularAttribute<? super X, Y> attribute, JoinType jt);

以上代码导致编译错误! 像这样更改代码:

SingularAttribute attribute = Bus_.foo;
root.fetch(attribute, JoinType.LEFT);

我们可以绕过 JPA 标准中的泛型检查 SingularAttribute&lt;? super X, Y&gt; 而 Hibernate 处理它!

【讨论】:

    猜你喜欢
    • 2018-03-01
    • 2017-11-25
    • 1970-01-01
    • 2010-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多