// ======================================================================== // Copyright (C) zeroth Project Team. All rights reserved. // GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007 // http://www.gnu.org/licenses/agpl-3.0.txt // ======================================================================== package zeroth.framework.enterprise.infra.persistence; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import javax.enterprise.inject.Default; import javax.persistence.EntityManager; import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import zeroth.framework.enterprise.shared.Persistable; import zeroth.framework.standard.shared.Pageable; import zeroth.framework.standard.shared.Sort.Direction; import zeroth.framework.standard.shared.Sort.Order; /** * 先進データ永続化サービス(JPA2/CriteriaQuery) * <p> * {@link SimplePersistenceServiceImpl} へクエリオブジェクト(Criteria)を追加したサービスである。(クエリオブジェクト@PofEAA) である。 * </p> * @param <E> エンティティ型 * @param <ID> 識別子オブジェクト型 * @since JPA 2.0 * @author nilcy */ @Default public class QueryPersistenceServiceImpl<E extends Persistable<ID>, ID extends Serializable> extends SimplePersistenceServiceImpl<E, ID> implements QueryPersistenceService<E, ID> { /** 識別番号 */ private static final long serialVersionUID = 6451157743975586409L; /** 標準ビルダー */ private final CriteriaBuilder builder; /** 標準クエリ */ public CriteriaQuery<E> query; /** 標準ルート */ public Root<E> root; /** * コンストラクタ * @param manager エンティティマネージャ * @param clazz エンティティクラス */ public QueryPersistenceServiceImpl(final EntityManager manager, final Class<E> clazz) { super(manager, clazz); builder = manager.getCriteriaBuilder(); query = builder().createQuery(clazz); root = query().from(clazz); } /** {@inheritDoc} */ @Override public CriteriaBuilder builder() { return builder; } /** {@inheritDoc} */ @Override public CriteriaQuery<E> query() { return query; } /** {@inheritDoc} */ @Override public Root<E> root() { return root; } /** {@inheritDoc} */ @Override public TypedQuery<E> createQuery() { return manager.createQuery(query); } /** * {@inheritDoc} * <p> * ページ条件があるとき、オフセット、ページサイズ、ソート条件をクエリへ設定して、範囲指定クエリを作成する。 ページ条件がないとき、クエリを作成する。 * </p> */ @Override public TypedQuery<E> createQuery(final Pageable pageable) { if (pageable != null) { if (pageable.getSort() != null) { final Collection<javax.persistence.criteria.Order> criteriaOrders = new ArrayList<>(); for (final Iterator<Order> iter = pageable.getSort().iterator(); iter.hasNext();) { final Order order = iter.next(); if (Direction.ASC.equals(order.getDirection())) { criteriaOrders.add(builder.asc(root.get(order.getProperty()))); } else { criteriaOrders.add(builder.desc(root.get(order.getProperty()))); } } query.orderBy(criteriaOrders.toArray(new javax.persistence.criteria.Order[0])); } return createRangeQuery(createQuery(), pageable.getOffset(), pageable.getPageSize()); } return createQuery(); } /** * {@inheritDoc} * <p> * WHERE句がないとき表明エラーとする。標準ルートとWHERE句をもとに件数クエリを作成する。 * </p> */ @Override public TypedQuery<Long> createCountQuery(final Predicate expression) { assert expression != null; return manager.createQuery(builder().createQuery(Long.class) .select(builder().count(root())).where(expression)); } }