简体   繁体   中英

What is the best approach to reuse multiple repository criterias?

I have an repository layer that have many methods combination, to match search criterias.. What is the best approach to reuse this criterias? I think that methods name like findByNameAndIdAndBirthdayAndAccounaNumber is not a good idea ! Thanks !

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

}

Sounds like you may be looking for the Specification pattern which would allow you write a method like:

public Order findOrderBySpecification(Specification specification) {

}

and then call this using a combination of one or more specifications eg by account number, by account number and name etc.

There is an example here using the Criteria API:

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

See also the article below which refers to the Spring Data project but which is probably worth a read anyway even if you are not using Spring.

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

Also, you can achieve this more simply using the QueryDSL library referenced in the article above rather than the rather verbose Criteria API with Straight JPA (ie without Spring).

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

Try to use the specification pattern in your repository implementation.

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);
    }
}

Then you must implment the logical specifications AndSpecification , OrSpecification , NotSpecification , etc..

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(); 
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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