我正在使用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记录?这不是向我的用户实体添加额外成员字段的选项。
答案 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()])));