如何使用JPA CriteriaBuilder查询执行外连接?

时间:2013-09-13 20:49:46

标签: hibernate jpa join jpa-2.0 outer-join

我正在使用JPA 2.0,Hibernate 4.1.0.Final和MySQL 5.5.27。我想构建一个JPA查询,每行返回两个实体,我想执行一个右外连接。这两个实体是:

@Entity
@Table(name = "user",
    uniqueConstraints = { @UniqueConstraint(columnNames = { "USER_NAME" }) }
)
public class User implements Comparable<User>, Serializable
{
    ...
    @Column(name = "first_name")
    @NotNull
    /* the first name of the User */
    private String firstName;

@Entity
@Table(name="code_user",
    uniqueConstraints = { 
        @UniqueConstraint(columnNames = { "CODE_ID", "USER_ID" }) }
)
public class CodeUser 
{

    @Id
    @NotNull
    @GeneratedValue(generator = "uuid-strategy")
    @Column(name = "ID")
    private String id;

    @ManyToOne
    @JoinColumn(name = "CODE_ID", nullable = false, updatable = true)
    private Code code;

    @ManyToOne
    @JoinColumn(name = "USER_ID", nullable = false, updatable = true)
    private User user;

到目前为止,这是我的JPA,但问题是正在执行内连接,并且每行只返回一个实体(User对象)......

    final CriteriaBuilder builder = m_entityManager.getCriteriaBuilder();
    final CriteriaQuery<User> criteria = builder.createQuery(User.class);
    final Root<User> user = criteria.from(User.class);

    final Root<CodeUser> codeUser = criteria.from(CodeUser.class);
    final Join<CodeUser, User> joinUser = codeUser.join(CodeUser_.user);
    criteria.select(joinUser);
    …
    return criteria.where(builder.and(preds.toArray(new Predicate[preds.size()])));

如何执行外部联接以便返回所有用户并返回任何匹配的CodeUser记录?这不是向我的用户实体添加额外成员字段的选项。

3 个答案:

答案 0 :(得分:2)

您可以执行以下操作以制作RIGHT JOIN

Join<CodeUser, User> joinUser = rootCodeUser.join(CodeUser_.user, JoinType.RIGHT);
//now you can add your conditions on the CodeUser

另外,为了选择更多实体,请尝试这样做:

CriteriaQuery<Object[]> criteria = builder.createQuery( Object[].class );
Root<CodeUser> codeUserRoot = criteria.from( CodeUser.class );
Join<CodeUser, User> joinUser = rootUser.join(CodeUser_.user, JoinType.RIGHT);

criteria.select( builder.array( joinUser, codeUserRoot ) );
//now you can add you conditions

PS:我在你的代码中检测到的一个问题是它需要两个根,而不是一个。

答案 1 :(得分:2)

您必须检查Hibernate是否支持Right Join,因为JPA提供程序不需要根据documentation支持RIGHT JOIN:

  

不需要右外连接和右外连接   Java Persistence 2.0支持。使用RIGHT join的应用程序   类型不可移植。

所以,那么,如果你发现没有hibernate版本,那么我看到的唯一解决方案就是:

解决方案1。将LAZY字段添加到User实体

@OneToMany(mappedBy="TODO", fetch=FetchType.LAZY)
private Collection<CodeUser> codeUsers;

然后使用LEFT JOIN从User导航到CodeUsers。

解决方案2. 制作两个不同的查询:在第一次获取所有用户时,在第二次获取相应的CodeUsers。

答案 2 :(得分:-1)

使用交叉联接

    final CriteriaBuilder builder = m_entityManager.getCriteriaBuilder();
    final CriteriaQuery<User> criteria = builder.createQuery(User.class);
    final Root<User> user = criteria.from(User.class);

    final Root<CodeUser> codeUser = criteria.from(CodeUser.class);
    criteria.select(codeUser);
    preds.add(builder.equal(codeUser.get("USER_ID"), user.get("ID")))

    …
    return criteria.where(builder.and(preds.toArray(new Predicate[preds.size()])));