【问题标题】:Why @OneToMany does not discriminate sub-entities in collections为什么@OneToMany 不区分集合中的子实体
【发布时间】:2017-01-28 10:34:33
【问题描述】:

我在拥有实体中有 2 个不同子实体的集合:

@Entity
@Table(name = "car")
public class Car {  
    @Id
    private Long id;

    @OneToMany(mappedBy = "owner", cascade = CascadeType.ALL, orphanRemoval = true, targetEntity = Headlight.class)
    private Collection<Headlight> headlights = new ArrayList<Headlight>();

    @OneToMany(mappedBy = "owner", cascade = CascadeType.ALL, orphanRemoval = true, targetEntity = Wheel.class)
    private Collection<Wheel> wheels = new ArrayList<Wheel>();      
}

@Entity
@Table(name = "part")
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING, length = 16)
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Part {    
    @Id
    private Long id;

    private String manufacturer;
}

@Entity
@DiscriminatorValue("HEADLIGHT")
public class Headlight extends Part {
    private Integer power;

    @ManyToOne
    @JoinColumn(name = "owner_id", referencedColumnName = "id")
    private Car owner;  
}

@Entity
@DiscriminatorValue("WHEEL")
public class Wheel extends Part {

    private Integer size;

    @ManyToOne
    @JoinColumn(name = "owner_id", referencedColumnName = "id")
    private Car owner;
}

我希望这两个集合由相应子类(2 个前灯和 4 个轮子)的实例填充:

@Test
public void testCar() {
    Car car = new Car();
    car.setId(1l);

    Headlight light1 = new Headlight();
    light1.setId(1l);
    light1.setManufacturer("Osram");
    light1.setPower(12);
    light1.setOwner(car);

    Headlight light2 = new Headlight();
    light2.setId(2l);
    light2.setManufacturer("Osram");
    light2.setPower(12);
    light2.setOwner(car);

    car.getHeadlights().add(light1);
    car.getHeadlights().add(light2);

    Wheel wheel1 = new Wheel();
    wheel1.setId(3l);
    wheel1.setManufacturer("Bridgestone");
    wheel1.setSize(16);
    wheel1.setOwner(car);

    Wheel wheel2 = new Wheel();
    wheel2.setId(4l);
    wheel2.setManufacturer("Bridgestone");
    wheel2.setSize(16);
    wheel2.setOwner(car);

    Wheel wheel3 = new Wheel();
    wheel3.setId(5l);
    wheel3.setManufacturer("Bridgestone");
    wheel3.setSize(16);
    wheel3.setOwner(car);

    Wheel wheel4 = new Wheel();
    wheel4.setId(6l);
    wheel4.setManufacturer("Bridgestone");
    wheel4.setSize(16);
    wheel4.setOwner(car);

    car.getWheels().add(wheel1);
    car.getWheels().add(wheel2);
    car.getWheels().add(wheel3);
    car.getWheels().add(wheel4);

    entityManager.persist(car);

    entityManager.flush();
    entityManager.clear();

    Car restoredCar = entityManager.find(Car.class, 1l);

    Assert.assertEquals(2, restoredCar.getHeadlights().size());
    Assert.assertEquals(4, restoredCar.getWheels().size());
}

相反,第一个集合包含 6 个车头灯(部分填充),第二个集合包含不正确的数据:

org.hibernate.WrongClassException: Object with id: 1 was not of the specified subclass: com.commerzbank.tr.nonotc.repository.Wheel (loaded object was of wrong class class com.commerzbank.tr.nonotc.repository.Headlight)

输出 SQL:

SELECT headlights0_.owner_id AS owner6_3_1_,
headlights0_.id            AS id2_7_1_,
headlights0_.id            AS id2_7_0_,
headlights0_.manufacturer  AS manufact3_7_0_,
headlights0_.owner_id      AS owner6_7_0_,
headlights0_.power         AS power4_7_0_
FROM part headlights0_
WHERE headlights0_.owner_id=?

我希望鉴别器列也包含在 WHERE 子句中:

AND headlights0_.type = 'HEADLIGHT'

,但它不存在。

我只能使用 Hibernate @Where(clause = "type = 'WHEEL') 注释来解决这个问题。

为什么在这种情况下 Hibernate 不能正常工作?我希望它拥有能够发出正确 SQL 的所有必要元数据信息。

【问题讨论】:

  • 我有一个和你一样的关系,我使用的 JPA 提供程序(DataNucleus JPA)确实将鉴别器添加到集合字段的选择中,因此一切正常(没有非 JPA 注释) .虽然 JPA 规范没有明确处理共享关系(“所有者”字段在 2 个 mappedBy 中重用),但恕我直言,这是完全合理的事情;也许会在您的 JPA 提供商上提出问题?我还认为您不需要在 @OneToMany 上指定“targetEntity”,因为泛型提供了它。

标签: java hibernate jpa inheritance orm


【解决方案1】:

你可能想试试 @DiscriminatorOptions(force = true) 在你的抽象类“Part”上。

另请参阅:About the use of @ForceDiscriminator/@DiscriminatorOptions(force=true)

【讨论】:

  • 谢谢!有用!虽然我没有摆脱代码中的 Hibernate 依赖,但这比使用 @Where 好得多。
猜你喜欢
  • 2015-05-30
  • 2012-10-02
  • 1970-01-01
  • 2011-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多