4

我正在使用 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,但问题是正在执行内部连接,并且每行只返回一个实体(用户对象)......

    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 记录?向我的用户实体添加额外的成员字段不是一个选项。

4

3 回答 3

4

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

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

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

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

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

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

解决方案 2.进行两个不同的查询:第一个获取所有用户,第二个获取相应的 CodeUser。

于 2013-09-18T09:44:34.753 回答
3

您可以执行以下操作来制作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:我在您的代码中检测到的一个问题是它需要两个根,而不是一个根。

于 2013-09-17T09:38:58.427 回答
-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()])));
于 2019-07-18T03:47:27.443 回答