/* * Databinder: a simple bridge from Wicket to Hibernate * Copyright (C) 2006 Nathan Hamblen nathan@technically.us * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ package net.databinder.models.jpa; import java.util.Iterator; import javax.persistence.EntityManager; import javax.persistence.Query; import net.databinder.jpa.Databinder; import net.databinder.models.PropertyDataProvider; /** * Provides query results to DataView and related components. Like the Hibernate model classes, * the results of this provider can be altered by query binders and criteria builders. By default * this provider wraps items in a compound property model in addition to a Hibernate model. * This is convenient for mapping DataView subcomponents as bean properties (as with * PropertyListView). However, <b>DataTable will not work with a compound property model.</b> * Call setWrapWithPropertyModel(false) when using with DataTable, DataGridView, or any * other time you do not want a compound property model. * * @author rhansen@kindleit.net * * @param <T> Type of the Model */ public abstract class JPAProvider<T> extends PropertyDataProvider<T> { private static final long serialVersionUID = 3420653591929473081L; private QueryBuilder queryBuilder, countQueryBuilder; private String factoryKey; /** * Provides entities matching the given queries. * @param query Query the provider will work with. * @param countQuery Query that returns the element count in this provider */ public JPAProvider(final String query, final String countQuery) { this(new QueryBinderBuilder(query), new QueryBinderBuilder(countQuery)); } /** * Provides entities matching the given queries with bound parameters. * @param query query to return entities * @param queryBinder binder for the standard query * @param countQuery query to return count of entities * @param countQueryBinder binder for the count query (may be same as queryBinder) */ public JPAProvider(final String query, final QueryBinder queryBinder, final String countQuery, final QueryBinder countQueryBinder) { this(new QueryBinderBuilder(query, queryBinder), new QueryBinderBuilder(countQuery, countQueryBinder)); } public JPAProvider(final QueryBuilder queryBuilder, final QueryBuilder countQueryBuilder) { this.queryBuilder = queryBuilder; this.countQueryBuilder = countQueryBuilder; } /** @return session factory key, or null for the default factory */ public String getFactoryKey() { return factoryKey; } /** * Set a factory key other than the default (null). * @param key session factory key * @return this, for chaining */ public JPAProvider<T> setFactoryKey(final String key) { this.factoryKey = key; return this; } /** * It should not normally be necessary to override (or call) this default implementation. * @param first First element to retrieve in the list * @param count Number of elements to retrieve * @return An iterator for the returned elements */ @SuppressWarnings("unchecked") public Iterator<T> iterator(final int first, final int count) { final EntityManager em = Databinder.getEntityManager(factoryKey); final Query q = queryBuilder.build(em); q.setFirstResult(first); q.setMaxResults(count); return q.getResultList().iterator(); } /** * Only override this method if a single count query or * criteria projection is not possible. * @return The element count. */ public int size() { final EntityManager sess = Databinder.getEntityManager(factoryKey); final Query q = countQueryBuilder.build(sess); final Object obj = q.getSingleResult(); return ((Number) obj).intValue(); } /** does nothing */ @Override public void detach() { } }