当我的实体成员字段中没有 Set 时,如何在 JPA 中构造 SetJoin?

Dav*_*ave 5 hibernate jpa criteria jpa-2.0

我使用的是 JPA 2.0、Hibernate 4.1.0.Final 和 MySQL 5.5.37。我有以下实体

@Entity
@Table(name = "user_subscription",
    uniqueConstraints = { @UniqueConstraint(columnNames = { "USER_ID", “SUBSCRIPTION_ID" }) }
)
public class UserSubscription
{

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

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

    @ManyToOne
    @JoinColumn(name = “SUBSCRIPTION_ID", nullable = false, updatable = true)
    private Subscription subscription;
Run Code Online (Sandbox Code Playgroud)

@Entity
@Table(name = "Subscription")
public class Subscription implements Serializable 
{

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

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "PRODUCT_ID")
    @NotNull
    private Product product;
Run Code Online (Sandbox Code Playgroud)

在不更改实体的情况下,如何构建 JPA CriteriaBuilder 查询,在其中查找没有特定订阅实体“A”但具有与实体“A”匹配相同产品的其他订阅实体的用户实体?我试过这个无济于事……

public List<User> findUsersWithSubscriptions(Subscription Subscription)
{
    final List<User> results = new ArrayList<User>();
    final CriteriaBuilder builder = m_entityManager.getCriteriaBuilder();
    final CriteriaQuery<UserSubscription> criteria = builder.createQuery(UserSubscription.class);
    final Root<UserSubscription> root = criteria.from(UserSubscription.class);

    Join<UserSubscription, Subscription> SubscriptionRoot = root.join(UserSubscription_.subscription);

    criteria.select(root).where(builder.equal(root.get(UserSubscription_.Subscription).get(Subscription_.product),subscription.getProduct()),
                                builder.notEqual(root.get(UserSubscription_.subscription), subscription));
Run Code Online (Sandbox Code Playgroud)

我想如果我可以从用户 -> 订阅实体构建一个 SetJoin,我可以说“not.in”之类的东西,但我不知道如何在限制条件下做到这一点。

编辑:这是 Vlad 的帖子生成的 SQL:

url AS url97_, user1_.user_demographic_info_id AS USER18_97_, user1_.user_name AS user14_97_ FROM sb_user_subscription subscription0_ INNER JOIN sb_user user1_ON subscription0_.user_id = user1_.id INNER JOIN cb_subscription2.ON JOIN cb_subscription_product_subscription_3_subscription_3_product_subscription_3_subscription2. = product3_.id AND product3_.id = ? AND subscription2_.id <>?id INNER JOIN cb_subscription subscription2_ON subscription0_.subscription_id = subscription2_.id INNER JOIN sb_product product3_ON subscription2_.product_id = product3_.id AND product3_.id = ? AND subscription2_.id <>?id INNER JOIN cb_subscription subscription2_ON subscription0_.subscription_id = subscription2_.id INNER JOIN sb_product product3_ON subscription2_.product_id = product3_.id AND product3_.id = ? AND subscription2_.id <>?

Vla*_*cea 1

检查这个查询:

\n\n
final CriteriaBuilder builder = m_entityManager.getCriteriaBuilder();\nfinal CriteriaQuery<User> criteria = builder.createQuery(User.class);\nfinal Root<UserSubscription> root = criteria.from(UserSubscription.class);\n\nJoin<UserSubscription, User> userJoin = root.join(UserSubscription_.user);\nJoin<UserSubscription, Subscription> subscriptionJoin = root.join(UserSubscription_.subscription);\nJoin<Subscription, Product> productJoin = subscriptionJoin.join(Subscription_.product);\n\ncriteria\n    .select(userJoin)\n    .where(cb.and(\n         builder.equal(productJoin, subscription.getProduct()),\n         builder.notEqual(subscriptionJoin, subscription)\n);\nreturn entityManager.createQuery(criteria).getResultList();\n
Run Code Online (Sandbox Code Playgroud)\n\n

输出查询看起来不错,它应该选择具有给定 subscription.product 且订阅与产品父级订阅不同的用户。

\n\n

您可以在 SQL 控制台中尝试它,但它看起来不错并且验证了初始要求:

\n\n
\n

没有特定的订阅实体 \xe2\x80\x9cA\xe2\x80\x9d,但具有与实体 \xe2\x80\x9cA\xe2\x80\x9d 匹配相同产品的其他订阅实体

\n
\n