Hibernate自我加入

时间:2009-09-21 17:53:37

标签: hibernate join self-join

背景

我有一个包含列 id,imageId,propertyId 的表。

可能有许多图像与单个属性相关联,并且可能有许多属性与单个图像相关联。

imageId - many-to-many - propertyId

我有一个propertyIds列表,我想找出所有与使用Hibernate 的所有propertyIds 相关联的图像。

问题。

刚才我一次选择一个属性并使用Criteria API查找与此propertyId关联的所有imageId,我获取了一个imageIds列表。我在下一个查询中使用此imageIds列表并说出

select imageIds where imageId in (imageIds obtained in previous step) where propertyId = x

如此有效,击中数据库的查询数量将等于propertyIds的数量。我不认为这是一个很好的解决方案,不得不点击数据库n次,我尝试使用Detached Query但没有成功。有更好的解决方案吗?

另外,当我最终获得imageIds列表时,将它存储在用户会话和分页中是不是一个好主意(让我们不考虑结果的数量)或重写整个它是一个好主意过程或我是否应考虑将其存储在DB中以用于分页?

2 个答案:

答案 0 :(得分:2)

这是您的数据库架构的问题:

您正尝试将3个单独的关联(图像集合,图像 - 属性,集合 - 属性)填充到单个 ImageCollection 表中。这不是一件好事。虽然你可以使用普通的SQL(以该表中包含空列的大量行为代价)来避免这种情况,但是你将无法在Hibernate中正确映射它。顺便说一句,这个表不需要代理主键。

您需要做的是将其拆分为3个单独的表,并在Hibernate中将模型映射为正确的多对多。例如:

@Entity
public class Image {
  @ManyToMany
  @JoinTable(
    name="IMAGE_PROPERTIES",
    joinColumns=@JoinColumn(name="IMAGE_ID"),
    inverseJoinColumns=@JoinColumn(name="PROPERTY_ID")
  )
  private Collection<Property> properties;

  ...
}

IMAGE_PROPERTIES表格只有IMAGE_IDPROPERTY_ID列;你也可以拥有COLLECTION_IMAGESCOLLECTION_PROPERTIES表格。

然后,您将能够按以下属性名称查询图像:

from Image img
  left join img.properties as prop
  with prop.name in ('Tag1', 'Tag2', 'Tag3')

如果您的属性非常像标记,请查看this article以获取AND / OR / UNION查询示例。

如果属性确实是属性(即,它们具有所有者实体的生命周期并且不能同时属于多个实体),请考虑将它们分成两个表(一个用于Images,一个用于集合)和使用一对多关联。这样您就不需要上面的IMAGE_PROPERTIESCOLLECTION_PROPERTIES表了。

答案 1 :(得分:0)

所以你有一个这样的类(注意:我没有用ide写这个,所以代码可能在语法上不正确):

public class Property {
@ManyToMany
private List<Image> images;
}

public class Image {
@ManyToMany
private List<Property> properties;
}

因此像select property from Property property这样的查询应该会为您提供属性列表,您可以通过普通的Java属性获取这些属性。

这是你在找什么,还是我误解了这个问题?