开发者

hibernate @DiscriminatorValue does not apply to associations

I have the following inheritance hierarchy.

@Entity
@Table(FRUIT)
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColum(name="FRUIT_TYPE",discriminatorType=STRING)
public class Fruit {
..
@Id
private FruitId id;
...
}

@DiscriminatorValue("APPLE")
public class Apple extends Fruit {
...
@ManyToOne
private FruitBowl bowl; //this association is only present in the subclass

...
}

class FruitBowl .. {
...
        @OneToMany(fetch = FetchType.LAZY, mappedBy = "bowl")
    @IndexColumn(name="POSITION",base = 1) 
        List<Apple> apples;
...

When I do a session.load(Apple.class,...), it adds FRUIT_TYPE = 'APPLE' to the select query. But if I do a select on FruitBowl(which has a 1:m relationship with Apple), the select query on the Apple does not contain FRUIT_TYPE = 'APPLE'. Why does this happen? How do I rectify the problem?

Query --Query for FruitBowl

select fruitbowl0_开发者_如何转开发.BOWL_ID as BOWL1_1_0_ from FRUITBOWL fruitbowl0_ where fruitbowl0_.BOWL_ID=? 

--Query for Fruit to retrieve Apples (records with fruit_type ='A') --but it does not include that condition

select apples0_.ENTITY_ID as ENTITY3_1_, apples0_.POS as POS1_, apples0_.POS as POS0_0_, apples0_.ENTITY_ID as ENTITY3_0_0_, apples0_.COLOR as COLOR0_0_ from FRUIT apples0_ where apples0_.ENTITY_ID=?


You can add @DiscriminatorOptions(force=true) to your "Fruit" class which will force hibernate to use the descriminator when querying this relationship.

This seems like something you would expect by default, but maybe there is some performance reason why it is not so.


(Edited based on mappings / SQL queries / sample data posted in question / comments).

Your mapping specifies that FruitBowl contains a collection of Apples. Hibernate will therefore not add discriminator value condition to loader query for that collection because it knows in advance that only Apple instances can be returned.

SQL queries you've posted do exactly that - load FruitBowl by id and subsequently load apples collection for that FruitBowl instance. The problem lies with the data you've posted:

 fruit_type entity_id  pos  color
     A         1        1   white
     B         1        2   blue

There's another instance of Fruit with discriminator value B - Banana? :-) - that has the same entity_id and thus is retrieved as part of collection loading query. The question here is - how was it inserted in the first place? There are two possible scenarios:

  1. Banana is a subclass of Apple. In that case everything is correct, it should be returned as part of apples collection.
  2. You've inserted the above data manually for testing purposes. This data is illegal from the Hibernate's standpoint - it would have NEVER be inserted by the Hibernate itself; this in turn leads to the behavior you're seeing. You need to either get rid of Banana row or remove its entity_id (thus removing it from apples collection).

Generally speaking, mixing object hierarchy and collection elements in the same table is not a good idea. Consider either re-mapping the hierarchy as "table-per-subclass" or mapping apples collection using @JoinTable - note that it will become uni-directional in the latter case.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜