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

时间:2014-06-22 16:32:33

标签: hibernate jpa jpa-2.0 criteria

我正在使用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;

@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;

在不更改实体的情况下,如何构建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));

我想如果我可以从用户构建SetJoin - &gt;订阅实体,我可以说像“not.in”这样的东西,但我不确定如何在限制条件下做到这一点。

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

SELECT user1_.id AS id97_,        user1_.creator_id AS CREATOR15_97_,        user1_.dob AS DOB97_,        user1_.enabled AS ENABLED97_,        user1_.expiration AS EXPIRATION97_,        user1_.first_name AS first5_97_,        user1_.grade_id AS GRADE16_97_,        user1_.incorrect_logins AS INCORRECT6_97_,        user1_.last_name AS last7_97_,        user1_.middle_name AS middle8_97_,        user1_.organization_id AS organiz17_97_,        user1_.password AS password97_,        user1_.reset_state AS RESET10_97_,        user1_.salutation AS salutation97_,        user1_.temporary_password AS temporary12_97_,        user1_.url AS url97_,        user1_.user_demographic_info_id AS USER18_97_,        user1_.user_name AS user14_97_ 来自sb_user_subscription subscription0_        INNER JOIN sb_user user1_                ON subscription0_.user_id = user1_.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&lt;&gt;?

1 个答案:

答案 0 :(得分:0)

检查此查询:

final CriteriaBuilder builder = m_entityManager.getCriteriaBuilder();
final CriteriaQuery<User> criteria = builder.createQuery(User.class);
final Root<UserSubscription> root = criteria.from(UserSubscription.class);

Join<UserSubscription, User> userJoin = root.join(UserSubscription_.user);
Join<UserSubscription, Subscription> subscriptionJoin = root.join(UserSubscription_.subscription);
Join<Subscription, Product> productJoin = subscriptionJoin.join(Subscription_.product);

criteria
    .select(userJoin)
    .where(cb.and(
         builder.equal(productJoin, subscription.getProduct()),
         builder.notEqual(subscriptionJoin, subscription)
);
return entityManager.createQuery(criteria).getResultList();

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

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

  

没有特定的订阅实体“A”,但有其他   与实体“A”匹配相同产品的订阅实体