我正在玩JPA和其他Java EE 6的东西,但现在我面临使用标准Builder的类型查询的一些问题。 我的poc的商业案例是一个推特克隆,所以我的用户有一个订阅者和订阅列表,我得到了推文。
@Entity
public class Tweet {
@Id @GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
@ManyToOne
private TwitterUser author;
@ManyToOne
private TwitterUser receiver;
@Temporal(TemporalType.TIMESTAMP)
private Date datetime;
private String message;
}
@Entity
public class TwitterUser {
@Id @GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String username;
private String displayname;
private String password;
private String email;
@Temporal(TemporalType.TIMESTAMP)
private Date since;
@ManyToMany(cascade=CascadeType.ALL)
private List<TwitterUser> subscriptions;
@ManyToMany(mappedBy = "subscriptions")
private List<TwitterUser> subscribers;
}
JPA生成的数据模型由3个表组成:Tweet,TwitterUser和TwitterUser_TwitterUser。到目前为止,一切都很好。基本查询确实有效。
现在我想为时间轴选择所有推文,这意味着所有用户推文都在当前登录用户的订阅列表中。我通过使用subselect来考虑解决方案,所以我的sql看起来像:
select * from TWEET where author_id in (
select subscriptions_ID from TWITTERUSER_TWITTERUSER where subscribers_ID = ?loggedInUserId);
此查询效果很好,但我不知道如何使用CriteriaBuilder和泛型将其写下来。我甚至没有得到一个可编译的代码,在其他一些方面可能会失败,因为我不确定子查询的类型应该是什么。 我现在正在搜索大量的例子,但它们大多只是使用原始类型或使用子查询来检索子句中左侧的元素。
也许我想念树木,但我真的很困惑。 :(
答案 0 :(得分:3)
在JPQL中,表达这种情况的一种方式类似于以下内容:
SELECT
tweet
FROM
Tweet tweet JOIN tweet.author author
WHERE
EXISTS (
SELECT
user
FROM
TwitterUser user JOIN user.subscriptions subscriber
WHERE
user = :loggedinUser AND
subscriber = author
)
作为几乎直接遵循JPQL模型的Criterias,也许这会让你开始。
答案 1 :(得分:1)
再次感谢你们帮助我们。我终于设法找到了一个输入的解决方案,它看起来如下:
public List<Tweet> findAllForSubscriber(TwitterUser user) {
// Select tweets
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Tweet> cq = cb.createQuery(Tweet.class);
Root<Tweet> tweet = cq.from(Tweet.class);
cq.select(Tweet);
// Select subscribers of user
Subquery<Long> sq = cq.subquery(Long.class);
Root<TwitterUser> twitterUser = sq.from(TwitterUser.class);
Join<TwitterUser, TwitterUser> subscriptions = twitterUser.join(TwitterUser_.subscriptions);
sq.select(subscriptions.get(TwitterUser_.id));
sq.where(cb.equal(twitterUser, user));
// Where authorId in list of subscribers
cq.where(cb.in(tweet.get(Tweet_.author).get(TwitterUser_.id)).value(sq));
//
return em.createQuery(cq).getResultList();
}
我的缺点是:
P.S。:我的解决方案完全没有选择用户自己的推文! ^^
答案 2 :(得分:0)