有一个实体Truck。它与实体Dirty和OneToOne 关系有关Gravel。Sand此外,这三个实体中的两个始终为空(好像一辆卡车一次只能装载一个负载,其余的将是空的)。
卡车:
@Entity
public class Truck {
@Id
Integer id;
@Column(name = "owner")
String owner;
@OneToOne(mappedBy = "truck")
Dirty dirty;
@OneToOne(mappedBy = "truck")
Gravel gravel;
@OneToOne(mappedBy = "truck")
Sand sand;
}
货物类(继承自 AbstractCargo):
@MappedSuperClass
public abstract class AbstractCargo {
@OneToOne
@JoinColumn(name = "truck_id")
Truck truck;
@Column(name = "weight")
int weight;
}
@Entity
public class Dirty {
}
@Entity
public class Gravel {
}
@Entity
public class Sand {
}
现在我需要获取一个实体列表,Truck其属性owner等于某个字符串并与实体关联Dirty,Gravel或者Sand,其中属性weight等于某个数字(我提醒您,一个实体Truck一次只能有一个负载,其余的将为空)。顺便说一句,我正在使用EntityGraph,所以使用是JOIN不可取的(Hibernate 开始发誓)。
用人类语言来说,然后我需要获取属于某个所有者的所有卡车,这些卡车的负载等于某个数量。
我尝试了很长时间进行正确的 JPQL 查询,但这就是发生的事情:
SELECT t FROM Truck t, Dirty d, Gravel g, Sand s
WHERE t.owner=:owner
AND ((d.truck.id=t.id AND d.weight=:weight) OR
(g.truck.id=t.id AND g.weight=:weight) OR
(s.truck.id=t.id AND s.weight=:weight))
但结果是疯狂的(行重复)。
我如何在这里提出请求?
JPQL支持关联过滤,所以这个查询应该可以工作:
在这里
left join,使用了多种outer join。考虑它是如何工作的(使用一个例子dirty,其他人也一样)。对于主条目(在我们的例子中,来自 table
Truck),在 中搜索匹配的条目Dirty。如果找到了,那很好,Truck.dirty关于它的信息会写在字段中(在这种情况下,以代理的形式,因为没有fetch),如果没有找到,那么字段dirty将被设置为null,但是truck它仍将作为请求的结果返回。在我们的例子中,我们使用的事实是,如果我们的连接没有找到表中的记录,那么
dirty == null我们过滤掉那些Truck通过权重条件找不到关联的字段。如果您希望关联不懒惰,请替换
left join为left join fetch.如果您将我的原始查询与 一起使用,您可以获得正确的输出
DISTINCT,尽管我不确定此解决方案的性能。