带有提取问题的Hibernate查询

时间:2009-11-13 15:50:16

标签: hibernate

我有一对多关系中的2个实体:

OfficeView.java:

public class OfficeView implements java.io.Serializable {

    private Integer officeId;
    private String addr1;
    private String city;
    private String state;
    private String zip;
    private List<Devices> devices;

getters and setters

    @OneToMany(mappedBy = "officeView", fetch = FetchType.EAGER)
    public List<Devices> getDevices() {
        return devices;
    }

    public void setDevices(List<Devices> devices) {
        this.devices = devices;
    }

}

Devices.java:

public class Devices implements java.io.Serializable {

    private Integer devId;
    private String devName;
    private Date lastUpdate;
    private OfficeView officeView;

getters and setters

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "office_id")
    public OfficeView getOfficeView() {
        return officeView;
    }

    public void setOfficeView(OfficeView officeView) {
        this.officeView = officeView;
    }

}

对于某些设备,除了lastUpdate之外,表中有2个几乎相同的条目。我总是想要检索表中最新的条目。只有那个条目。

例如,您有2个此设备的条目:

SSA-PITTSB-PA-NEF82 2009-10-12 23:51:07 SSA-PITTSB-PA-NEF82 2009-10-15 14:19:35

当我为包含此(和其他设备)的办公室加载OfficeView实例时,我只想获取这两个设备中最新的一个。在数据库中,我可以使用此SQL查询从devices表中获取该短列表:

select t.* from
  (select dev_id, dev_name, max(last_update) maxValue 
from devices
  group by dev_name) x
join devices t on x.dev_name=t.dev_name
and x.maxValue=t.last_update

SSA-PITTSB-PA-NEF82 2009-10-15 14:19:35

这是一个seam应用程序,调用查询的OfficeViewHome.java扩展了EntityHome。我认为正确的方法是使用自定义查询重载loadInstance。

我根本不知道如何构建查询。我该怎么做?

我知道如何在SQL中编写连接查询以加入oFfice_view和devices表并获取所有正确的数据。但我不能使用此查询来加载实例(如在createNativeQuery中),因为来自devices表的数据需要作为Devices对象列表加载。

我真的希望这是有道理的,因为我完全被难倒了。

april26

1 个答案:

答案 0 :(得分:0)

您必须override collection loader - 请注意这是JPA标准的Hibernate扩展。您可以使用SQL查询来执行此操作而不是编写HQL - 实际上,在这种情况下编写HQL可能有点麻烦。

@Loader(namedQuery = "latestDevices")
@NamedNativeQuery(name="latestDevices", query="...", resultClass = Devices.class)
@OneToMany(mappedBy = "officeView", fetch = FetchType.EAGER)
public List<Devices> getDevices() {
  return devices;
}

实际查询是您在上面写的office_id附加条件,其参数值将由Hibernate提供:

select t.* from
 (select dev_id, dev_name, max(last_update) maxValue 
    from devices
   group by dev_name) x
  join devices t on x.dev_name=t.dev_name
   and x.maxValue=t.last_update
   and t.office_id = ?

如果名称在整个过程中不是唯一的,则必须重写上述内容以明确加入office内部选择的ID,因为您无法重复?占位符。

通过Devices上的集合更新/删除Office时要非常小心,Hibernate会尝试优化某些操作,最终可能会删除上面未检索到的给定Office的设备选择。