我们正在使用Crystal Reports XI,并且我使用一个表生成了一个简单的报告。在创建报告期间,我使用ODBC连接到我们的开发数据库。 现在我想在Java中运行时更改数据源,以便连接到我们的另一个数据库。
所以我创建了一个更改数据源的方法。因为我们使用不同的数据库系统(infomix,oracle和mysql)。
private ReportClientDocument replaceDatabaseConnection(ReportClientDocument doc, Database database, String ip, String port, String dbname, String dbservername, String username, String passwort, String userOrSchemaName) {
StopWatch sw = new StopWatch();
try {
for (int i = 0; i < doc.getDatabaseController().getDatabase().getTables().size(); i++) {
ITable table = doc.getDatabaseController().getDatabase().getTables().get(i);
sw.start(table.getName());
System.out.println("processing table : " + table.getName());
// dbane.owner.tablename
String original_qualifiedName = table.getQualifiedName();
String new_qualifierName = original_qualifiedName;
switch (database) {
case ORACLE:
// SCHEMA.TABLENAME
String tableName = StringUtils.substringAfterLast(original_qualifiedName, ".").toUpperCase();
new_qualifierName = userOrSchemaName.toUpperCase()+"."+tableName;
break;
case INFORMIX:
// DATABASE.OWNER.TABLENAME
new_qualifierName = dbname + ":" + userOrSchemaName + "." + StringUtils.substringAfterLast(original_qualifiedName, ".");
break;
case MYSQL:
// DATABASE.OWNER.TABLENAME
new_qualifierName = dbname + "." + userOrSchemaName + "." + StringUtils.substringAfterLast(original_qualifiedName, ".");
break;
default:
break;
}
String jdbcConnectionString = null;
String preQEServerName = null;
String driver = null;
switch (database) {
case INFORMIX:
// !com.informix.jdbc.IfxDriver!jdbc:informix-sqli://localhost:40421/export:INFORMIXSERVER=cargool1!user={userid}!password={password}
jdbcConnectionString = "!com.informix.jdbc.IfxDriver!jdbc:informix-sqli://"+ip+":"+port+"/"+dbname+":INFORMIXSERVER="+dbservername+"!user={userid}!password={password}";
// jdbc:informix-sqli://localhost:40421/export:INFORMIXSERVER=cargool1
preQEServerName = "jdbc:informix-sqli://"+ip+":"+port+"/"+dbname+":INFORMIXSERVER="+dbservername;
// com.informix.jdbc.IfxDriver
driver = "com.informix.jdbc.IfxDriver";
break;
case MYSQL:
// !com.mysql.jdbc.Driver!jdbc:mysql://172.20.9.170:3306/hego
jdbcConnectionString = "!com.mysql.jdbc.Driver!jdbc:mysql://"+ip+":"+port+"/"+dbname;
// jdbc:mysql://172.20.9.170:3306/customer
preQEServerName = "jdbc:mysql://"+ip+":"+port+"/"+dbname;
// com.mysql.jdbc.Driver
driver = "com.mysql.jdbc.Driver";
break;
case ORACLE:
// !oracle.jdbc.driver.OracleDriver!jdbc:oracle:thin:@//localhost:50000/tmsddb2
jdbcConnectionString = "!oracle.jdbc.driver.OracleDriver!jdbc:oracle:thin:@//"+ip+":"+port+"/"+dbname;
// jdbc:oracle:thin:@//localhost:50000/tmsddb2
preQEServerName = "jdbc:oracle:thin:@//"+ip+":"+port+"/"+dbname;
// "oracle.jdbc.driver.OracleDriver"
driver = "oracle.jdbc.driver.OracleDriver";
break;
default:
break;
}
System.out.println("Qualfied Name : "+ table.getQualifiedName());
table.setQualifiedName(new_qualifierName);
ConnectionInfo newConnectionInfo = new ConnectionInfo();
PropertyBag boPropertyBag1 = new PropertyBag();
boPropertyBag1.put("JDBC Connection String", jdbcConnectionString);
boPropertyBag1.put("PreQEServerName", preQEServerName);
boPropertyBag1.put("Server Type", "JDBC (JNDI)");
boPropertyBag1.put("Database DLL", "crdb_jdbc.dll");
boPropertyBag1.put("Database", dbname);
boPropertyBag1.put("Database Class Name", driver);
boPropertyBag1.put("Use JDBC", "true");
boPropertyBag1.put("Database Name", dbname);
boPropertyBag1.put("Server Name", preQEServerName);
boPropertyBag1.put("Connection URL", preQEServerName);
boPropertyBag1.put("Server", null);
newConnectionInfo.setAttributes(boPropertyBag1);
newConnectionInfo.setUserName(username);
newConnectionInfo.setPassword(passwort);
table.setConnectionInfo(newConnectionInfo);
doc.getDatabaseController().setTableLocation(table, doc.getDatabaseController().getDatabase().getTables().get(i));
System.out.println("***************************DONE********************************");
sw.stop();
}
return doc;
} catch (Exception ex) {
System.out.println(ExceptionUtils.getFullStackTrace(ex));
}
System.out.println(sw.prettyPrint());
return doc;
}
现在,如果我使用只有一个表的报表,那么stange行为是正常的。我可以毫无问题地连接到每个数据库,并且工作非常快。
但是如果报告有多个表,我会收到奇怪的数据库连接错误,即用户名/密码不正确。来自异常的用户名是完全错误的(它不是我传递给方法的用户名)。
com.crystaldecisions.sdk.occa.report.lib.ReportSDKLogonException:Fehler bei der Anmeldung:密码不正确或用户com.informix.asf.IfxASFRemoteException:数据库服务器上不知道username @ employee-nb1 .--- - 错误代码:-2147217393错误代码名称:dbLogonFailed
首先,我不想连接到informix数据库。我向方法传递了一个mysql参数。例外来自informix,它是我在创建报告期间连接到的数据库(通过ODBC)。
下一个奇怪的是用户名@ employee-nb1 用户名是我在创建报告时登录到数据库的用户名,最令人恼火的是emplyee-nb1。这是我们公司的一个笔记本的名称,但它与我无关。该报告从未在计算机上打开/创建,并且java进程也未在该计算机上运行。
就像我说的,如果我只使用一个表使用报告(以相同的方式创建),一切正常。有多个表,我收到此错误。我还没有使用任何子报告。
有人有想法吗?
这就是我调用方法的方法
private void createReport8() {
ReportClientDocument doc = new ReportClientDocument();
try {
doc.setReportAppServer(ReportClientDocument.inprocConnectionString);
doc.open("C:\\dev\\reports\\003_jdbc_informix_3_tabellen.rpt",OpenReportOptions._openAsReadOnly);
changeDataSource(doc, null, null, "username", "******", "!com.mysql.jdbc.Driver!jdbc:mysql://172.20.9.170:3306/customerdb", "com.mysql.jdbc.Driver", null);
PDFExportFormatOptions outputOptions = new PDFExportFormatOptions();
ExportOptions exportOptions = new ExportOptions();
exportOptions.setExportFormatType(ReportExportFormat.PDF);
exportOptions.setFormatOptions(outputOptions);
InputStream stream = doc.getPrintOutputController().export(
exportOptions);
byte[] bytes = StreamUtils.getBytes(stream);
FileUtils.writeByteArrayToFile(new File("C:\\dev\\reports\\pdf\\Infomix_MultipleTables001.pdf"), bytes);
}catch (Exception ex) {
System.out.println(ex);
}
}