使用JoinTable和Lazy Fetch对@ManyToMany中的表进行JPA 2.0 CriteriaQuery

时间:2012-10-03 14:47:58

标签: java jpa-2.0 criteria-api

我在@ManyToMany关系中有两个实体,如下所示:

@Entity
@Table(name = "USERS") 
public class User implements EntityMetaModel, Serializable {

  @Id
  @GeneratedValue(strategy = IDENTITY)
  @Column(name = "ID", unique = true, nullable = false)
  private Integer id; 

  @Column(name = "USERNAME", unique = true, length = 20)
  private String username;

  @Column(name = "PASSWORD", nullable = false, length = 32)
  private String password;

  @Column(name = "ENABLED")
  private Boolean enabled;

  @ManyToMany(
      cascade = {CascadeType.PERSIST, CascadeType.MERGE},
      fetch = (FetchType.LAZY)
  )
  @JoinTable(         
      name = "USER_ROLES",
      joinColumns = @JoinColumn(name="USERID", referencedColumnName="ID"),
      inverseJoinColumns = @JoinColumn(name="ROLEID", referencedColumnName="ID")
  )
  @SequenceGenerator(
      name = "sgIdUserRoles",
      sequenceName = "SQ_ID_USER_ROLES"
  ) 
  @CollectionId(
      columns = {@Column(name="ID")},
      type = @Type(type="integer"), 
      generator = "sgIdUserRoles"
      )
  @Fetch(value = FetchMode.SELECT)
  private Collection<Role> roles = new HashSet<Role>();
}

@Entity
@Table(name = "ROLES")
public class Role implements EntityMetaModel, Serializable {

  @Id
  @GeneratedValue(strategy = IDENTITY)
  @Column(name = "ID", unique = true, nullable = false)
  private Integer id; 

  @Column(name = "ROLENAME", unique = true, length = 50)
  private String rolename;

  @ManyToMany(
      cascade = {CascadeType.PERSIST, CascadeType.MERGE},
      fetch = (FetchType.LAZY)
  )
  @JoinTable(         
      name = "USER_ROLES",
      joinColumns = @JoinColumn(name="ROLEID", referencedColumnName="ID"),
      inverseJoinColumns = @JoinColumn(name="USERID", referencedColumnName="ID")
  )
  @SequenceGenerator(
      name = "sgIdUserRoles",
      sequenceName = "SQ_ID_USER_ROLES"
  ) 
  @CollectionId(
      columns = {@Column(name="ID")},
      type = @Type(type="integer"), 
      generator = "sgIdUserRoles"
      )
  @Fetch(value = FetchMode.SELECT)
  private Collection<User> users = new HashSet<User>();
}

我已经创建了元模型:

@StaticMetamodel(User.class)
public class User_ {
  public static volatile SingularAttribute<User, Integer> id;
  public static volatile SingularAttribute<User, String> username;
  public static volatile SingularAttribute<User, String> password;
  public static volatile SingularAttribute<User, Boolean> enabled;        
  public static volatile CollectionAttribute<User, Role> roles;
}

@StaticMetamodel(Role.class)
public class Role_ {
  public static volatile SingularAttribute<Role, Integer> id;
  public static volatile SingularAttribute<Role, String> rolename;
  public static volatile CollectionAttribute<Role, User> users;
}

类用户拥有角色集合。我需要做的是从JPA2 CriteriaQuery中找到没有用户通过id给出的角色。 我该如何做这样的CriteriaQuery?

select r.id, r.rolename 
from roles r 
where not exists 
(select 1 
from user_roles ur 
where ur.roleid = r.id 
and ur.userid = :userid)

1 个答案:

答案 0 :(得分:0)

如果查询是:

List<Role> roles = session.createQuery("select u.roles from User u left join fetch u.roles where u.id= :idParam").
     setParameter("idParam", param).
     asList();

我记得以下标准应该有效:

List<Role> roles = session.
    createCriteria(Role.class).
    add(Restrictions.eq("users.id", param)).
    setFetchMode("users", FethchMode.EAGER).
    list();

否则,您返回具有非实体结构的查询,您可能需要ResultTransformer。