RISOLTO Come aprire e leggere velocemente informazioni da database tramite Java

Stato
Discussione chiusa ad ulteriori risposte.

Scripta14

Nuovo Utente
95
8
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.
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.
 

BAT

Moderatore
Staff Forum
Utente Èlite
22,448
11,351
CPU
1-Neurone
Dissipatore
Ventaglio
RAM
Scarsa
Net
Segnali di fumo
OS
Windows 10000 BUG
Premetto che che sono un bel po' di anni che non lavoro con i database in Java, quindi non sono aggiornato sugli "ultimi sviluppi";
però da quanto mi risulta (e che difficilmente penso che sia cambiato), le prestazioni pure del database non dipendono da Java in sé per sé, quanto dal database stesso. In altri termini: se usi un server di database Oracle ritengo fuori dubbio che sia molto più effiente di qualsiasi versione di Access. Per quanto riguarda l'interscambio dei dati tra applicazione Java e database, il massimo delle prestazioni (ai miei tempi...) si otteneva mediante connessione via driver (fornito dal produttore di database, che deve essere il più efficiente possibile).
Per quanto riguarda il lato Java, sempre che io ricordi, ci sono un paio di modi per velocizzare l'accesso ed il reperimento ai dati del database:
  • mantenere aperta la connessione con il database (evitando di chiuderla alla fine di una query) quando si prevede che l'applicazione debba eseguire molte query. Basta inizializzare la connessione (o le connessioni in caso di diversi database) una sola volta all'inizio dell'applicazione. La/le connessione/i devono rimanere aperte fintantoché gira l'applicazione, devono essere chiuse solo alla fine;
  • usare i PreparedStatement (in parole povere istruzioni SQL già compilate); inizialmente può sembrare macchinoso, però ci si guadagna perché il dialogo col database avviene ad un livello più basso (saltando la fase dell'interpretazione della query da parte del DB) e, se le query da eseguire sono fondamentalmente sempre le stesse, fa risparmiare risorse perché vengono mantenute in cache. Per una introduzione rapida e/o per info migliori delle mie dai un'occhiata qui: https://www.pcprofessionale.it/review/java-sfruttarlo-al-meglio-le-prepared-statements/, per miglioramenti affidati alla documentazione Oracle o (meglio) ad un testo specialistico sull'interazione tra Java e i DB.
Immagino che tu sappia già tutte queste cose, in tal caso scusami se ti ho fatto perdere tempo.
 
Ultima modifica:

Scripta14

Nuovo Utente
95
8
Innanzitutto ti ringrazio della risposta e di avermi dedicato del tempo. Nella disperazione ho provato a rilevare i tempi in ogni punto dove vengono esegue le varie operazioni(un pò empirico come sistema, ma funzionale). Rilevo proprio un rallentamento nel codice che si occupa del setDataConnection di Crystal Report. Quindi a questo punto mi viene da pensare che sia qualcosa legato alle classi e metodi di CR. Siccome non ho mai sviluppato integrazioni con CR non mi aspettavo una così tale lentezza. La vecchia versione è un fulmine ed era stata sviluppata con componenti Activex. Un esempio di un banale report esportato in pdf che prende i dati da Access ci impiega fino a 18/20 secondi, mentre con l'attuale versione in ActiveX è immediato.
Dai test che ho fatto ci impiega sempre lo stesso tempo nell'eseguire l'export. circa un paio di secondi per leggere alcune informazioni che verranno utilizzate per aprire il report. Dopo l'apertura rimane bloccato per circa 7/8 secondi e conclude impostazione dei parametri e export in un secondo.
Con oracle va un pò meglio e conclude in circa 6 secondi.Ovviamente dipende dalla quantità di informazioni che deve esportare il report.
Grazie ancora e spero che altri prima di me hanno affrontato questi argomenti e mi possano dare qualche suggerimento, perchè in questo momento di meglio non credo fare.:muro::muro:
Post unito automaticamente:

2019-03-04 11:46:11 DEBUG com.crystaldecisions.reports.common.commandmanager command SETUP: NotUndoableCommand
2019-03-04 11:46:11 DEBUG com.crystaldecisions.reports.common.commandmanager command PERFORM: NotUndoableCommand
2019-03-04 11:46:11 DEBUG com.crystaldecisions.reports.common.commandmanager -- command is NOT UNDOABLE -> purge undo stack
2019-03-04 11:46:11 DEBUG com.crystaldecisions.reports.common.commandmanager --- Purging command SetReportDateCommand
2019-03-04 11:46:11 DEBUG com.crystaldecisions.reports.common.commandmanager --- Purging command SetReportDateCommand
2019-03-04 11:46:11 DEBUG com.crystaldecisions.reports.common.commandmanager --- Purging command SetSummaryInfoCommand
2019-03-04 11:46:11 DEBUG com.healthmarketscience.jackcess.impl.DatabaseImpl Finished reading system catalog. Tables: [Tabelle DB Access] (Db=NomeDb.mdb)
2019-03-04 11:46:18 INFO com.businessobjects.reports.sdk.JRCCommunicationAdapter received request: fetchSubreportNames
2019-03-04 11:46:18 DEBUG com.crystaldecisions.reports.common.commandmanager command SETUP: NotUndoableCommand
2019-03-04 11:46:18 DEBUG com.crystaldecisions.reports.common.commandmanager command PERFORM: NotUndoableCommand
2019-03-04 11:46:18 DEBUG com.crystaldecisions.reports.common.commandmanager -- command is NOT UNDOABLE -> purge undo stack
2019-03-04 11:46:18 INFO com.businessobjects.reports.sdk.JRCCommunicationAdapter received request: addTableRequest

Mi sto analizzando i log e come si può vedere c'è quel salto di 7 secondi. Avete qualche suggerimento a proposito?
Grazie a tutti.
 
Ultima modifica:

Andretti60

Utente Èlite
6,440
5,091
pubblica il codice che corrisponde al salto di sette secondi.

Mi spiace ma non sono un esperto di CR, non sono io che lo ho integrato nel nostro software, ma ho spesso sentito smadonnamenti in uffcio :)
Se fai una ricerca in rete ti accorgerai quanta gente si lamenta using JRC.
 

Scripta14

Nuovo Utente
95
8
Ciao, grazie ecco il codice:
Codice:
    /**
     * 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 {
                    Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
                    dbcon = DriverManager.getConnection (connURL,username,null);
                    if(dbcon.isValid(10)) 
                      System.out.println("connessione ancora aperta");
                  else 
                      System.out.println("connessione chiusa");
                
             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 (ClassNotFoundException e) 
            {
                Utility.updateTableCmd("8", e.getMessage(), id_richiesta, dbodbc, nomeTabella);
            } 
            catch (SQLException e) 
            {
                    Utility.updateTableCmd(String.valueOf(e.getErrorCode()), e.getMessage(), id_richiesta, dbodbc, nomeTabella);
            } 
            catch (ReportSDKException e) 
            {
                    Utility.updateTableCmd(String.valueOf(e.errorCode()), e.getMessage(), id_richiesta, dbodbc, nomeTabella);
            }
    }

/**
     * Changes the DataSource for each Table
     * @param clientDoc The reportClientDocument representing the report being used
     * @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 username, String password,
                                         String connectionURL, String driverName, String jndiName)
            throws ReportSDKException
    {

        changeDataSource (clientDoc, null, null, username, password, connectionURL, driverName, jndiName);
    }

    /**
     * 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 è il codice per Access. Ovviamente se riuscissi a trovare una soluzione per migliorare le performance, poi la replicherò anche su Oracle.

Ancora Grazie.
 

Scripta14

Nuovo Utente
95
8
Finalmente ho trovato una soluzione funzionale per il mio problema. Effettivamente è semplice, ma non l'avevo presa in considerazione, fintantoché non ho fatto alcune prove con CR Designer è ho capito come avrei potuto migliorare le performance.
Rispetto al codice riportato precedentemente ho aggiunto il metodo save(). Siccome CR per ambiente java utilizza la connessione JDBC, e deve modificare i dati della connessione del report con JDBC. (Esempio Access utilizza come SERVER TYPE ODBC), Ho fatto in modo di modificare la connessione solo una volta e le volte successiva utilizzare il report con già le modifiche al suo interno.
Adesso l'applicazione esporta un pdf in 2/2,5 secondi.


Codice:
.....(codice)

                    // Update the table information
                    clientDoc.getDatabaseController ().setTableLocation (origTable, newTable);

                   
                }
            }
        }
        clientDoc.save();
        
........(codice )

                        // Update the table information
                        clientDoc.getSubreportController ().getSubreport (subNames.getString (subNum)).getDatabaseController ().setTableLocation (origTable, newTable);
                    }
                }
            }
            clientDoc.save();
        }
        return clientDoc;
    }
 
  • Mi piace
Reazioni: Mursey
Stato
Discussione chiusa ad ulteriori risposte.

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!