如何做一个Hibernate嵌套选择?

时间:2014-01-13 18:42:15

标签: java hibernate

不确定我是否正确地提出了问题,但我正在使用postgres数据库

我正在寻找以下sql语句的等价物。

从轨道中选择*,其中id为(从track_item中选择track_id,其中x和y之间的item_time)。

我是hibernate的新手,我尝试使用Hibernate Query并使用Criteria并且两种方式都失败了。

如果有一个使用这两种方法的芒果,那么看到这两个例子会很好,因为我正在努力学习如何使用这两种方法。

这是两个表的创建表信息

CREATE TABLE track (
id bigint NOT NULL,
track_uuid text,
track_number text,
track_exercise_indicator_id bigint NOT NULL,
track_simulation_indicator_id bigint NOT NULL,
track_status_id bigint,
last_modified timestamp with time zone DEFAULT timezone('utc'::text, now())
);

CREATE TABLE track_item (
id bigint NOT NULL,
track_item_type_id bigint NOT NULL,
item_time bigint NOT NULL,
frame_number bigint,
image_source text,
last_modified timestamp with time zone DEFAULT timezone('utc'::text, now()),
track_item_uuid character varying(200) NOT NULL,
track_id bigint NOT NULL
);

ALTER TABLE ONLY track_item
ADD CONSTRAINT track_item_track_id_fkey FOREIGN KEY (track_id) REFERENCES track(id);

ALTER TABLE ONLY track_item
ADD CONSTRAINT track_item_track_item_type_id_fkey FOREIGN KEY (track_item_type_id) REFERENCES track_item_type(id);

从上表生成的java类是。

@Entity
@Table(name = "track", schema = "d2d")
public class Track implements java.io.Serializable {

/**
 * ID.
 */
private static final long serialVersionUID = 2313376497269789747L;
private long id;
private TrackSimulationIndicator trackSimulationIndicator;
private TrackStatus trackStatus;
private TrackExerciseIndicator trackExerciseIndicator;
private String trackUuid;
private String trackNumber;
private Date lastModified;
private Set<TrackMessageToTrackMapping> trackMessageToTrackMappings = new HashSet<TrackMessageToTrackMapping>(
        0);
private Set<TrackInterval> trackIntervals = new HashSet<TrackInterval>(0);
private Set<AnomalyToTrackMapping> anomalyToTrackMappings = new HashSet<AnomalyToTrackMapping>(
        0);
}




 @Entity
 @Table(name = "track_item", schema = "d2d")
 public class TrackItem implements java.io.Serializable {

/**
 * ID.
 */
private static final long serialVersionUID = 8469898950069782997L;
private long id;
private TrackItemType trackItemType;
private long itemTime;
private Long frameNumber;
private String imageSource;
private String trackItemUUID;
private Track track;
private Date lastModified;
private Set<TrackPoint> trackPoints = new HashSet<TrackPoint>(0);
private Set<TrackInformation> trackInformations = new HashSet<TrackInformation>(
        0);
}

3 个答案:

答案 0 :(得分:2)

您的查询应该使用连接更高效,并且在HQL中更容易翻译:

select distinct t.* from track t
inner join track_item item on t.id = item.track_id
where item.item_time between 100 and 200

此SQL查询将转换为HQL:

select distinct t from Track t 
inner join t.items item
where item.time between 100 and 200

在标准中:

Criteria c = session.createCriteria(Track.class, "t");
c.setResultTransformer(criteria.DISTINCT_ROOT_ENTITY);
c.createAlias("t.items", "item");
c.add(Restrictions.between("item.time", 100L, 200L);

编辑:

您已将关联映射为从TrackItem到Track的ManyToOne关联。从Track到TrackItem的反向OneToMany关联不存在,因此上述查询将不起作用。以下HQL可以工作:

select distinct t from Item item 
inner join item.track t
where item.time between 100 and 200

您无法将此类查询转换为Criteria,因此您最好将关联设为双向:跟踪没有理由不知道其项目。

答案 1 :(得分:0)

我的一位同事在下面提出了这个标准解决方案。一旦他更新了表名和对itemTime的引用,JB Nizet为HQL语句发布的解决方案就可以了。 HQL查询也发布在此底部。

 /**
 * @param p_startTime The date and time in ms
 * @param p_endTime The date and time in ms
 * @param p_session the session
 * @return Returns the latest valid rule for the specified date time
 * @throws IOException
 */
@SuppressWarnings("unchecked")
public static List<Track> loadAllTracksByDateRange(final long p_startTime,
        final long p_endTime, final Session p_session) throws IOException {


    // create the criteria
    final Criteria criteria = p_session.createCriteria(TrackItem.class);


    // set projection
    criteria.setProjection(Projections.distinct(Projections
            .property("track")));


    // add the restriction
    criteria.add(Restrictions.ge("itemTime", p_startTime));
    criteria.add(Restrictions.le("itemTime", p_endTime));


    return criteria.list();
}

HQL解决方案:

Select distinct t 
from TrackItem item inner join item.track t 
where item.itemTime between 100L and 200L;

答案 2 :(得分:0)

您可以使用DetachedCriteria类进行嵌套选择:

Session s = obtainSession();
Criteria c = s.createCriteria(Track.class);
DetachedCriteria dc = DetachedCriteria.forClass(TrackItem.class);

dc.setProjection(Property.forName("track"));
dc.add(Restrictions.between("itemTime", x, y));

c.add(Subqueries.propertyIn("id", dc))

看问题 diff between criteria and detached criteria in hibernate?when to use detached criteria in hibernate?
和hibernate文档Chapter 15.8 详情