2012-05-29 24 views
70

Ciao Mi chiedevo se è possibile eseguire qualcosa di simile utilizzando JDBC in quanto attualmente fornisce un'eccezione anche se è possibile nel browser query MySQL.più query eseguite in java in un'unica istruzione

"SELECT FROM * TABLE;INSERT INTO TABLE;" 

Mentre mi rendo conto che è possibile avere con la stringa di query SQL di essere diviso e l'istruzione eseguita due volte, ma mi chiedevo se v'è un approccio un tempo per questo.

String url = "jdbc:mysql://localhost:3306/"; 
    String dbName = "databaseinjection"; 
    String driver = "com.mysql.jdbc.Driver"; 
    String sqlUsername = "root"; 
    String sqlPassword = "abc"; 

    Class.forName(driver).newInstance(); 

    connection = DriverManager.getConnection(url+dbName, sqlUsername, sqlPassword); 
+1

messo in una stored procedure, chiamare la stored procedure. significa che non devi ridistribuire il tuo codice quando vuoi apportare una modifica. – Chris

+3

C'è una proprietà che devi impostare nella stringa di connessione 'allowMultiQueries = true'. – Rahul

+0

duplicato probabile: come eseguire query sql composite in java? [1] [1]: http://stackoverflow.com/questions/6773393/how-to-execute-composite-sql-queries-in-java – prayagupd

risposta

100

Mi chiedevo se è possibile eseguire qualcosa di simile utilizzando JDBC.

"SELECT FROM * TABLE;INSERT INTO TABLE;" 

Sì, è possibile. Ci sono due modi, per quanto ne so. Sono

  1. impostando la proprietà di connessione al database per consentire query multiple, separate da un punto e virgola per impostazione predefinita.
  2. Chiamando una stored procedure che restituisce i cursori impliciti.

esempi seguenti dimostrano due possibilità precedenti.

Esempio 1: (Per consentire più query):

Durante l'invio di una richiesta di connessione, è necessario aggiungere una proprietà di connessione allowMultiQueries=true all'url database. Questa è una proprietà di connessione aggiuntiva a quelli se ne esiste già, come autoReConnect=true, ecc. I valori accettabili per la proprietà allowMultiQueries sono true, false, yes e no. Qualsiasi altro valore viene rifiutato in fase di esecuzione con un SQLException.

String dbUrl = "jdbc:mysql:///test?allowMultiQueries=true"; 

A meno che non si passa ad esempio l'istruzione, un SQLException viene generata.

Devi usare execute(String sql) o le sue altre varianti per andare a prendere i risultati dell'esecuzione della query.

boolean hasMoreResultSets = stmt.execute(multiQuerySqlString); 

per scorrere e il processo di risultati richiesti seguenti operazioni:

READING_QUERY_RESULTS: // label 
    while (hasMoreResultSets || stmt.getUpdateCount() != -1) { 
     if (hasMoreResultSets) { 
      Resultset rs = stmt.getResultSet(); 
      // handle your rs here 
     } // if has rs 
     else { // if ddl/dml/... 
      int queryResult = stmt.getUpdateCount(); 
      if (queryResult == -1) { // no more queries processed 
       break READING_QUERY_RESULTS; 
      } // no more queries processed 
      // handle success, failure, generated keys, etc here 
     } // if ddl/dml/... 

     // check to continue in the loop 
     hasMoreResultSets = stmt.getMoreResults(); 
    } // while results 

Esempio 2: Passi da seguire:

  1. creare una routine con uno o più select, e DML domande.
  2. Chiamalo da java utilizzando CallableStatement.
  3. È possibile catturare più ResultSet s eseguiti nella procedura.
    I risultati DML non possono essere acquisiti, ma è possibile rilasciarne un altro select
    per scoprire in che modo le righe sono interessate nella tabella.

tavolo del campione e la procedura di:

mysql> create table tbl_mq(i int not null auto_increment, name varchar(10), primary key (i)); 
Query OK, 0 rows affected (0.16 sec) 

mysql> delimiter // 
mysql> create procedure multi_query() 
    -> begin 
    -> select count(*) as name_count from tbl_mq; 
    -> insert into tbl_mq(names) values ('ravi'); 
    -> select last_insert_id(); 
    -> select * from tbl_mq; 
    -> end; 
    -> // 
Query OK, 0 rows affected (0.02 sec) 
mysql> delimiter ; 
mysql> call multi_query(); 
+------------+ 
| name_count | 
+------------+ 
|   0 | 
+------------+ 
1 row in set (0.00 sec) 

+------------------+ 
| last_insert_id() | 
+------------------+ 
|    3 | 
+------------------+ 
1 row in set (0.00 sec) 

+---+------+ 
| i | name | 
+---+------+ 
| 1 | ravi | 
+---+------+ 
1 row in set (0.00 sec) 

Query OK, 0 rows affected (0.00 sec) 

Procedure Call da Java:

CallableStatement cstmt = con.prepareCall("call multi_query()"); 
boolean hasMoreResultSets = cstmt.execute(); 
READING_QUERY_RESULTS: 
    while (hasMoreResultSets) { 
     Resultset rs = stmt.getResultSet(); 
     // handle your rs here 
    } // while has more rs 
+0

Sfortunatamente, questo non funziona con la versione integrata di Derby. – user2428118

+0

@ user2428118: motivo? Qualche errore osservato? Hai controllato se il driver supporta questa funzione? –

+0

ho aggiunto allowMultiQueries = true e funziona bene :) – Hazim

0

Perché non provi a scrivere un Stored Procedure per questo?

È possibile ottenere lo Result Set e nello stesso Stored Procedure è possibile Insert quello che vuoi.

L'unica cosa è che si potrebbe non ottenere le nuove righe inserite nel Result Set se Insert dopo la Select.

21

È possibile utilizzare l'aggiornamento batch ma query deve essere azione (cioè. Inserire, aggiornare e cancellare) interroga

Statement s = c.createStatement(); 
String s1 = "update emp set name='abc' where salary=984"; 
String s2 = "insert into emp values ('Osama',1420)"; 
s.addBatch(s1); 
s.addBatch(s2);  
s.executeBatch(); 
+0

Non è possibile utilizzare questo approccio per le query "call sprocname ('abc', 984)"? – sebnukem

7

Sulla base della mia prova, la bandiera corretta è "allowMultiQueries = true"

12

Suggerimento: se si dispone di più di una carta Proprietà ction poi separarli con:

& 

Per darvi somthing come:

url="jdbc:mysql://localhost/glyndwr?autoReconnect=true&allowMultiQueries=true" 

Spero che questo aiuta qualcuno.

saluti,

Glyn

0

credo che questo sia il modo più semplice per multy selezione/aggiornamento/inserimento/cancellazione. Puoi eseguire tanti update/insert/delete come vuoi dopo aver selezionato (devi prima fare una select (un dummy se necessario)) con executeUpdate (str) (usa solo new int (count1, count2, ...)) e se hai bisogno di una nuova selezione chiudi 'istruzione' e 'connessione' e crea una nuova per la prossima selezione. Come ad esempio:

String str1 = "select * from users"; 
String str9 = "INSERT INTO `port`(device_id, potition, port_type, di_p_pt) VALUE ('"+value1+"', '"+value2+"', '"+value3+"', '"+value4+"')"; 
String str2 = "Select port_id from port where device_id = '"+value1+"' and potition = '"+value2+"' and port_type = '"+value3+"' "; 
try{ 
    Class.forName("com.mysql.jdbc.Driver").newInstance(); 
    theConnection=(Connection) DriverManager.getConnection(dbURL,dbuser,dbpassword); 
    theStatement = theConnection.prepareStatement(str1); 
    ResultSet theResult = theStatement.executeQuery(); 
    int count8 = theStatement.executeUpdate(str9); 
    theStatement.close(); 
    theConnection.close(); 
    theConnection=DriverManager.getConnection(dbURL,dbuser,dbpassword); 
    theStatement = theConnection.prepareStatement(str2); 
    theResult = theStatement.executeQuery(); 

    ArrayList<Port> portList = new ArrayList<Port>(); 
    while (theResult.next()) { 
     Port port = new Port(); 
     port.setPort_id(theResult.getInt("port_id")); 

     portList.add(port); 
    } 

Spero che aiuta

+1

L'apertura di una connessione DB è molto più costosa. Non è una buona pratica farlo ogni volta. Il dato che hai dato dovrebbe fare n numero di accessi al DB per n numero di query che porta a prestazioni scadenti. –

Problemi correlati