user620339
user620339

Reputation: 901

Hibernate Criteria with multiple joins and left join

I have a following query:

SELECT users.user_id as user_id , users.USERNAME, users.FIRSTNAME, users.LASTNAME, roles.name AS role_name
    FROM user_role userrole
    JOIN user users ON userrole.user_id = users.user_id
    JOIN role roles ON userrole.role_id  = roles.role_id
    WHERE userrole.role_id IN (
        SELECT  distinct(role.role_id) FROM perm p
            JOIN function_code fc ON p.function_code_id = fc.function_code_id
            JOIN role role ON p.role_id  = role.role_id
            JOIN service service ON service.service_id = fc.service_id AND service.name = '<myservice>'
            LEFT JOIN datapolicy dp ON p.datapolicy_id = dp.datapolicy_id AND p.role_id = dp.role_id
    )

I am trying to convert this to Hibernate Criteria Query. I am really a rookie when it comes to HCQ. Any help would be very much appreciated.

Here is the ER mappings:

user --> role (one to many)
role --> perm (one to many)
perm --> function_code  (one to one) 
perm --> datapolicy  (one to one)
service --> function_code (one to many)
role  --> datapolicy (one to many)


@Firo
I made my query based on your answer,

sessionFactory.getCurrentSession().createCriteria(User.class, "user")
    .createAlias("roles", "role").add(
        Subqueries.in("role.id", DetachedCriteria.forClass(Role.class).
        createCriteria("securityPermissions").createCriteria("functionCode")
        .createCriteria("serviceName").add(Restrictions.eq("name", serviceName))
        .setProjection(Projections.distinct(Projections.id())))
    ).setProjection(Projections.projectionList().add(Projections.property("id"))
    .add(Projections.property("user.username")).add(Projections.property("user.firstname"))
    .add(Projections.property("user.lastname")).add(Projections.property("role.name")));

Now I am getting this exception:

java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
    org.hibernate.type.IntegerType.set(IntegerType.java:64)
    org.hibernate.type.NullableType.nullSafeSet(NullableType.java:154)
    org.hibernate.type.NullableType.nullSafeSet(NullableType.java:136)
    org.hibernate.loader.Loader.bindPositionalParameters(Loader.java:1728)
    org.hibernate.loader.Loader.bindParameterValues(Loader.java:1699)
    org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1589)
    org.hibernate.loader.Loader.doQuery(Loader.java:696)
    org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
    org.hibernate.loader.Loader.doList(Loader.java:2228)
    org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2125)
    org.hibernate.loader.Loader.list(Loader.java:2120)
    org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:118)
    org.hibernate.impl.SessionImpl.list(SessionImpl.java:1596)
    org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:306)

Though it clearly states java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer, but I am not sure do I have explicitly mention dataType wherever I am dealing with the ID's in my query (shouldn't Hibernate be able to figure it out itself?).

Where am I going wrong ?

Upvotes: 2

Views: 6992

Answers (1)

Firo
Firo

Reputation: 30803

untested

session.createCriteria(User.class, "user")
    .createAlias("Roles", "role");
    .add(Subqueries.In("role.id", DetachedCriteria.for(Role.class)
        .createCriteria("functions")
            .createCriteria("services")
                .add(Restrictions.eq("name", "<myservice>")
        .setProjection(Projections.distinct(Projections.id()))
    )
    .setProjection(Projections.list()
        .add(Projections.property("id"))
        .add(Projections.property("Name"))
        ...
        .add(Projections.property("role.id"))
        .add(Projections.property("role.name"))
    )
    .list();

Upvotes: 2

Related Questions