net.sf.jasperreports.engine.query.package-info Maven / Gradle / Ivy
/*
* JasperReports - Free Java Reporting Library.
* Copyright (C) 2001 - 2023 Cloud Software Group, Inc. All rights reserved.
* http://www.jaspersoft.com
*
* Unless you have purchased a commercial license agreement from Jaspersoft,
* the following license terms apply:
*
* This program is part of JasperReports.
*
* JasperReports 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 3 of the License, or
* (at your option) any later version.
*
* JasperReports 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 JasperReports. If not, see .
*/
/**
* Provides support for report queries and query executers.
*
* Report SQL Queries
* To fill a report, provide the reporting engine with the report data, or at least instruct it
* how to get this data.
*
* JasperReports normally expects to receive a
* {@link net.sf.jasperreports.engine.JRDataSource} object as the report data source, but
* it has also been enhanced to work with JDBC so that it can retrieve data from relational
* databases if required.
*
* The library allows the report template to specify the SQL query for report data if this
* data is located in relational databases.
* The SQL query specified in the report template is taken into account and executed only if
* a java.sql.Connection
object is supplied instead of the normal
* {@link net.sf.jasperreports.engine.JRDataSource} object when filling the report.
*
* This query can be introduced in the JRXML report template using the <queryString>
* element. If present, this element comes after the report parameter declarations and before
* the report fields.
*
* Report parameters in the query string are important to further refine the data retrieved
* from the database. These parameters can act as dynamic filters in the query that supplies
* data for the report. Parameters are introduced using a special syntax, similar to the one
* used in report expressions.
*
* There are three possible ways to use parameters in the query, described below:
*
* $P{paramName}
Syntax - the parameters are used like normal java.sql.PreparedStatement
parameters
* $P!{paramName}
Syntax - the parameters are used to dynamically modify portions of the SQL
* query or to pass the entire SQL query as a parameter to the report-filling routines. The
* value supplied for those parameters replace the parameter references in the query, before
* it is sent to the database server using a java.sql.PreparedStatement
object.
* $X{functionName, param1, param2,...}
Syntax - There are also cases when a part of the query
* needs to be dynamically built starting from a report parameter value, with the query part containing both
* query text and bind parameters. This is the case, for instance, with IN
and NOT IN
* query clauses that need to use a collection report parameter as a list of values. Such complex query clauses are
* introduced into the query using the $X{} syntax.
*
* In the majority of cases, the SQL query text placed inside a report template is a SELECT
* statement. JasperReports uses a java.sql.PreparedStatement
behind the scenes to
* execute that SQL query through JDBC and retrieve a java.sql.ResultSet
object to
* use for report filling. However, the SQL query string might also contain stored procedure
* calls.
*
* Certain conditions must be met to put stored procedure calls in the SQL query string of a
* report template:
*
* - The stored procedure must return a
java.sql.ResultSet
when called through JDBC.
* - The stored procedure cannot have OUT parameters.
*
* Query Executers
* Report data can be produced by specifying queries in languages other than SQL. Each query language
* is associated a query executer factory implementation. JasperReports has built-in query executer
* implementations for SQL, Hibernate 3, XPath, EJB-QL, CSV and Excel queries.
*
* The query language is specified in JRXML using the language
attribute of the
* <queryString>
tag. Using the API, the query language is set by
* {@link net.sf.jasperreports.engine.design.JRDesignQuery#setLanguage(String) setLanguage(String)}. The default language is SQL, thus ensuring
* backward compatibility for report queries that do not specify a query language.
*
* To register a query executer factory for a query language, one has to define a
* JasperReports property named
* {@link net.sf.jasperreports.engine.query.QueryExecuterFactory#QUERY_EXECUTER_FACTORY_PREFIX net.sf.jasperreports.query.executer.factory.<language>}. The same mechanism can be used to
* override the built-in query executers for a query language, for instance to use a custom
* query executer for SQL queries.
*
* The API for query executers involves an executer factory interface, a query executer
* interface, implementations of these interfaces, and {@link net.sf.jasperreports.engine.JRDataSource} implementations.
*
* {@link net.sf.jasperreports.engine.query.QueryExecuterFactory} is a factory interface used to query executers for a specific
* language and to provide information regarding the connection parameters required by the
* query executer to run the query. It has the following methods:
*
* public JRQueryExecuter createQueryExecuter(JasperReportsContext jasperReportsContext, JRDataset dataset, Map<String,? extends JRValueParameter> parameters)
-
* This method creates a query executer. The dataset includes the query string and the fields that
* will be requested from the data source created by the query executer. The parameters map contains
* parameter types and runtime values to be used for query parameters. This method usually sends the
* dataset and parameters map to the created query executer.
* public Object[] getBuiltinParameters()
- This method returns parameters that will
* be automatically registered with a report/dataset based on the query language. These parameters will
* be used by query executers as the context/connection on which to execute the query. For instance,
* the Hibernate query executer factory specifies a HIBERNATE_SESSION
parameter of type
* org.hibernate.Session
whose value will be used by the query executer to run the query.
* public boolean supportsQueryParameterType(String className)
- This method is used on
* report validation to determine whether a query parameter type (for a parameter specified in the query
* using $P{..}
) is supported by the query executer implementation.
*
* A {@link net.sf.jasperreports.engine.query.JRQueryExecuter} is responsible for running a query, creating a
* data source out of the result, and closing the result. It includes these methods:
*
* public JRDataSource createDatasource()
- This method processes and runs the query
* and creates a data source out of the query result. Usually, the required data (query string and parameter
* values) is made available to the query executer by the factory on creation.
* public void close()
- This method closes the query execution result and any other
* resource associated with it. It is called after all data produced by the query executer has been fetched.
* public boolean cancelQuery()
- This method is called when the user decides to cancel
* a report fill process. The implementation should check whether the query is
* currently being executed and ask the underlying mechanism to abort the execution.
* The method should return true if the query was being executed and the execution
* was canceled. If execution abortion is not supported, the method will always return false.
*
* Query executer implementation can benefit from using
* {@link net.sf.jasperreports.engine.query.JRAbstractQueryExecuter} as
* a base. The abstract base provides query parameter processing functionality and other
* utility methods.
*
* In most cases, a query executer needs a new {@link net.sf.jasperreports.engine.JRDataSource}
* implementation to wrap its specific query results. Still, in some of the cases, query executers
* can use existing {@link net.sf.jasperreports.engine.JRDataSource} implementations.
*
* Note that registering new query executer implementations by adding properties in the
* jasperreports.properties
file, as mentioned above, is only one way of registering
* the executers. They can be registered in a more transparent way by using the
* JasperReports extension support. One ore more query executer implementations can be
* packaged in a query executer bundle that can be deployed as a single JAR file. This
* approach obviates the need to modify existing application files. The query executer
* extension point in JasperReports is represented by the
* {@link net.sf.jasperreports.engine.query.QueryExecuterFactoryBundle} interface.
*
* SQL Query Executer
* The SQL query executer is a JDBC-based executer for SQL queries.
*
* The SQL query executer factory does not register any parameter as the
* {@link net.sf.jasperreports.engine.JRParameter#REPORT_CONNECTION REPORT_CONNECTION} parameter
* is kept in all reports for backward compatibility. The
* SQL query executer uses this parameter to retrieve a java.sql.Connection
object.
* The query executer creates a {@link net.sf.jasperreports.engine.JRResultSetDataSource} data source to wrap the JDBC
* result set.
*
* Aborting the currently running query is supported using
* java.sql.PreparedStatement.cancel()
when running a report asynchronously by using {@link net.sf.jasperreports.engine.fill.FillHandle#cancellFill()}.
* Alternatively, the query timeout of the JDBC statement used by the query executer can be set to cancel the query after a certain amount of time by using the
* {@link net.sf.jasperreports.engine.query.JRJdbcQueryExecuterFactory#PROPERTY_JDBC_QUERY_TIMEOUT net.sf.jasperreports.jdbc.query.timeout} configuration property
* at the report level or globally.
*
The fetch size of the JDBC statement used
* by the query executer behind the scenes can be set using the
* {@link net.sf.jasperreports.engine.query.JRJdbcQueryExecuterFactory#PROPERTY_JDBC_FETCH_SIZE net.sf.jasperreports.jdbc.fetch.size} configuration property at report level or
* globally.
*
* XPath Query Executer
* The XPath query executer permits reports using XML data sources to specify the XPath
* that produces the list of nodes/records as the report query.
*
* The query executer factory registers a parameter named
* {@link net.sf.jasperreports.engine.query.JRXPathQueryExecuterFactory#PARAMETER_XML_DATA_DOCUMENT XML_DATA_DOCUMENT}
* of type org.w3c.dom.Document
. The query executer will run the XPath query against this
* document and produce a {@link net.sf.jasperreports.engine.data.JRXmlDataSource} data source.
*
* Parameters are supported in the XPath query. All parameters will be replaced in the
* query string by their java.lang.String
values.
* This query executer recognizes four additional parameters that serve for localization
* purposes when creating the {@link net.sf.jasperreports.engine.data.JRXmlDataSource} instance:
*
* - {@link net.sf.jasperreports.engine.query.JRXPathQueryExecuterFactory#XML_LOCALE XML_LOCALE}
* - {@link net.sf.jasperreports.engine.query.JRXPathQueryExecuterFactory#XML_NUMBER_PATTERN XML_NUMBER_PATTERN}
* - {@link net.sf.jasperreports.engine.query.JRXPathQueryExecuterFactory#XML_DATE_PATTERN XML_DATE_PATTERN}
*
*
* Hibernate Query Executer
* JasperReports includes support for Hibernate 3 in the form of a query executer. This
* allows users to specify in a report an HQL query that should be used to retrieve report
* data.
*
* For reports having an HQL query, the executor factory will automatically define a
* parameter named {@link net.sf.jasperreports.engine.query.JRHibernateQueryExecuterFactory#PARAMETER_HIBERNATE_SESSION HIBERNATE_SESSION}
* of type org.hibernate.Session
. Its value will be used by the query executor to create the query.
*
* Like SQL queries, HQL queries can embed two types of parameters:
*
* - using
$P{..}
syntax - These parameters are used as named parameters of the Hibernate query.
* - using
$P!{..}
syntax - The java.lang.String
value of the parameter is substituted
* as-is in the query string before creating the Hibernate query. This type of parameter can be used to dynamically
* specify query clauses/parts.
*
* The result of a Hibernate query can be obtained in several ways. The Hibernate query
* executer chooses the way the query result will be produced based on a property named
* {@link net.sf.jasperreports.engine.query.JRHibernateQueryExecuterFactory#PROPERTY_HIBERNATE_QUERY_RUN_TYPE net.sf.jasperreports.hql.query.run.type}. The run type can be one of the following:
*
* list
- The result is fetched using org.hibernate.Query.list()
. The result
* rows can be fetched all at once or in fixed-sized chunks. To enable paginated result row retrieval,
* the {@link net.sf.jasperreports.engine.query.JRHibernateQueryExecuterFactory#PROPERTY_HIBERNATE_QUERY_LIST_PAGE_SIZE net.sf.jasperreports.hql.query.list.page.size}
* configuration property should have a positive value.
* scroll
- The result is fetched using org.hibernate.Query.scroll()
.
* iterate
- The result is fetched using org.hibernate.Query.iterate()
.
*
* The fetch size of the query can be set using the
* {@link net.sf.jasperreports.engine.query.JRJdbcQueryExecuterFactory#PROPERTY_JDBC_FETCH_SIZE net.sf.jasperreports.jdbc.fetch.size} configuration property at report level or
* globally.
*
* However, when dealing with large amounts of data, using pagination is the most
* common way to present the document content. In this case, it is necessary to clear
* Hibernate's first-level cache after each page fetching, otherwise Hibernate will
* eventually cause an OutOfMemory error. If the Hibernate's session cache is regularly
* cleared, the memory trap can be avoided. Because flushing data and clearing the cache is
* a time-consuming process, you should use it only if really huge datasets are involved.
* This is why the {@link net.sf.jasperreports.engine.query.JRHibernateQueryExecuterFactory#PROPERTY_HIBERNATE_CLEAR_CACHE net.sf.jasperreports.hql.clear.cache} property was introduced.
* Normally, it defaults to false. If set to true, the periodic Hibernate session cache
* cleanup is performed after each page fetching.
*
* A report/dataset field is mapped to a value from the Hibernate query result either by its
* description or its name. By default, the program uses the report field name, but the report
* field description property can be used instead if the
* {@link net.sf.jasperreports.engine.query.JRHibernateQueryExecuterFactory#PROPERTY_HIBERNATE_FIELD_MAPPING_DESCRIPTIONS net.sf.jasperreports.hql.field.mapping.descriptions} configuration
* property is set to true either in the report template or globally.
*
* The mappings are similar to the ones used by JavaBeans data sources, except that select aliases are
* used when queries return tuples instead of single objects.
*
* MDX Query Executer
* Reporting on OLAP data is supported in JasperReports via the MDX query executer and
* a data source that use the Mondrian API's (this is why often we refer to this query
* executer also as the Mondrian query executer). Users can create reports with MDX
* queries and map report fields onto the OLAP result; the engine will execute the query via
* Mondrian and pass the result to a data source implementation, which will be used to fill
* the report.
*
* The Mondrian query executer is registered by default for queries having MDX
or mdx
as
* the language specified in the report template. One can use JasperReports configuration
* properties to register additional or alternative query language to query executer mappings
*
* The Mondrian query executer requires a single connection parameter named
* {@link net.sf.jasperreports.olap.JRMondrianQueryExecuterFactory#PARAMETER_MONDRIAN_CONNECTION MONDRIAN_CONNECTION}
* of type mondrian.olap.Connection
.
*
* MDX queries can contain placeholders for parameters of any type. When the query gets
* executed, each parameter placeholder will be replaced in the query string by its
* toString()
value. Therefore, for MDX queries, $P{...}
parameters are equivalent to
* $P!{...}
query fragments.
*
* The Mondrian query executer passes the query result to a {@link net.sf.jasperreports.olap.JRMondrianDataSource}, which
* will be used to iterate the result and map values from the result to the report fields.
* The field mapping deals with mapping values from the OLAP result to the report fields.
* As an OLAP result has a multidimensional and hierarchical structure while a
* JasperReports data source has a tabular structure, mapping values to fields is not a trivial
* task.
*
* A special syntax is used to specify what value should be mapped to a field. The field
* description is used to hold the mapping specification.
*
* Using the mapping syntax, one can map two types of values from the OLAP result:
*
* - Member values are names or properties of members of the result axes.
* - Data/measure values are cell values from the result.
*
* The Mondrian data source performs a traversal of the OLAP result by iterating the
* members of the result axes. On every step, each field is checked for whether its mapping
* matches the current position in the OLAP result. If so, the value is extracted from the
* result and set to the field.
*
* XML/A Query Executer
* MDX queries can also be executed on remote OLAP data sources via the XML for
* Analysis interface. This functionality is implemented in JasperReports as a query
* executer.
*
* Just like the Mondrian query executer presented in the previous section, the XML/A
* query executer is also mapped by default to the MDX
and mdx
query languages, but the
* Mondrian query executer takes precedence.
*
* The dispatch between the two query executers that are mapped on the same query
* language is done by a special query executer implementation. It is actually the
* {@link net.sf.jasperreports.olap.JRMdxQueryExecuterFactory} class that is registered by default
* with the MDX
and mdx
* query languages, and it delegates the creation of the query instances at runtime to either
* the {@link net.sf.jasperreports.olap.JRMondrianQueryExecuterFactory} or the
* {@link net.sf.jasperreports.olap.xmla.JRXmlaQueryExecuterFactory},
* depending on the specific parameter values that are passed in at report-filling time.
* It first checks for the
* {@link net.sf.jasperreports.olap.JRMondrianQueryExecuterFactory#PARAMETER_MONDRIAN_CONNECTION MONDRIAN_CONNECTION}
* parameter, and if found, the Mondrian query executer takes over. If this parameter is not found, it
* then checks for the {@link net.sf.jasperreports.olap.xmla.JRXmlaQueryExecuterFactory#PARAMETER_XMLA_URL PARAMETER_XMLA_URL}
* to see if the XMLA query executer can be used. In fact, there are 3 possible connection parameters for the
* XML/A query executer:
*
* XMLA_URL
- a java.lang.String
value representing the XMLA/SOAP service URL
* XMLA_DATASOURCE
- a java.lang.String
value representing the information
* required to connect to the OLAP data source
* XMLA_CATALOG
- a java.lang.String
value representing name of the OLAP catalog to use
*
* The XMLA query executer creates a data source equivalent to the one created by the
* Mondrian query executer, with a few minor exceptions.
*
* This means that the result cube traversal and field mapping logic available for the
* MDX query executer applies for the XMLA query executer as well.
*
* The XMLA query executer lacks some of the functionality of the Mondrian query
* executer, due to inherent limitations of the XML for Analysis standard. The missing
* features are the following:
*
* - Mapping report fields to custom member properties does not work with XML/A
* - For XMLA, it is not possible to produce a complete
mondrian.olap.Member
* object, hence this feature is not supported.
* - Parent member matching using the
mondrian.olap.Member.getParent()
method
* does nor work via XML/A, since the parent member information is not present in the response.
*
* EJB-QL/JPA Query Executer
* The EJB-QL report query executer adds support for reporting on EJB 3.0 persistent
* entities data. For an EJB-QL query in a report, the query executer will use the EJB 3.0
* Java Persistence API to execute the query against an entity manager provided at runtime,
* and use the query result as a data source for the report.
*
* The built-in EJB-QL query executer is registered by default for queries having EJBQL
or
* ejbql
as their language. This mapping can be changed by using JasperReports
* properties.
*
* The EJB-QL query executer contributes built-in parameters to the report:
*
* - The entity manager to be used for executing the query
* - An optional query hints map
*
* When the report template contains an EJB-QL query, one must provide a JPA entity
* manager at runtime; the query executer will run the query using the supplied entity
* manager. The entity manager is of type javax.persistence.EntityManager
and
* should be provided via the
* {@link net.sf.jasperreports.engine.query.JRJpaQueryExecuterFactory#PARAMETER_JPA_ENTITY_MANAGER JPA_ENTITY_MANAGER}
* built-in parameter:
*
* Map parameters = new HashMap();
* javax.persistence.EntityManager entityManager = createEntityManager();
* parameters.put( JRJpaQueryExecuterFactory.PARAMETER_JPA_ENTITY_MANAGER, entityManager );
* JasperFillManager.fillReport(jasperReport, parameters);
*
* The means of getting hold of an entity manager depends on the particular EJB/JPA
* environment and implementation.
*
* An additional parameter named
* {@link net.sf.jasperreports.engine.query.JRJpaQueryExecuterFactory#PARAMETER_JPA_QUERY_HINTS_MAP JPA_QUERY_HINTS_MAP}
* allows you to specify query hints for running the query. The parameter value should be a map containing hint values
* mapped to hint names. The hints are set using the
*
* javax.persistence.Query.setHint(String hintName, Object value)
method.
*
* Hints can also be specified statically by using report properties. The query executer treats
* any report property starting with
* {@link net.sf.jasperreports.engine.query.JRJpaQueryExecuterFactory#PROPERTY_JPA_QUERY_HINT_PREFIX net.sf.jasperreports.ejbql.query.hint.<hintName>} as a hint by interpreting
* the property suffix as the hint name and the property value as the hint value. Thus, if the
* following property is present in the report:
*
* <property name="net.sf.jasperreports.ejbql.query.hint.cacheType" value="Shared"/>
*
* then the cacheType
hint having Shared
as value will be set when running the query.
*
* Note that only hints that accept String values can be set using this mechanism.
*
* A separate report property can be used to paginate the query result. This property can be
* used for controlling the amount of Java heap space used by the query executer while
* filling the report. The property can be set in the following manner:
*
* <property name="net.sf.jasperreports.ejbql.query.page.size" value="500"/>
*
* The results of the query will be fetched in chunks containing 500 rows.
*
* The pagination is achieved via the javax.persistence.Query.setMaxResults()
* and setFirstResult()
methods. Obviously, using pagination could result in
* performance loss. Therefore enabling it is primarily recommended when the query
* results are very large.
*
* EJB-QL report queries can contain parameters of any type. At runtime, the value of the
* parameter is directly set by using
* javax.persistence.Query.setParameter(String name, Object value)
, with
* no other processing.
*
* The result of the query execution is sent to a
* {@link net.sf.jasperreports.engine.data.JRJpaDataSource}
* data source implementation, which iterates
* over it and extracts report field values. Fields are mapped to specific values in the query
* result by specifying the mapping as field description or field name.
* The JPA data source can handle two types of query results:
*
* - Queries returning a single entity/bean per row
* - Queries returning object tuples as rows
*
* When the query returns a single entity/bean per row, as in
*
* SELECT m FROM Movie m
*
* or
*
* SELECT NEW MovieDescription(m.title, m.gender) FROM Movie m
*
* then the field mappings are interpreted as bean property names. The same conventions as for
* JavaBeans data sources are used.
*
* When the query returns multiple objects per row, as in
*
* SELECT m.title, m.gender FROM Movie m
*
* then the fields are mapped using one of the following forms:
*
* COLUMN_<index>
- maps the field to a value specified by its position
* in the resulting tuple. The positions start from 1.
* COLUMN_<index>.<property>
- maps the field to a property of a
* value specified by its position in the resulting tuple.
*
* For instance, the following mappings could be used for a query returning multiple
* objects per row: COLUMN_1
, COLUMN_2
, COLUMN_1.title
, and
* COLUMN_2.movie.title
.
*
* Related Documentation
* JasperReports Tutorial
* @see net.sf.jasperreports.engine.JRDataSource
* @see net.sf.jasperreports.engine.JRResultSetDataSource
* @see net.sf.jasperreports.engine.data.JRJpaDataSource
* @see net.sf.jasperreports.engine.data.JRXmlDataSource
* @see net.sf.jasperreports.olap.JRMdxQueryExecuterFactory
* @see net.sf.jasperreports.olap.JRMondrianDataSource
* @see net.sf.jasperreports.olap.JRMondrianQueryExecuterFactory
* @see net.sf.jasperreports.olap.xmla.JRXmlaQueryExecuterFactory
*/
package net.sf.jasperreports.engine.query;