【问题标题】:JPA Criteria api join through embedded IDJPA Criteria api 通过嵌入式 ID 加入
【发布时间】:2014-05-04 16:07:52
【问题描述】:

我有以下实体:

@Entity
@Table(name = "place_revision")
public class PoiRevision {
    @OneToMany(mappedBy = "pk.revision", cascade = {CascadeType.ALL})
    private Collection<PoiRevisionCategory> categoryMapping;
    // ...
}

@Entity
@Table(name = "place_revision__category")
@AssociationOverrides({
    @AssociationOverride(name = "pk.revision",
        joinColumns = @JoinColumn(name = "place_revision_id")),
    @AssociationOverride(name = "pk.category",
        joinColumns = @JoinColumn(name = "category_id"))
})
public class PoiRevisionCategory {
    @EmbeddedId
    private PoiRevisionCategoryId pk = new PoiRevisionCategoryId();
    // ...
}

@Embeddable
public class PoiRevisionCategoryId implements Serializable {
    @ManyToOne
    private PoiRevision revision;
    @ManyToOne
    private Category category;
    // ...
}

@Entity
@Table(name = "category")
public class Category {
    @ManyToMany(targetEntity = Section.class, cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
    @JoinTable(
        name = "category__section",
        joinColumns = @JoinColumn(name = "category_id"),
        inverseJoinColumns = @JoinColumn(name = "section_id")
    )
    private Collection<Section> sections;
    // ...
}

并且想要选择有CategoriesPoiRevisions 有一些Sections。 我正在使用 Spring-data Specification 来查询数据库中的这些实体。

我的意图是写这样的东西:

Specification<PoiRevision> spec = new Specification<PoiRevision>() {
    @Override
    public Predicate toPredicate(Root<PoiRevision> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
        List<Predicate> conditions = new ArrayList<>(CONDITION_COUNT);

        CollectionJoin<PoiRevision, PoiRevisionCategory> mapping = root.join(PoiRevision_.categoryMapping);
        // BROKEN here as we cannot use nested path for joins
        Join<PoiRevisionCategory, Category> categories = mapping.join("pk.category"); 
        conditions.add(categories.get("sections").in(sections));

        // ...

        return cb.and(conditions.toArray(new Predicate[] {}));
    }
};

但是我们不能使用嵌套路径来进行这样的连接,因为 JPA 提供程序(在我的例子中是 Hibernate)只查找 PoiRevisionCategory 类的直接属性。而且我们不能将嵌入的 Id“加入”到我们的结果集中,因为它不是一个可管理的实体。

我真的被这个问题困住了,当翻译成 SQL 时,它似乎远非复杂,但它在 ORM 方面有一些复杂性。

非常感谢任何想法。

【问题讨论】:

  • this thread @gustavo 中提到了一些persistence.xml 设置以启用@Embedded 实体管理通过休眠。听起来这样可能会有所帮助,但也可能有一些缺点。但是我还找不到这个参数。

标签: java hibernate jpa spring-data criteria-api


【解决方案1】:

完全切换到元模型 API 后,它变得更加清晰,我实际上能够加入嵌入式实体,就像我尝试使用字符串 api 失败一样。

所以正确的方法就是像平常一样加入

Join<PoiRevisionCategory, PoiRevisionCategoryId> pk = mapping.join(PoiRevisionCategory_.pk);
Join<PoiRevisionCategoryId, Category> cats = pk.join(PoiRevisionCategoryId_.category);
CollectionJoin<Category, Section> sec = cats.join(Category_.sections);
conditions.add(sec.get(Section_.id).in(sections));

它做得很好!

真是一种解脱。

【讨论】:

  • 您是如何让它为您的嵌入式ID 生成元模型的?我的没有元模型...
  • @Amalgovinus,嗨,我写这篇文章已经有一段时间了,我不再能够访问代码本身,但我不记得元模型生成有任何问题。
  • 我最后只是取消了 embeddedID 并添加了一个代理键,使用标准 API 管理自然键太痛苦了
  • 不能怪你 :) 在处理 ORM 时使用代理键通常要容易得多。过去我只是沉迷于数据库纯粹主义者的观点。
  • @Amalgovinus 元模型生成可以使用 hibernate-jpamodelgen 完成;然后需要将其配置/添加到您的 maven pom 中,例如在 Maven“生成源”阶段运行。请咨询JPA-metamodels with maven 了解一些指南。
猜你喜欢
  • 2015-02-15
  • 1970-01-01
  • 2015-05-30
  • 2015-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-17
相关资源
最近更新 更多