繁体   English   中英

在EAV模型上进行复杂选择Spring数据jpa

[英]Complex select on EAV model Spring data jpa

我有一个如下的产品实体(简单版本)

@Entity
@Table(name = "product")
public class Product {
   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   private long id;

   @OneToMany(mappedBy = "product")
   private List<ProductAtt> attributes;
}

每个产品可以具有一个或多个属性。 属性如下所示

@Entity
@Table(name = "attribute")
public class Attribute {
   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   private long id;

   private String name;
}

因此,我使用附加值属性创建了如下所示的关系实体

@Entity
@Table(name = "product_att")
public class ProductAtt implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @ManyToOne
    @JoinColumn
    private Product product;

    @ManyToOne
    @JoinColumn
    private Attribute attribute;

    private int value;
}

现在,我想查找所有具有某些具有自定义值属性的产品。 例如,所有属性1的值为3且属性2的值为40和...的所有产品。

什么是最简单,最有效的查询?

由于要查询的属性数量在设计时未知,因此必须使用Spring Data JPA支持的动态查询机制之一。 当然,可以使用JPA规范或条件API构建查询。

如果使用QueryDSL支持,则可以使用exists子查询。 以下示例显示了如何完成此操作(假设使用Java 8和QueryDSL 4)。

interface ProductRepository
          extends CrudRepository<Product, Long>
                  , QueryDslPredicateExecutor<Product> {
  default Iterable<Product> findAllByAttributes(final Map<String, String> attributes) {
    final QProduct root = QProduct.product;
    BooleanExpression query = root.isNotNull();

    for (final String attribute : attributes.keySet()) {
      final QProductAttribute branch = root.attributes.any();
      final BooleanExpression subquery = branch.attribute.name.equalsIgnoreCase(attribute)
                                                          .and(branch.value.equalsIgnoreCase(attributes.get(attribute)));

      query = query.and(JPAExpressions.selectFrom(QProductAttribute.productAttribute).where(subquery).exists());
    }

    return findAll(query);
  }
}

应该注意的是,数据库设计必然会发生性能问题,因为包含相同表( ProductAttr )的次数与要搜索的属性一样多。 这不是QueryDSL,JPA,Hibernate,SQL或数据库服务器的问题,而是数据模型本身(也称为EAV模型)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM