Мы используем 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;
}
Теперь странное поведение: если я использую отчет только с одной таблицей, он работает нормально. Я могу без проблем подключиться к каждой базе данных, и она работает очень быстро.
Но если в отчете более одной таблицы, я получаю странные ошибки подключения к базе данных из-за неправильного имени пользователя / пароля Имя пользователя из исключения полностью неверно (это не имя пользователя, которое я передал методу).
com.crystaldecisions.sdk.occa.report.lib.ReportSDKLogonException: Fehler bei Anmeldung: неверный пароль или пользователь com.informix.asf.IfxASFRemoteException: username @ employee-nb1 не известен на сервере базы данных .--- - Код ошибки: -2147217393 Имя кода ошибки: dbLogonFailed
Во-первых, я не хотел подключаться к базе данных informix. Я передал методу параметр mysql. Исключение составляет информация о базе данных, к которой я подключился при создании отчета (через ODBC).
Следующая странная вещь заключается в том, что username @ 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);
}
}