【问题标题】:What is the best approach to reuse multiple repository criterias?重用多个存储库标准的最佳方法是什么?
【发布时间】:2015-02-23 16:45:50
【问题描述】:

我有一个包含许多方法组合的存储库层,以匹配搜索条件。重用此条件的最佳方法是什么?我认为像 findByNameAndIdAndBirthdayAndAccounaNumber 这样的方法名称不是一个好主意!谢谢!

public Order findByIdAndName(String orderId) {
List<OrderEntity> list = entityManager.createNamedQuery(OrderEntity.QUERY_FIND_BY_ORDERID_AND_NAME,     OrderEntity.class)
     .setParameter("orderId", orderId)
     .setParameter("name", name).getResultList();
if (list.isEmpty()) {
    return null;
}

OrderEntity orderEntity = list.get(0);

return toOrder(orderEntity);

}

【问题讨论】:

  • 这些名字没有错。您仍然需要使用 na、e、id、birthday 和 account 参数来定义这些查询。如果它让您烦恼,您可以使用 CriteriaBuilder 并从参数列表/映射构造查询...

标签: java jpa repository criteria


【解决方案1】:

听起来您可能正在寻找允许您编写如下方法的规范模式:

public Order findOrderBySpecification(Specification specification) {

}

然后使用一个或多个规范的组合来调用它,例如按帐号,按帐号和姓名等。

这里有一个使用 Criteria API 的示例:

http://java.dzone.com/articles/java-using-specification

另请参阅下面的文章,该文章引用了 Spring Data 项目,但即使您不使用 Spring,也可能值得一读。

http://spring.io/blog/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl/

此外,您可以更简单地使用上面文章中引用的 QueryDSL 库,而不是使用带有 Straight JPA(即没有 Spring)的相当冗长的 Criteria API。

http://blog.mysema.com/2010/04/querydsl-as-alternative-to-jpa-2.html http://www.querydsl.com/static/querydsl/2.1.0/reference/html/ch02s02.html

【讨论】:

  • Alan 从您的声誉来看,您是经验丰富的开发人员,所以我有一个问题。你在实际情况中使用过吗?它实际上比显式 JPA 查询更易于管理吗?您可以通过快速查看这些单行查询来检查它们,而使用规范您需要打开 X 类并检查它们的代码(其中很可能包含由 Ctr+C Ctr+V 引起的典型错误)。只是您的意见/经验?
  • 如果我选择使用 QueryDSL。我已经在 Hibernte/JPA 工作了 7 或 8 年,并且拥有 Oracle JPA 证书。即使我们暂时忽略规范,我也觉得 Criteria API 很糟糕。我宁愿使用 Criteria API 还是这样做: List users = repository.findAll(QUser.user.address.town.eq("London").and(QUser.user.gender.eq(Gender.M)) ) 和 X 和 Y 和 Z... 的任意组合;我在个人项目中使用它,下次我在绿地项目中工作时肯定会建议考虑它。
  • 对不起,我的意思是标准/规范方法与 JPQL 查询(文本或命名)。但是你已经表达了你对 Criteria 的厌恶,所以我想我知道答案了。
【解决方案2】:

尝试在您的存储库实现中使用规范模式。

OrderSpecificationByName.java

public class OrderSpecificationByName implements OrderSpecification, HibernateSpecification {
    private String name;

    public OrderSpecificationByName(String name) {
        super();
        this.name = name;
    }

    @Override
    public boolean isSatisfiedBy(Object order) {
        return ((Order)order).hasName(name);
    }

    @Override
    public Criterion toCriteria() {
        return Restrictions.eq("name", name);
    }
}

OrderSpecificationById.java

public class OrderSpecificationById implements OrderSpecification, HibernateSpecification { 
    private Long id;

    public OrderSpecificationById(String id) {
        super();
        this.id = id;
    }

    @Override
    public boolean isSatisfiedBy(Object order) {
        return ((Order)order).hasId(id);
    }

    @Override
    public Criterion toCriteria() {
        return Restrictions.eq("id", id);
    }
}

那么你必须实现逻辑规范AndSpecificationOrSpecificationNotSpecification等。

AndSpecification.java

public class AndSpecification implements HibernateSpecification {
    private Specification first;
    private Specification second;

    public AndSpecification(Specification first, Specification second) {
        first = first;
        second = second;
    }

    @Override
    public boolean isSatisfiedBy(Object candidate) {
        return first.isSatisfiedBy(candidate) && second.isSatisfiedBy(candidate);
    }

     @Override
    public Criterion toCriteria() {
        Conjunction conjuntion = Restrictions.conjunction();
        conjuntion.add(first.toCriteria());
        conjuntion.add(second.toCriteria());

        return conjuntion;
    }
}

OrderRepository.java

public List<Order> query(HibernateSpecification specification) {    
    Session session = sessionFactory.getCurrentSession();
    Criteria criteria = session.createCriteria(Order.class);
    criteria(specification.toCriteria());
    return criteria.list(); 
}

【讨论】:

  • 除非他没有使用任何 Hibernate 特定的代码。如果您根据 JPA 接口重写,那么尽管基本上是下面提出的,但可能是正确的答案。
  • 抱歉,您在我回复时发送了您的信息。是的,你是对的,他可以在他的案例中实现 JPA 接口。
猜你喜欢
  • 2021-11-15
  • 2020-04-28
  • 2019-12-24
  • 1970-01-01
  • 1970-01-01
  • 2021-02-09
  • 1970-01-01
  • 2020-09-26
  • 2012-04-25
相关资源
最近更新 更多