报表中的参数(Parameters )是应用程序与报表引擎之间沟通的桥梁,它可以用于以下用途:
" J) l( H. C4 y; V% g3 k; h% {* c, K# {% d: N; C) i
传递 SQL 查询中的参数值,比如 SQL 语句中的 where 条件。
) d4 `( _% D) J' l5 Q
提供数据源所无法提供的值,比如自定义表头、生成该报表的账号、应用所指定的图片路径等等。
& I# @ v W W& F' D3 f参数由一个名称和一个 Java 实现类(Class)组成。比如 java.sql.Connection 类型的参数,一般用于子报表(subreport);而 java.lang.Boolean 类型的参数,用于是否展示报表的某一部分。; w( D6 _2 K( N( n+ k
参数可以设定一个默认值,这样如果应用没有传递该参数值,JasperReports 也能正确解析。2 w( o8 A5 j) p
1 管理参数
% o; }# p! O1 U7 w' g5 L3 {& b4 k5 n# }. z
可以使用 outline 面板来管理参数。, y8 f% y/ A! I0 L0 h
Parameters 下的那些灰色参数,表示是系统级的参数,不能编辑或者删除它。@( L5 A0 A' L8 e
右键点击 Parameters ,就可以创建参数:
3 e. _ f8 b1 \. K
4 @2 P/ Z0 v# F8 v7 f1 b
右键点击某个具体参数,就可以选择删除它。
: R: U: p, d. ?$ Y5 Q6 O点击某个具体参数,就可以在 Properties 面板中,对其进行查看或设置:8 @) M/ [5 W L3 ^
有以下这些可设置项:3 }) x5 Y0 _) J, m0 D: g* N* t
设置项说明Name参数名。Class参数实现类。Default Value Expression参数默认值,它可以是一个表达式。Description参数说明。JasperReports 没有直接使用该值,但为了便于未来维护,建议还是要填写下。Is for Prompting如果勾选该项,当在 Jaspersoft Studio 中点击 Preview 预览报表时,就会弹出参数输入框,供预览者依据实际情况填写报表所需的参数值。在 Properties 面板的 Advanced 选项卡中,可以按照键值对的方式,对其进行设置:+ W' u7 ]5 M+ T4 l
2 内置参数( ]( k) k2 X' [1 ?1 j' X
4 @0 O J1 r) e) m3 u
Jaspersoft Studio 定义了一些内置参数,具体说明如下:
" B+ s5 `9 o. D9 U0 w( N内置参数说明REPORT_PARAMETERS_MAP使用者调用 API 中的 fillReport() 方法所传入的 Map 型键值对参数。REPORT_CONNECTION报表中的 JDBC connection,用于执行 SQL 语句。REPORT_MAX_COUNT报表所能填充的最大记录数。如果未指定,则没有限制。REPORT_DATA_SOURCE如果没有使用 JDBC connection(比如非数据库的数据源 CSV 等),将会使用这个参数。REPORT_SCRIPTLET报表创建时的脚本实例,默认使用 net.sf.jasperreports.engine.JRDefaultScriptlet。REPORT_LOCALElocale 区域设置,一般用于国际化场景。默认为系统值。REPORT_TIME_ZONE所在时区,默认为系统值。REPORT_FORMAT_FACTORY默认实现是 net.sf.jasperreports.engine.util.FormatFactory。可以参考该工厂类,实现自定义工厂。REPORT_CLASS_LOADER可用于设置报表填充时的 class loader。REPORT_URL_HANDLER_FACTORY可用于指定创建 URL handlers 实现工厂。REPORT_FILE_RESOLVER默认实现是 net.sf.jasperreports.engine.util.FileResolver,用于解析报表中的资源路径,也可以自定义。REPORT_VIRTUALIZER定义报表填充器的实现类,默认为 JRVirtualizer 接口的实现类。IS_IGNORE_PAGINATIONBoolean 类型,分页开关。默认情况下,除了导出 excel 与 HTML 之外,其它情况不分页。3 查询场景
4 S! }6 A. U. j" y2 R3 D9 d
5 b. a2 G- {# _# j+ T4 F1 u, V- K一般情况下,JasperReports 会把传入的参数放入 sql statement 中,然后再执行查询,这样可以避免 SQL 注入问题。当然这也会使得参数不够灵活,无法把 SQL 片段作为参数传入语句。5 q3 J9 W* {7 a( Z+ {' T5 }% k3 J( _, {
3.1 SQL 语句中的参数8 g) |2 B0 D* S( p F3 `) m
& m/ w8 }" G0 P# h
参数可以定义在 where 条件中,用于过滤数据,语法为 $P{参数名},比如:
0 M9 U+ O$ c; i) D... and T3.STAFF_NO = $P{staff_no}这条语句将会以 prepared statement 形式加以执行:8 |* ^7 g" F" G2 g$ w9 _
... and T3.STAFF_NO = ?在 Jaspersoft Studio 的 Input Parameters 中,输入 staff_no 参数(记得先定义好这个参数)值:
9 N7 C* x) P5 O; I! R
5 k3 M% H3 b. a9 C$ ]# o
输出结果:
/ C8 w: Z' a/ m
参数也可以传入 SQL 片段,用于拼接 SQL 语句,语法为 $P!{参数名},比如:
% w& _$ j7 |/ R; S ^and $P!{conditions}在 Jaspersoft Studio 的 Input Parameters 中,输入 conditions 参数值:``T3.STAFF_NO = 1`,输出结果与上例相同。
9 {2 i1 f2 U t) B0 i' z利用该语法,甚至可以把整个 SQL 语句作为参数传入报表引擎。形如 $P!{自定义SQL语句}7 f( a) m! F4 c! _ k$ Y
一个 query 可以包含任意个入参,当遇到语法 $P!{xxx} 时,就会被替换为所传入的实际值。3 i8 I5 t' g' z. v" t
注意: 必须为参数设置默认值,让报表更健壮。
6 ^5 g( q0 {7 j, |3.2 处理 SQL 语句中的 Null
5 N! i5 o7 u, [; `- Y2 ~( @# e0 y
9 ^4 `% q/ b. f/ X$P{parametername} 格式的参数,无法正确处理 Null 值,我们可以使用 $X{EQUAL,fieldname,parametername}来处理 Null 值。
9 }: A6 g, C0 R, K比较这两种写法的区别:
# I( |4 z, Z: }" i6 j* ?) v' V% b: m' W( D9 x
$P{param} 模式的语句为 select * from client where address = $P{address_param}) v* B4 _9 K1 i I( u6 W, V1 d
$X{EQUAL, column_name, param_name} 模式的语句为 select * from client where $X{EQUAL, address , address_param}
4 A. l# C! R+ m' e4 t) {/ E" ]2 N. T) a- F! V: x: A
$ j5 _$ n& z7 l% o
如果 address_param 参数值不为 Null,那么这两种写法,都会被解析为 select * from client where address = '北京'。5 ~" w- l/ {9 ^0 p6 J& |# u: C
如果 address_param 参数值为 Null,那么 $P{} 模式会被解析为 select * from client where address = null,而 $X{} 模式会被解析为 select * from client where address is null。V+ c9 |2 f0 V) ^- H4 J9 F7 C5 W$ \很明显,$X{} 的解析模式才是正确的 SQL 处理 null 的模式。* [0 Q3 T/ R& z9 ~5 E
3.3 处理 SQL 语句中的 IN 与 NOT IN 形式
5 m0 B, w6 Y0 j, G7 E- \$ v+ J0 y4 C* K p- i4 z) }1 x9 P; X
JasperReports 使用特殊语法来应对 where 中的 IN 与 NOT IN 形式。
- f" O! d6 N% V' TIN 一般用于一系列的值,比如:! X# D1 G% k; G O% q" O. p! F2 b
select * from client where address in ('北京','上海','广州')
0 Q& r$ k- C+ uaddress 的参数值一般是一个列表(最好是 java.util.Collection)或者一个数组,之前的 SQL 可以用以下语法来表示:
2 l8 _% x% j+ h7 gselect * from client where $X{IN, address,address_values}, K' {6 t1 J6 S, N
address_values 是包含一系列地址数据的参数,$X{} 支持三个入参:
, I. v |; c+ G! j0 V$ ~( a ?, J) D# V# d V) D& j1 q
IN 或者 NOTIN
7 l9 i$ q' x8 a, V- W
字段名
, P; e1 u% i8 K6 J8 x0 g5 [
参数名
% @) b; A8 Y7 i s4 |- @如果传入的参数是 null 或者是一个空列表,$X{} 会解析为 0 = 0。$ h6 U; i$ o5 b
3.4 处理时间
$ d/ W: U+ Q3 p" k4 D7 A# X3 ]. x( y- T) J7 g* S* q: H. C
3.4.1 表达式1 B+ l, z# E( e ^
; u) o! v) q' O7 Z. m
可以使用类型为 DateRange 的参数,来作为时间条件,过滤数据。
! N! _. f. S$ d' g6 S6 h表达式格式为 +/-,具体说明如下:7 B: Z" _ J5 i4 C% R, w
/ h: [( p8 J. k. R# ^6 p5 D ?
指定时间单位,可为 DAY, WEEK, MONTH, QUARTER, SEMI 和 YEAR。/ F6 t% ]" w' j% [ q Z/ e0 O9 J) W
表示是在该时间之前(-)还是之后(+)。
, \& \- E! ?+ v& D C
表示 N 个时间单位。6 I2 d* V: v) p! k3 u% A比如 DAY - 1 表示前一天。
, N: ?+ O# q1 f$ S1 P& P这种表达方式存在一定的局限性,只能表示某个时间点的左右偏移量。如果要表示时间范围,可以用 BETWEEN 语法:5 T3 g2 Y9 Q! ~
$X{BETWEEN, column, startParam, endParam}比如说要设置当前周到某一天的,可以这样表示:) v2 F2 I7 L( w& r
$X{BETWEEN, column, WEEK, DAY}3.4.2 时间范围参数类型/ C1 `* A1 E" g
8 A/ F2 Z( }1 x& G' O
[table][tr]参数类型说明示例[/tr][tr][td]net.sf.jasperreports.types.date.DateRange[/td][td]以 YYYY-MM-DD 格式表示的日期字符串。[/td][td]