Hibernate Criteria conditions or subqueries on OneToMany property values

One component of my application logs the parameters that an User send with an http URL. The mapping is as follow:

public class ActivityLog {

    @Column(name = "id")
    private Long id;

    @OneToMany(mappedBy="activityLog", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    protected List<ActivityLogParameter> activityLogParameters = new ArrayList<ActivityLogParameter>();
}

public class ActivityLogParameter {

    @Column(name = "id")
    private Long id;

    @Column(name = "key", length=10)
    protected String key;

    @Column(name = "value", length=50)
    protected String value;

    @ManyToOne(fetch = FetchType.LAZY, cascade={CascadeType.MERGE})
    @JoinColumn(name="activity_log_id")
    protected ActivityLog activityLog;
}

Let assume with every URL always 2 parameters are being passed: U and L

I need to create a query using hibernate's Criteria (mandatory from specification) so that it returns me all the ActivityLogs where both parameters matche a certain value. ie: U=aaa and L=bbb

I tried like this:

Criteria criteria = getCurrentSession().createCriteria(ActivityLog.class, "al");
// create alias
criteria = criteria.createAlias("activityLogParameters", "alp",JoinFragment.LEFT_OUTER_JOIN);

// create transformer to avoid duplicate results
criteria = criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
criteria = criteria.setFetchMode("al.activityLogParameters", FetchMode.SELECT);

//filters
criteria = criteria.add(Restrictions.or(Restrictions.eq("alp.value", UValue), Restrictions.ne("alp.key", "L")));
criteria = criteria.add(Restrictions.or(Restrictions.eq("alp.value", LValue), Restrictions.ne("alp.key", "U")));

But here I'm stuck. I tried to add projections like distinct and group by on this but it's not enough to have a correct result.

I'm trying also to use this criteria as a sub criteria, so to count the number of rows for any ActivityLog and keep only the records that have count(*) = 2 (all parameters match the condition) but I can't find how to do it with Subqueries.

Any idea on how to solve the above problem? In SQL I would do something like this:

select activity_log_id from (
    select count(*) as ct, activity_log_id 
    from activity_log_parameter alp inner join activity_log al on alp.activity_log_id=al.id 
    where (alp.value='visitor' or alp.key<>'U') 
        and (alp.value='room1' or alp.key<>'L') 
    group by activity_log_id
) as subq
where subq.ct = 2

Thanks


使用子查询解决

DetachedCriteria subquery = DetachedCriteria.forClass(ActivityLogParameter.class, "alp")
        .createAlias("activityLog", "al",JoinFragment.LEFT_OUTER_JOIN)
        .setProjection(Projections.projectionList()
                .add(Projections.count("id"), "alpId"));

subquery = subquery.add( Property.forName("al.id").eqProperty("mainAl.id") );

subquery = subquery.add(Restrictions.or(Restrictions.eq("alp.value", UValue), Restrictions.ne("alp.key", "L")));
subquery = subquery.add(Restrictions.or(Restrictions.eq("alp.value", LValue), Restrictions.ne("alp.key", "U")));

Criteria criteria = getCurrentSession().createCriteria(type, "mainAl");

criteria = criteria.add(Subqueries.eq(new Long(2), subquery));
链接地址: http://www.djcxy.com/p/37124.html

上一篇: 休眠查询没有给出预期的结果

下一篇: Hibernate Criteria条件或OneToMany属性值上的子查询