【问题标题】:how to get data or query from Many to Many?如何从多对多获取数据或查询?
【发布时间】:2019-07-02 12:03:59
【问题描述】:

我有产品和代码实体,我为它们建立了多对多关系,所以它将是 Product_Code

所以 Product_Code 将有 product_id 和 product_id

我真的很想通过代码从产品中获取数据,但是我想要的结果我也想要产品值和代码值的详细信息,我不知道如何在 JPA 上做到这一点

我想先获取产品代码,然后在 Product_Code 表中找到该 id 的 id 产品,然后从中获取数据并在代码实体上再次找到代码的 id, 我确信有办法为此获取数据,但我不知道如何,我确实喜欢用简单的方法来了解它是如何工作的

我是新手

我的实体产品是这样的

@Entity
@Table(name = "PRODUCT")
@Setter
@Getter
@DynamicUpdate
public class Product extends Base {

    @ManyToMany(mappedBy = "products", fetch = FetchType.EAGER)
    private Set<Code> codes;

    @Column(name = "NAME", nullable = false)
    private String Name;

    @Column(name = "DESCRIPTION")
    private String description;

    public int hasCode() {
        return Objects.hashCode(getId());
    }

} 

这是我的代码实体:

@Entity
@Table(name = "CODE")
@DynamicUpdate
@Setter
@Getter
public class Voucher extends Base {

    @ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
    @JoinTable(name = "PRODUCT_CODE",
               joinColumns =  @JoinColumn(name = "CODE_ID"),
               inverseJoinColumns = @JoinColumn(name = "PRODUCT_ID"))
    private Set<Product> products;

    @Column(name = "CODE", unique = true)
    private String codeName;

    @Column(name = "TYPE", nullable = false)
    private String type;

    private String descriptions;

    public int hasCode() {
            return Objects.hashCode(getId());
        }
}

当我尝试通过代码查找时,我真的很想获取所有数据 假设我想找到一个代码像“A7”的产品,所以我想从产品实体中获取,然后我会得到详细的代码实体,也像那个产品一样带有 product_id 和 code_id

当我尝试 Product findByCode(String code)Product findOneByCode(String code) 结果是我扩展的Base 实体而不是产品实体, Base 实体是可重用的实体,例如 generate id, token, createdAt, deletedAt, updatedAt

【问题讨论】:

  • 你要根据具体的Voucher.codeName获取List吗?
  • 是的,这可能吗?
  • 我试过这个 "SELECT p.name , v.code " + " from Product p " + " INNER JOIN ProductCode cp ON p.id = cp.productId " + " INNER JOIN Code v on v.id = cp.codeId WHERE v.code = ?1" 但失败
  • 是的,我建议您使用JpaSpecificationExecutor 存储库和CriteriaBuilder.isMember 函数。通过 id 选择 Code 并将其传递给 isMember 函数。
  • 你有例子吗?我不是按id找的,我要按code的名字找

标签: java spring hibernate spring-boot jpa


【解决方案1】:

这可以在启用JpaSpecificationExecutor&lt;Product&gt; 的存储库上使用Specification&lt;Product&gt; 来实现。

  1. 确保您的ProductRepository 实现JpaSpecifiactionExecutor&lt;Product&gt;

然后,在你的@Service 的某个地方同时注入VoucherRepositoryProductRepository 做:

//implement a method in VoucherRepository findByName which returns Voucher instance.
Voucher code = voucherRepository.findByName("A7");

//then pass the instance to isMember function in ProductRepository
List<Product> products = productRepository.findAll((r, q, b) -> b.isMember(code, Product_.codes));

评论

r, q, b 是 lambda 表达式的方法参数,例如实现 Specification&lt;Product&gt; 覆盖方法 toPredicate。如果您的项目限制您使用 Java 7 及以下版本,您可以使用以下方法实现此对象:

Specification<Product> spec = new Specification<Product>() {
        @Override
        public Predicate toPredicate(Root<Product> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
            return criteriaBuilder.isMember(code, root.get(Product_.codes));
        }
};

参数

r 代表根元素Root&lt;Product&gt;

q代表条件查询CriteriaQuery&lt;?&gt;

b 代表标准构建器CriteriaBuilder

Product_.* 是您的Product 实体的静态元模型。它可以使用 JPA 模型生成器自动生成,也可以使用 @Staticmetamodel 注释手动创建。

通过执行findAll(Specification&lt;Product&gt;),您可以进行类似过滤的选择,您的结果列表将仅包含符合您条件的产品。

编辑:

您的 Product 元模型可能看起来像(目前),但是,我建议使用元模型生成器。

@StaticMetamodel(Product.class)
public class Product_ {
      public static volatile SetAttribute<Product, Code> codes;
}

【讨论】:

  • 什么是r, q, b ?我应该在 findAll 的产品回购中设置参数吗??
  • 我还是一头雾水
  • 我还是不明白,如何正确创建@Staticmetamodel?
  • 添加了简单的例子。请用谷歌搜索,因为这与您所问的问题无关。
  • @StaticMetamodel 写在 repo 上?还是服务?
猜你喜欢
  • 2013-02-01
  • 1970-01-01
  • 2021-01-30
  • 1970-01-01
  • 2020-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多