【问题标题】:JPA 2.0 CriteriaQuery on tables in @ManyToMany with JoinTable and Lazy Fetch使用 JoinTable 和 Lazy Fetch 对 @ManyToMany 中的表进行 JPA 2.0 CriteriaQuery
【发布时间】:2012-10-03 14:47:58
【问题描述】:

我在@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)

【问题讨论】:

  • 如果我误解了这个问题,或者您不能接受答案,请通知我。我会尽快澄清并修复它。

标签: java jpa-2.0 criteria-api


【解决方案1】:

如果查询是:

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。

【讨论】:

  • 查询应该返回用户没有的角色。我需要 JPA 2.0 模式下的代码(使用 CriteriaQuery、CriteriaBuilder、Root 等),而不是 Hibernate 代码。
  • 在问题中,您写的是“为 id 给定的用户查找角色。”,而不是“没有”。我正在研究它,但在这种情况下它可能不会更慢,我没有直接使用 JPA CriteriaBuilder API。你在尝试什么?我在criteriabuilder 中找到了一个isNotMember,它可能会起作用。
  • Azendh,很抱歉这个错误。
猜你喜欢
  • 2011-08-03
  • 2015-07-18
  • 1970-01-01
  • 1970-01-01
  • 2011-04-29
  • 2018-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多