JPQL ElementCollection:获取至少具有列表角色的所有用户

时间:2012-09-23 17:05:58

标签: java jpa eclipselink

用户可以扮演很多角色。我想从参数列表中获取至少有一个角色的所有用户。

数据定义如下:

@Entity
public class User implements Serializable {
    @Id
    @Column(name = "Id",
            nullable = false)
    private long id;

    @Column(name = "LoginName",
            length = 30,
            unique = true,
            nullable = false)
    private String loginName;

    @ElementCollection
    @Enumerated(EnumType.STRING)
    @CollectionTable(name = "Role",
                     joinColumns = @JoinColumn(name = "Id"),
                     uniqueConstraints = @UniqueConstraint(columnNames = {"Id", "Role"}))
    @Column(name = "Role")
    private Set<RoleType> roles = new HashSet<RoleType>();
}


public enum RoleType {
    GUEST,
    ACCOUNTING,
    ADMIN,
    OPERATOR;
}

现在我希望所有具有至少一个角色的用户都不在参数列表中。该列表可以是动态的。我尝试了以下代码:

String sql = "SELECT DISTINCT u FROM User u JOIN u.roles AS r WHERE r IN :filteredRoles";
Query query = entityManager.createQuery(sql);
List<RoleType> filteredRoles = new ArrayList<RoleType>();
filteredRoles.add(RoleType.ADMIN);
filteredRoles.add(RoleType.ACCOUNTING);
query.setParameter("filteredRoles", filteredRoles);
List<User> result = (List<User>) query.getResultList();

并收到以下异常:

Exception [EclipseLink-6078] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.QueryException
Exception Description: The class of the argument for the object comparison is incorrect. 
Expression: [null] 
Mapping: [org.eclipse.persistence.mappings.DirectCollectionMapping[roles]] 
Argument: [[ADMIN, ACCOUNTING]]
Query: ReadAllQuery(referenceClass=User sql="SELECT DISTINCT t0.Id FROM User t0, Role t1 WHERE ((t1.Role IN ?) AND (t1.Id = t0.Id))")

我尝试了几种不同的JPQL但没有成功。 我希望收到有用的提示。

2 个答案:

答案 0 :(得分:0)

你可以尝试2.4版本,这看起来像是修复过的东西。

答案 1 :(得分:-1)

我不确定,这将是最好的解决方案。我希望它会对你有所帮助;

public enum Role {
    AAA, BBB, CCC, DDD;
}

@Entity
public class Student implements Serializable {
    @Id
    private String id;
    private String name;
    @ElementCollection
    @Enumerated(EnumType.STRING)
    @CollectionTable(name = "Role", joinColumns = @JoinColumn(name = "Id"),
                     uniqueConstraints = @UniqueConstraint(columnNames = { "Id", "Role" }))
    @Column(name = "Role")
    private List<Role> roleList;

    public Student() {
    }

    //gettter and setter
}

/**
    Assume :
    ==================          ================
    Student Table               Role Table
    ==================          ================
    R001    Student 1           R001    AAA
    R002    Student 2           R002    BBB
    R003    Student 3           R002    CCC
    R004    Student 4           R004    DDD
                                R001    BBB
                                R002    CCC

*/
public class TestCase {
    public static <T> Set<T> intersection(Set<T> setA, Set<T> setB) {
        Set<T> tmp = new TreeSet<T>();
        for (T x : setA)
          if (setB.contains(x))
            tmp.add(x);
        return tmp;
      }

    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("JPA");
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        Set<Role> paramRoles = new HashSet<Role>();
        paramRoles.add(Role.BBB);
        paramRoles.add(Role.CCC);

        Query q = em.createQuery("SELECT s FROM Student s");
        List<Student> studentList = q.getResultList();
        for (Student s : studentList) {
            Set<Role> result = TestCase.intersection(paramRoles, new HashSet<Role>(s.getRoleList()));
            if (!result.isEmpty()) {
                System.out.println(s.getName());
            }
        }
        em.getTransaction().commit();
        em.close();
    }
}

/** Output :

Student 1
Student 2

*/