BIRT 4.14代码执行报表抛SQL错误,设计器运行正常
BIRT 4.14报表代码执行时SQL/Schema错误排查方案
问题现象
BIRT 4.14设计的报表在设计器内运行正常,但通过Java代码调用时持续抛出SQL相关错误:
- 带
public前缀的SQL报语法错误:Syntax error: Encountered "public" at line 1, column 8 - 移除
public后报Schema不存在:Schema 'SA' does not exist - 移除SQL参数后仍触发相同Schema错误
错误日志
带public前缀时的报错:
Apr 23, 2024 6:36:39 PM org.eclipse.birt.data.engine.odaconsumer.Connection prepareOdaQuery SEVERE: Failed to prepare the following query for the data set type (org.eclipse.birt.report.data.oda.jdbc.JdbcSelectDataSet). [SELECT public.users.first_name, public.users.last_name FROM public.users WHERE id = ? ] org.eclipse.birt.report.data.oda.jdbc.JDBCException: Error preparing SQL statement. SQL error #1:Syntax error: Encountered "public" at line 1, column 8
移除public后的报错:
PM org.eclipse.birt.data.engine.odaconsumer.Connection prepareOdaQuery SEVERE: Failed to prepare the following query for the data set type (org.eclipse.birt.report.data.oda.jdbc.JdbcSelectDataSet). [SELECT first_name, last_name FROM users WHERE id = ? ] org.eclipse.birt.report.data.oda.jdbc.JDBCException: Error preparing SQL statement. SQL error #1:Schema 'SA' does not exist
移除参数后的报错:
Apr 23, 2024 6:40:02 PM org.eclipse.birt.data.engine.odaconsumer.Connection prepareOdaQuery SEVERE: Failed to prepare the following query for the data set type (org.eclipse.birt.report.data.oda.jdbc.JdbcSelectDataSet). [SELECT first_name, last_name FROM users ] org.eclipse.birt.report.data.oda.jdbc.JDBCException: Error preparing SQL statement. SQL error #1:Schema 'SA' does not exist
代码片段
public void generateReport(Integer userId, Integer courseId, HttpServletResponse response, HttpServletRequest request) throws EngineException, IOException, SQLException { IReportRunnable reportDesign = reportEngine.openReportDesign("UserStatistics\\user_answers_statistic_for_course.rptdesign"); // classpath in the result jar IRunAndRenderTask task = reportEngine.createRunAndRenderTask(reportDesign); response.setContentType(reportEngine.getMIMEType("pdf")); PDFRenderOption pdfRenderOption = new PDFRenderOption(); pdfRenderOption.setOutputFormat(HTMLRenderOption.OUTPUT_FORMAT_PDF); task.setRenderOption(pdfRenderOption); pdfRenderOption.setOutputStream(response.getOutputStream()); task.getAppContext().put("OdaJDBCDriverPassInConnection", dataSource.getConnection()); task.setParameter("UserId", userId, ""); task.setParameter("CourseId", courseId, ""); task.run(); }
核心原因
设计器与代码运行时的数据库连接默认Schema不一致:
- 设计器中配置的连接默认指向
publicSchema,因此带public前缀的SQL可正常执行; - 代码中
dataSource.getConnection()获取的连接默认使用SASchema(多数数据库如H2的默认用户/Schema为SA),但目标表实际在publicSchema下,导致找不到表; - 部分数据库驱动对
public.users这种Schema前缀写法支持有限,或当前连接用户无publicSchema访问权限,触发语法错误。
解决方案
方案1:修改代码中JDBC连接的默认Schema
获取连接后,手动指定默认Schema为public(不同数据库语法略有差异):
Connection conn = dataSource.getConnection(); // PostgreSQL语法 conn.createStatement().execute("SET search_path TO public"); // H2语法 // conn.createStatement().execute("SET SCHEMA public"); task.getAppContext().put("OdaJDBCDriverPassInConnection", conn);
方案2:调整报表SQL并确认权限
保持报表SQL的Schema前缀写法,同时确保代码使用的数据库用户拥有public Schema的访问权限:
SELECT first_name, last_name FROM public.users WHERE id = ?
方案3:对齐设计器与代码的数据源配置
确保设计器中使用的数据源(用户、默认Schema)与代码中dataSource的配置完全一致,消除环境差异。
验证步骤
- 应用上述任一方案后重新运行代码;
- 若仍报错,检查数据库用户对
publicSchema下users表的访问权限; - 打印当前连接的默认Schema,确认配置生效:
DatabaseMetaData meta = conn.getMetaData(); System.out.println("当前默认Schema: " + meta.getUserName()); // 不同数据库获取方式略有差异
内容的提问来源于stack exchange,提问作者Арина Бабаян
相关产品推荐
相关产品推荐

