KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > jasperreports > engine > query > JRJpaQueryExecuter


1 /*
2  * ============================================================================
3  * GNU Lesser General Public License
4  * ============================================================================
5  *
6  * JasperReports - Free Java report-generating library.
7  * Copyright (C) 2001-2005 JasperSoft Corporation http://www.jaspersoft.com
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
22  *
23  * JasperSoft Corporation
24  * 303 Second Street, Suite 450 North
25  * San Francisco, CA 94107
26  * http://www.jaspersoft.com
27  */

28 package net.sf.jasperreports.engine.query;
29
30 import java.util.HashSet JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.Map JavaDoc;
34 import java.util.Set JavaDoc;
35
36 import javax.persistence.EntityManager;
37 import javax.persistence.Query;
38
39 import net.sf.jasperreports.engine.JRDataSource;
40 import net.sf.jasperreports.engine.JRDataset;
41 import net.sf.jasperreports.engine.JRException;
42 import net.sf.jasperreports.engine.JRParameter;
43 import net.sf.jasperreports.engine.JRPropertiesMap;
44 import net.sf.jasperreports.engine.JRRuntimeException;
45 import net.sf.jasperreports.engine.JRValueParameter;
46 import net.sf.jasperreports.engine.data.JRJpaDataSource;
47 import net.sf.jasperreports.engine.util.JRProperties;
48 import net.sf.jasperreports.engine.util.JRStringUtil;
49
50 import org.apache.commons.logging.Log;
51 import org.apache.commons.logging.LogFactory;
52
53 /**
54  * EJBQL query executer that uses the Java Persistence API.
55  * <p/>
56  * To use EJBQL in queries, an <code>javax.persistence.EntityManager</code> is needed.
57  * When running or filling reports the <code>em</code> need to be supplied with the named parameter {@link net.sf.jasperreports.engine.query.JRJpaQueryExecuterFactory#PARAMETER_JPA_ENTITY_MANAGER}.
58  * <p/>
59  * Example:
60  * <code>
61  * <pre>
62  * Map parameters = new HashMap();
63  * EntityManager em = emf.createEntityManager();
64  * parameters.put(JRJpaQueryExecuterFactory.PARAMETER_JPA_ENTITY_MANAGER, em);
65  * JasperRunManager.runReportToPdfFile(fileName, parameters);
66  * </pre>
67  * </code>
68  * <p/>
69  * When dealing with large result sets, pagination can be used by setting the {@link net.sf.jasperreports.engine.query.JRJpaQueryExecuterFactory#PROPERTY_JPA_QUERY_PAGE_SIZE} property in the report template.
70  * <p/>
71  * Example:
72  * <code>
73  * <pre>
74  * &lt;property name="net.sf.jasperreports.ejbql.query.page.size" value="100"/&gt;
75  * </pre>
76  * </code>
77  * <p/>
78  * Implementation-specific query hints can be set either using report properties in the report template,
79  * or by supplying the named parameter {@link net.sf.jasperreports.engine.query.JRJpaQueryExecuterFactory#PARAMETER_JPA_QUERY_HINTS_MAP}
80  * containing a <code>java.util.Map</code> with named/value query hints.
81  * <p/>
82  * Example using report property:
83  * <code>
84  * <pre>
85  * &lt;property name="net.sf.jasperreports.ejbql.query.hint.fetchSize" value="100"/&gt;
86  * </pre>
87  * </code>
88  * The name of the query hint need to be prefixed with <code>net.sf.jasperreports.ejbql.query.hint.</code> ({@link net.sf.jasperreports.engine.query.JRJpaQueryExecuterFactory#PROPERTY_JPA_QUERY_HINT_PREFIX}).
89  * Above example will set a query hint with the name <code>fetchSize</code> and the <code>String</code> value <code>100</code>.
90  * <p/>
91  * Example using map:
92  * <code>
93  * <pre>
94  * Map hints = new HashMap();
95  * hints.put("fetchSize", new Integer(100));
96  * hints.put("anyName", anyObject());
97  * Map parameters = new HashMap();
98  * EntityManager em = emf.createEntityManager();
99  * parameters.put(JRJpaQueryExecuterFactory.PARAMETER_JPA_ENTITY_MANAGER, em);
100  * parameters.put(JRJpaQueryExecuterFactory.PARAMETER_JPA_QUERY_HINTS_MAP, hints);
101  * JasperRunManager.runReportToPdfFile(fileName, parameters);
102  * </pre>
103  * </code>
104  * Note that when using report properties only <code>String</code> values can be set as query hint.
105  * When using a query hints map, any <code>Object</code> can be set as value.
106  *
107  * @author Marcel Overdijk (marceloverdijk@hotmail.com)
108  * @version $Id: JRJpaQueryExecuter.java 1472 2006-11-09 19:16:52 +0200 (Thu, 09 Nov 2006) lucianc $
109  * @see net.sf.jasperreports.engine.query.JRJpaQueryExecuterFactory
110  */

111 public class JRJpaQueryExecuter extends JRAbstractQueryExecuter {
112
113     private static final Log log = LogFactory.getLog(JRJpaQueryExecuter.class);
114     
115     private final Integer JavaDoc reportMaxCount;
116     
117     private EntityManager em;
118     private Query query;
119     
120     public JRJpaQueryExecuter(JRDataset dataset, Map JavaDoc parameters) {
121         super(dataset, parameters);
122         
123         em = (EntityManager)getParameterValue(JRJpaQueryExecuterFactory.PARAMETER_JPA_ENTITY_MANAGER);
124         reportMaxCount = (Integer JavaDoc)getParameterValue(JRParameter.REPORT_MAX_COUNT);
125
126         if (em == null) {
127             log.warn("The supplied javax.persistence.EntityManager object is null.");
128         }
129     
130         parseQuery();
131     }
132     
133     public JRDataSource createDatasource() throws JRException {
134         JRDataSource datasource = null;
135         String JavaDoc queryString = getQueryString();
136         
137         if (em != null && queryString != null && queryString.trim().length() > 0) {
138             createQuery(queryString);
139
140             datasource = createResultDatasource();
141         }
142         
143         return datasource;
144     }
145
146     /**
147      * Creates the EJBQL query object.
148      *
149      * @param queryString the query string
150      */

151     protected synchronized void createQuery(String JavaDoc queryString) {
152         
153         if (log.isDebugEnabled())
154         {
155             log.debug("EJBQL query: " + queryString);
156         }
157         
158         query = em.createQuery(queryString);
159         
160         // Set parameters.
161
List JavaDoc parameterNames = getCollectedParameterNames();
162         if (!parameterNames.isEmpty()) {
163             // Use set to prevent the parameter to be set multiple times.
164
Set JavaDoc namesSet = new HashSet JavaDoc();
165             for (Iterator JavaDoc iter = parameterNames.iterator(); iter.hasNext();) {
166                 String JavaDoc parameterName = (String JavaDoc)iter.next();
167                 if (namesSet.add(parameterName)) {
168                     JRValueParameter parameter = getValueParameter(parameterName);
169                     String JavaDoc ejbParamName = getEjbqlParameterName(parameterName);
170                     Object JavaDoc paramValue = parameter.getValue();
171                     
172                     if (log.isDebugEnabled())
173                     {
174                         log.debug("Parameter " + ejbParamName + ": " + paramValue);
175                     }
176                     
177                     query.setParameter(ejbParamName, paramValue);
178                 }
179             }
180         }
181
182         // Set query hints.
183
// First, set query hints supplied by the JPA_QUERY_HINTS_MAP parameter.
184
Map JavaDoc queryHintsMap = (Map JavaDoc)getParameterValue(JRJpaQueryExecuterFactory.PARAMETER_JPA_QUERY_HINTS_MAP);
185         if (queryHintsMap != null) {
186             for (Iterator JavaDoc i = queryHintsMap.entrySet().iterator(); i.hasNext(); ) {
187                 Map.Entry JavaDoc pairs = (Map.Entry JavaDoc)i.next();
188                 log.debug("EJBQL query hint [" + pairs.getKey() + "] set.");
189                 query.setHint((String JavaDoc)pairs.getKey(), pairs.getValue());
190             }
191         }
192         // Second, set query hints supplied by report properties which start with JREjbPersistenceQueryExecuterFactory.PROPERTY_JPA_PERSISTENCE_QUERY_HINT_PREFIX
193
// Example: net.sf.jasperreports.ejbql.query.hint.fetchSize
194
// This property will result in a query hint set with the name: fetchSize
195
JRPropertiesMap datasetProperties = dataset.getPropertiesMap();
196         String JavaDoc[] propertyNames = datasetProperties.getPropertyNames();
197         for (int i = 0; i < propertyNames.length; i++) {
198             String JavaDoc propertyName = propertyNames[i];
199             if (propertyName.startsWith(JRJpaQueryExecuterFactory.PROPERTY_JPA_QUERY_HINT_PREFIX)) {
200                 String JavaDoc queryHint = propertyName.replaceFirst(
201                         JRJpaQueryExecuterFactory.PROPERTY_JPA_QUERY_HINT_PREFIX,
202                         "");
203                 if (queryHint != null && queryHint.length() > 0) {
204                     String JavaDoc property = datasetProperties.getProperty(propertyName);
205                     log.debug("EJBQL query hint [" + queryHint + "] set to: " + property);
206                     query.setHint(queryHint, property);
207                 }
208             }
209         }
210     }
211
212     /**
213      * Creates a data source out of the query result.
214      *
215      * @return the data source
216      */

217     protected JRDataSource createResultDatasource() {
218         JRDataSource resDatasource;
219         
220         JRPropertiesMap datasetProperties = dataset.getPropertiesMap();
221         
222         try {
223             int pageSize = JRProperties.getIntegerProperty(datasetProperties,
224                     JRJpaQueryExecuterFactory.PROPERTY_JPA_QUERY_PAGE_SIZE,
225                     0);
226
227             resDatasource = new JRJpaDataSource(this, pageSize);
228         }
229         catch (NumberFormatException JavaDoc e) {
230             throw new JRRuntimeException("The " + JRJpaQueryExecuterFactory.PROPERTY_JPA_QUERY_PAGE_SIZE +
231                     " property must be numerical.");
232         }
233         
234         return resDatasource;
235     }
236
237     public synchronized void close() {
238         query = null;
239     }
240
241     public synchronized boolean cancelQuery() throws JRException {
242         return false;
243     }
244     
245     protected String JavaDoc getParameterReplacement(String JavaDoc parameterName) {
246         return ':' + getEjbqlParameterName(parameterName);
247     }
248     
249     protected String JavaDoc getEjbqlParameterName(String JavaDoc parameterName) {
250         return JRStringUtil.getLiteral(parameterName);
251     }
252     
253     /**
254      * Runs the query by calling <code>javax.persistence.Query.getResultList</code>.
255      * <p/>
256      * All the result rows are returned.
257      *
258      * @return the result of the query as a list
259      */

260     public List JavaDoc getResultList() {
261         if (reportMaxCount != null) {
262             query.setMaxResults(reportMaxCount.intValue());
263         }
264         
265         return query.getResultList();
266     }
267     
268     /**
269      * Returns a page of the query results by calling <code>javax.persistence.Query.getResultList</code>.
270      *
271      * @param firstIndex the index of the first row to return
272      * @param resultCount the number of rows to return
273      * @return result row list
274      */

275     public List JavaDoc getResultList(int firstIndex, int resultCount) {
276         if (reportMaxCount != null && firstIndex + resultCount > reportMaxCount.intValue()) {
277             resultCount = reportMaxCount.intValue() - firstIndex;
278         }
279         
280         query.setFirstResult(firstIndex);
281         query.setMaxResults(resultCount);
282         
283         return query.getResultList();
284     }
285 }
286
Popular Tags