IN clause with a composite primary key in JPA criteria

Tiny picture Tiny · Jun 8, 2014 · Viewed 7.3k times · Source

I have a table named group_table in MySQL with only two columns user_group_id and group_id (both of them are of type VARCHAR). Both of these columns together form a composite primary key.

I need to execute a statement using a sub-select IN() to select rows based on a list of values passed to the query.

@Override
@SuppressWarnings("unchecked")
public List<GroupTable> getList(List<GroupTable> list)
{
    CriteriaBuilder criteriaBuilder=entityManager.getCriteriaBuilder();
    CriteriaQuery<GroupTable> criteriaQuery=criteriaBuilder.createQuery(GroupTable.class);
    Root<GroupTable> root = criteriaQuery.from(entityManager.getMetamodel().entity(GroupTable.class));
    criteriaQuery.where(root.in(list));
    return entityManager.createQuery(criteriaQuery).getResultList();
}

The implementation produces the following query.

SELECT group_id, 
       user_group_id 
FROM   projectdb.group_table 
WHERE  ((?, ?) IN ((?, ?), (?, ?))) 

/*Binding parameters.*/
bind => [null, null, ROLE_AAA, aaa, ROLE_BBB, aaa]

Please notice that the first two parameters which are about the composite key itself are null. They should be user_group_id and group_id respectively.

Why are they not substituted in the parameter list?


While I'm not interested in forming a composite primary key in a table, this is (likely) mandatory for JAAS I'm using for authentication.

In this scenario, the query returns the same list as it is supplied from the database which is needless in reality. I actually need this query for deletion of multiple rows.

Answer

Shailendra picture Shailendra · Jun 17, 2014

Try this

        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        CriteriaQuery<GroupTable> cq = cb.createQuery(GroupTable.class);
        Root<GroupTable> r = cq.from(GroupTable.class);
        Expression<EntityPK> exp = r.get("id"); //EntityPK is your primary composite key class and id is the property name of primary key in GroupTable entity
        Predicate predicate = exp.in(list);
        cq.select(r).where(predicate);

        entityManager.createQuery(cq).getResultList();

I have a following table with below structure

create table EntityA (
        col1 integer not null,
        col2 integer not null,
        description varchar(255),
        primary key (col1, col2)
    )

Following are the entity and composite key classes

@Entity
public class EntityA implements Serializable {

    @EmbeddedId
    private EntityPK id;
    private String description;

// getters, setteres    
    ...........................
    ............................


    }


@Embeddable
public class EntityPK implements Serializable {

    private int col1;
    private int col2;

// getters, setters, hashcode, equals etc

My test code is

 CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<EntityA> cq = cb.createQuery(EntityA.class);
        Root<EntityA> r = cq.from(EntityA.class);
        Expression<EntityPK> exp = r.get("id");
        Predicate predicate = exp.in(list);
        cq.select(r).where(predicate);
        em.createQuery(cq).getResultList();

The resulting SQL is

select
        entitya0_.col1 as col1_0_,
        entitya0_.col2 as col2_0_,
        entitya0_.description as descript3_0_ 
    from
        EntityA entitya0_ 
    where
        entitya0_.col1=? 
        and entitya0_.col2=? 
        or entitya0_.col1=? 
        and entitya0_.col2=? 
        or entitya0_.col1=? 
        and entitya0_.col2=?