简体   繁体   English

如何防止带有条​​件的左联接条件之后的Hibernate加载一对一字段?

[英]How can I prevent Hibernate loading one-to-one field after left-join criteria with condition?

I have the following database tables: 我有以下数据库表:

Cats
ParentID | Name
-----------------
1        | Mittins
2        | Cuddles
3        | Spot

Kittens
ID | ParentID | Color
---------------------
1  | 1        | Red
2  | 1        | Yellow
3  | 1        | Blue
4  | 2        | Red
5  | 2        | Blue
6  | 3        | Red
7  | 3        | Yellow
8  | 3        | Blue

And the following Mapping classes: 以及以下Mapping类:

class Cat
{
   @Id
   @Column(name="ParentID", nullable = false)
   public Integer parentID;

   @Column(name="Name", nullable = false)
   public String name;

   @OneToOne
   @JoinColumn(name="parentID")
   @NotFound(action=NotFoundAction.IGNORE)
   public Kitten kitten;
}

class Kitten
{
   @Id
   @Column(name="ID", nullable = false)
   public Integer id;

   @Column(name="ParentID", nullable = false)
   public Integer parentID;

   @Column(name="Color", nullable = false)
   public String color;
}

I want to join the cat with its kitten of a specified color. 我想将cat与指定颜色的kitten一起加入。 It is guaranteed that each cat has one-and-only-one kitten of the specified color. 保证每只猫都有一只指定颜色的小猫。 The mapping then will be one-to-one for this instance. 这样,该实例的映射将是一对一的。

Criteria crit = sessionFactory.getCurrentSession().createCriteria(Cat.class, "cat");
crit.createCriteria("cat.kitten", "kitten", Criteria.LEFT_JOIN, Restrictions.eq("kitten.color", "Red"));

crit.list();

This will return 3 Cat objects each populated with their "Red" kitten objects. 这将返回3个Cat对象,每个对象均填充有“ Red”小猫对象。 Hibernate gets this in one shot. Hibernate一枪解决。 The Kitten data is populated during this fetch and no subquery is performed to get the kitten data. 在此提取期间填充小猫数据,并且不执行任何子查询来获取小猫数据。

However, if for instance I search for "Yellow" kittens, I still want the 3 Cat objects which I do get. 但是,例如,如果我搜索“黄色”小猫,我仍然希望得到3个Cat对象。 But I want null for the kitten field for the Cat that does not have a yellow kitten (cat #2). 但是我想为没有黄色小猫的猫(小猫#2)的小猫字段设置null

Instead, what hibernate does is try to load all the kittens for cat 2 via another subquery on the parentID . 相反,休眠方式是尝试通过parentID上的另一个子查询为cat 2加载所有小猫。

I do not want it to do this because the mapping does not know that my original left-join criteria was limited to "yellow" kittens. 我不希望这样做,因为映射不知道我原来的左联接条件仅限于“黄色”小猫。 This of course results in the "More than one row with the given identifier was found" error. 当然,这会导致“找到具有给定标识符的多个行”错误。

When the original criteria is executed, hibernate should know that the "kitten" part of the query returned NULL. 当执行原始条件时,休眠应该知道查询的“小猫”部分返回了NULL。 Is it possible to have Hibernate set that field null rather than a proxy that will later try a second incorrect query to load the kitten objects? 是否有可能让Hibernate将该字段设置为null而不是一个代理,该代理稍后会尝试第二次不正确的查询来加载小猫对象?

to start with, it is not oneToOne but OneToMany, as Cat can have many kittens. 首先,它不是oneToOne而是OneToMany,因为Cat可以养很多只小猫。 So you should map to OneToMany using Map in which the color is the key and the value is the correct kitten. 因此,您应该使用Map映射到OneToMany,其中颜色是键,值是正确的小猫。

@OneToMany
@MapKey(name="color") 
@JoinColumn(name="parentID")
Map<String,Kitten> kittens;

Your java objects should represent the db model, not the possible query results. 您的Java对象应该代表db模型,而不是可能的查询结果。 You can still query for cats having particual kittens. 您仍然可以查询有特定小猫的猫。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM