Buongiorno a tutti,
sono qui per chiedervi una mano o qualche suggerimento su come ottimizzare l'apertura e la lettura dati su due diverse basi di dati.
Ho realizzato un'applicazione in java che permette di richiamare dal gestionale l'esportazioni in pdf e la stampa di un report creato tramite Crystal report. L'applicazione funziona, ma purtroppo impiega troppo tempo nell'eseguire l'esportazione o la stampa. Ho verificato i tempi per capire dove l'applicazione rallenta ed ho individuato la parte di codice dove accade quanto descritto. Riporto la parte interessata, spero qualcuno mi possa dare qualche suggerimento.
Ho inserito un timer per vedere il tempo impiegato per eseguire la lettura del report. Oracle impiegata ad eseguire questa parte in 5/6 secondo completando l'esecuzione con un secondo in più circa. All'incirca in 6/7 secondi esegue l'esportazione del file (ovviamente si deve considerare la dimensione dei dati del report).Mentre access impiega all'incirca il doppio e in alcuni casi anche il triplo per generare report con due dati in croce.
Questo è il metodo statico fornito da Crystal report che gestisce la modifica dei dati al db utilizzati dal report.
Questo è quanto. Tra le librerie previste da Crystal report è presente la log4j che in fase di runtime esegue il log e attraverso la console vedo l'esecuzione rallentare e ferimarsi per qualche istante quando deve connettersi al db. Spero qualcuno abbia già provato a lavorare su questi argomenti o comunque spero qualcuno mi possa dare una mano, perchè oggettivamente 18 secondi per esportare un file mi sembrano un pò troppi.
Grazie in anticipo per l'aiuto.
sono qui per chiedervi una mano o qualche suggerimento su come ottimizzare l'apertura e la lettura dati su due diverse basi di dati.
Ho realizzato un'applicazione in java che permette di richiamare dal gestionale l'esportazioni in pdf e la stampa di un report creato tramite Crystal report. L'applicazione funziona, ma purtroppo impiega troppo tempo nell'eseguire l'esportazione o la stampa. Ho verificato i tempi per capire dove l'applicazione rallenta ed ho individuato la parte di codice dove accade quanto descritto. Riporto la parte interessata, spero qualcuno mi possa dare qualche suggerimento.
Codice:
ReportClientDocument rcd=new ReportClientDocument();
rcd.open(nome_Rpt, OpenReportOptions._discardSavedData);
LetturaReport letturaReport=new LetturaReport();
letturaReport.dbConnection(dbConn, dbUser, dbPass,dbodbc,nomeTabella,id_Richiesta,rcd);
fine = System.currentTimeMillis();
time=(fine-inizio)/1000;
System.out.println("\n Tempo di esecuzione fino all'apertura db "+time + " sec");
Ho inserito un timer per vedere il tempo impiegato per eseguire la lettura del report. Oracle impiegata ad eseguire questa parte in 5/6 secondo completando l'esecuzione con un secondo in più circa. All'incirca in 6/7 secondi esegue l'esportazione del file (ovviamente si deve considerare la dimensione dei dati del report).Mentre access impiega all'incirca il doppio e in alcuni casi anche il triplo per generare report con due dati in croce.
Codice:
public void dbConnection(String dbConn,String dbUser, String dbPass,Jdbc_db dbodbc,String nomeTabella,long id_Richiesta,ReportClientDocument rcd) throws Exception
{
String nomeServer = null;
try{
/**
* estrae i nomi dei server
*
*/
for(String s:rcd.getDatabaseController().getServerNames())
{
// System.out.println(" nome Server "+s);
nomeServer=s;
}
if(nomeServer.contains("NOMEDBACCESS"))
{
dbAccess(dbodbc,nomeTabella,id_Richiesta,rcd);
}
else
{
dbOracle(dbConn,dbUser,dbPass,dbodbc,nomeTabella,id_Richiesta,rcd);
}
}
catch (ReportSDKException e)
{
Utility.updateTableCmd(String.valueOf(e.errorCode()), e.getMessage(), id_Richiesta, dbodbc, nomeTabella);
} catch (Exception e) {
Utility.updateTableCmd("7", e.getMessage(), id_Richiesta, dbodbc, nomeTabella);
}
}
/**
* Configura le proprietà per un file .rpt che si connette al db Access
* @param dbodbc
* @param nomeTabella
* @param id_richiesta
* @throws Exception
*/
public void dbAccess(Jdbc_db dbodbc,String nomeTabella,long id_richiesta,ReportClientDocument rcd) throws Exception
{
String connURL = "jdbc:ucanaccess://C://DATABASE//NOMEDB.mdb";
String dataBaseClassName="net.ucanaccess.jdbc.UcanaccessDriver";
String username="admin";
String password=null;
try {
if(rcd.getSubreportController().getSubreportNames().size()>0)
{
for(String subReportName: rcd.getSubreportController().getSubreportNames())
{
/**
* Ricava il nome della tabella che contiene il subReport indicato.
* Passa al metodo changeDataSource i riferimenti del subReport e della tabella.
* Al metodo getTable() viene passato il paramentro zero perchè si presume ci sia
* sempre un'unica tabella che può contenere uno o piu sottoreport
*/
String tableName=rcd.getSubreportController().getSubreportDatabase(subReportName).getTables().getTable(0).getName();
CRJavaHelper.changeDataSource(rcd, subReportName, tableName, username, password, connURL, dataBaseClassName, null);
}
}
else
{
/**
* Al metodo vengono passati solo i dati per la connessione, senza alcun riferimento
* a subReport
*/
CRJavaHelper.changeDataSource(rcd, username, password, connURL, dataBaseClassName, null);
rcd.getDatabaseController().logon("admin",null);
}
}
catch (ReportSDKException e)
{
Utility.updateTableCmd(String.valueOf(e.errorCode()), e.getMessage(), id_richiesta, dbodbc, nomeTabella);
}
}
public void dbOracle(String dbConn,String dbUser, String dbPass,Jdbc_db dbodbc,String nomeTabella,long id_richiesta,ReportClientDocument rcd) throws Exception
{
String dataBaseClassName="oracle.jdbc.driver.OracleDriver";
try {
if(rcd.getSubreportController().getSubreportNames().size()>0)
{
for(String subReportName: rcd.getSubreportController().getSubreportNames())
{
/**
* Ricava il nome della tabella che contiene il subReport indicato.
* Passa al metodo changeDataSource i riferimenti del subReport e della tabella.
* Al metodo getTable() viene passato il paramentro zero perchè si presume ci sia
* sempre un'unica tabella che può contenere uno o piu sottoreport
*/
String tableName=rcd.getSubreportController().getSubreportDatabase(subReportName).getTables().getTable(0).getName();
//CRJavaHelper.logonDataSource(rcd, dbUser, dbPass);
CRJavaHelper.changeDataSource(rcd, subReportName, tableName, dbUser, dbPass, dbConn, dataBaseClassName, null);
rcd.getDatabaseController().logon(dbUser,dbPass);
}
}
else
{
/**
* Al metodo vengono passati solo i dati per la connessione, senza alcun riferimento
* a subReport
*/
CRJavaHelper.changeDataSource(rcd, dbUser, dbPass, dbConn, dataBaseClassName, null);
rcd.getDatabaseController().logon(dbUser,dbPass);
}
}
catch (ReportSDKException e)
{
Utility.updateTableCmd(String.valueOf(e.errorCode()), e.getMessage(), id_richiesta, dbodbc, nomeTabella);
}
}
Questo è il metodo statico fornito da Crystal report che gestisce la modifica dei dati al db utilizzati dal report.
Codice:
/**
* Changes the DataSource for a specific Table
* @param clientDoc The reportClientDocument representing the report being used
* @param subreportName "" for main report, name of subreport for subreport, null for all reports
* @param tableName name of table to change. null for all tables.
* @param username The DB logon user name
* @param password The DB logon password
* @param connectionURL The connection URL
* @param driverName The driver Name
* @param jndiName The JNDI name
* @throws ReportSDKException
*/
public static void changeDataSource (ReportClientDocument clientDoc, String subreportName, String tableName,
String username, String password, String connectionURL, String driverName,
String jndiName) throws ReportSDKException
{
PropertyBag propertyBag = null;
IConnectionInfo connectionInfo = null;
ITable origTable = null;
ITable newTable = null;
// Declare variables to hold ConnectionInfo values.
// Below is the list of values required to switch to use a JDBC/JNDI
// connection
String TRUSTED_CONNECTION = "false";
String SERVER_TYPE = "JDBC (JNDI)";
// String SERVER_TYPE = "Server Oracle";
String USE_JDBC = "true";
String DATABASE_DLL = "crdb_jdbc.dll";
// String DATABASE_DLL = "crdb_oracle.dll";
// String JNDI_OPTIONAL_NAME = jndiName;
String CONNECTION_URL = connectionURL;
String DATABASE_CLASS_NAME = driverName;
// The next few parameters are optional parameters which you may want to
// uncomment
// You may wish to adjust the arguments of the method to pass these
// values in if necessary
// String TABLE_NAME_QUALIFIER = "new_table_name";
// String SERVER_NAME = "new_server_name";
// String CONNECTION_STRING = "new_connection_string";
// String DATABASE_NAME = "new_database_name";
// String URI = "new_URI";
// Declare variables to hold database User Name and Password values
String DB_USER_NAME = username;
String DB_PASSWORD = password;
// Obtain collection of tables from this database controller
if (subreportName == null || subreportName.equals (""))
{
Tables tables = clientDoc.getDatabaseController ().getDatabase ().getTables ();
for (int i = 0; i < tables.size (); i++)
{
origTable = tables.getTable (i);
if (tableName == null || origTable.getName ().equals (tableName))
{
newTable = (ITable) origTable.clone (true);
// We set the Fully qualified name to the Table Alias to keep the
// method generic
// This workflow may not work in all scenarios and should likely be
// customized to work
// in the developer's specific situation. The end result of this
// statement will be to strip
// the existing table of it's db specific identifiers. For example
// Xtreme.dbo.Customer becomes just Customer
// newTable.setQualifiedName (origTable.getAlias ());
// Change properties that are different from the original datasource
// For example, if the table name has changed you will be required
// to change it during this routine
// table.setQualifiedName(TABLE_NAME_QUALIFIER);
// Change connection information properties
connectionInfo = newTable.getConnectionInfo ();
// Set new table connection property attributes
propertyBag = new PropertyBag ();
// Overwrite any existing properties with updated values
propertyBag.put ("Trusted_Connection", TRUSTED_CONNECTION);
propertyBag.put ("Server Type", SERVER_TYPE);
propertyBag.put ("Use JDBC", USE_JDBC);
propertyBag.put ("Database DLL", DATABASE_DLL);
// propertyBag.put ("JNDIOptionalName", JNDI_OPTIONAL_NAME);
propertyBag.put ("Connection URL", CONNECTION_URL);
propertyBag.put ("Database Class Name", DATABASE_CLASS_NAME);
// propertyBag.put("Server Name", SERVER_NAME); //Optional property
// propertyBag.put("Connection String", CONNECTION_STRING); //Optional property
// propertyBag.put("Database Name", DATABASE_NAME); //Optional property
// propertyBag.put("URI", URI); //Optional property
connectionInfo.setAttributes (propertyBag);
// Set database username and password
// NOTE: Even if the username and password properties do not change
// when switching databases, the
// database password is *not* saved in the report and must be set at
// runtime if the database is secured.
connectionInfo.setUserName (DB_USER_NAME);
connectionInfo.setPassword (DB_PASSWORD);
// Update the table information
clientDoc.getDatabaseController ().setTableLocation (origTable, newTable);
// connectionInfo.setKind(ConnectionInfoKind.DBFile);
//
// int replaceParams = DBOptions._ignoreCurrentTableQualifiers + DBOptions._doNotVerifyDB;
// // Now replace the connections
// clientDoc.getDatabaseController().replaceConnection(connectionInfo, connectionInfo, null, replaceParams);
}
}
}
// Next loop through all the subreports and pass in the same
// information. You may consider
// creating a separate method which accepts
if (subreportName == null || !(subreportName.equals ("")))
{
IStrings subNames = clientDoc.getSubreportController ().getSubreportNames ();
for (int subNum = 0; subNum < subNames.size (); subNum++)
{
Tables tables = clientDoc.getSubreportController ().getSubreport (subNames.getString (subNum)).getDatabaseController ().getDatabase ().getTables ();
for (int i = 0; i < tables.size (); i++)
{
origTable = tables.getTable (i);
if (tableName == null || origTable.getName ().equals (tableName))
{
newTable = (ITable) origTable.clone (true);
// We set the Fully qualified name to the Table Alias to keep
// the method generic
// This workflow may not work in all scenarios and should likely
// be customized to work
// in the developer's specific situation. The end result of this
// statement will be to strip
// the existing table of it's db specific identifiers. For
// example Xtreme.dbo.Customer becomes just Customer
// newTable.setQualifiedName (origTable.getAlias ());
// Change properties that are different from the original
// datasource
// table.setQualifiedName(TABLE_NAME_QUALIFIER);
// Change connection information properties
connectionInfo = newTable.getConnectionInfo ();
// Set new table connection property attributes
propertyBag = new PropertyBag ();
// Overwrite any existing properties with updated values
propertyBag.put ("Trusted_Connection", TRUSTED_CONNECTION);
propertyBag.put ("Server Type", SERVER_TYPE);
propertyBag.put ("Use JDBC", USE_JDBC);
propertyBag.put ("Database DLL", DATABASE_DLL);
// propertyBag.put ("JNDIOptionalName", JNDI_OPTIONAL_NAME);
propertyBag.put ("Connection URL", CONNECTION_URL);
propertyBag.put ("Database Class Name", DATABASE_CLASS_NAME);
// propertyBag.put("Server Name", SERVER_NAME); //Optional property
// propertyBag.put("Connection String", CONNECTION_STRING); //Optionalproperty
// propertyBag.put("Database Name", DATABASE_NAME); //Optional property
// propertyBag.put("URI", URI); //Optional property
connectionInfo.setAttributes (propertyBag);
// Set database username and password
// NOTE: Even if the username and password properties do not
// change when switching databases, the
// database password is *not* saved in the report and must be
// set at runtime if the database is secured.
connectionInfo.setUserName (DB_USER_NAME);
connectionInfo.setPassword (DB_PASSWORD);
// Update the table information
clientDoc.getSubreportController ().getSubreport (subNames.getString (subNum)).getDatabaseController ().setTableLocation (origTable, newTable);
}
}
}
}
}
Questo è quanto. Tra le librerie previste da Crystal report è presente la log4j che in fase di runtime esegue il log e attraverso la console vedo l'esecuzione rallentare e ferimarsi per qualche istante quando deve connettersi al db. Spero qualcuno abbia già provato a lavorare su questi argomenti o comunque spero qualcuno mi possa dare una mano, perchè oggettivamente 18 secondi per esportare un file mi sembrano un pò troppi.
Grazie in anticipo per l'aiuto.