有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Subselect使用CriteriaBuilder(JPA)检索Installement的右侧

我正在玩JPA和其他JavaEE6的东西,但是现在我在使用CriteriaBuilder进行类型查询时遇到了一些问题。 我的poc的商业案例是一个twitter克隆,因此我有一个用户列表,其中有订阅者和订阅,我得到了推特

@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\u TwitterUser。到目前为止一切都很好。基本查询可以很好地工作

现在我想为一个时间轴选择所有Tweets,这意味着所有用户的Tweets,这些用户在当前登录用户的订阅列表中。我想到了一个使用subselect的解决方案,因此我的sql看起来像:

select * from TWEET where author_id in (
    select subscriptions_ID from TWITTERUSER_TWITTERUSER where subscribers_ID = ?loggedInUserId);

这个查询工作得很好,但我不知道如何使用CriteriaBuilder和泛型写下它。我甚至没有得到一段可能在其他点失败的可编译代码,因为我不确定子查询的类型应该是什么。 我现在搜索了很多示例,但它们大多只是使用原始类型或使用子查询来检索in子句左侧的元素

也许我想念树林,但我真的很困惑(


共 (3) 个答案

  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();
    }
    

    我的缺点是:

    • Criteria API只是能够 对一个区域内的对象进行比较 相等()但不在in()内 陈述但我没有得到一份工作 这是一个有益的例外 生成的查询错误(eclipselink&derby):(
    • in()语句 从左手边开始 语句,值语句 可能性的清单 措辞让我困惑
    • 我不能简单地访问ID 在所有订阅中,我必须使用 参加如果你认为 关于桌子的结构但是我 当我只是想 我的物品

    注:我的解决方案完全没有选择用户自己的推文!^

  2. # 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模型,这可能会让您开始学习