CallableStatement
O JDBC possui outra interface para cenários ainda mais complexos. Ele herda de PreparedStatement e é chamado CallableStatement .
É usado para chamar (Call) stored procedures no banco de dados. A peculiaridade de tal chamada é que, além do ResultSet result , os parâmetros também podem ser passados para tal procedimento armazenado.
O que há de novo, você pergunta? PreparedStatement também tem um resultado ResultSet e você também pode passar parâmetros para ele. Sim, isso mesmo, mas a peculiaridade dos stored procedures é que através de parâmetros eles podem não só receber, mas também retornar dados.
O procedimento armazenado é chamado com os parâmetros IN , OUT e INOUT . Ele retorna um ou mais objetos ResultSet . O método Connection.prepareCall() é usado para criar um objeto CallableStatement .
Aqui imagine que você tem um procedimento armazenado ADD que aceita os parâmetros a, b e c. Este procedimento adiciona a e b e coloca o resultado da adição na variável c.
Vamos escrever o código onde vamos tentar chamá-lo:
// Connect to the server
Connection connection = DriverManager.getConnection("jdbc:as400://mySystem");
// Create a CallableStatement object. It does preprocessing
// calling a stored procedure. Question marks
// indicate where the input parameters should be substituted, and where the output ones
// The first two parameters are input,
// and the third one is a day off.
CallableStatement statement = connection.prepareCall("CALL MYLIBRARY.ADD (?, ?, ?)");
// Setting up input parameters. Passing 123 and 234 to the procedure
statement.setInt (1, 123);
statement.setInt (2, 234);
// Registering the output parameter type
statement.registerOutParameter (3, Types.INTEGER);
// Run stored procedure
statement.execute();
// Get the value of the output parameter
int sum = statement.getInt(3);
// Close CallableStatement and Connection
statement.close();
connection.close();
O trabalho é quase como com PreparedStatement , só que há uma nuance. Nossa função ADD retorna o resultado da adição no terceiro parâmetro. Somente o objeto CallableStatement não sabe nada sobre isso. Portanto, dizemos isso explicitamente chamando o método registerOutParameter() :
registerOutParameter(parameter number, Parameter type)
Depois disso, você pode chamar o procedimento por meio do método execute() e, em seguida, ler os dados do terceiro parâmetro usando o método getInt() .
Solicitações em lote
Em projetos reais, muitas vezes surge uma situação em que você precisa fazer muitas consultas do mesmo tipo (a mais comum neste caso é PreparedStatement ), por exemplo, você precisa inserir várias dezenas ou centenas de registros.
Se você executar cada solicitação separadamente, levará muito tempo e reduzirá o desempenho do aplicativo. Para evitar isso, você pode usar o modo de inserção de lote. Está no fato de você acumular algum buffer com suas solicitações e executá-las imediatamente.
Aqui está um pedaço de código como exemplo:
PreparedStatement stmt = con.prepareStatement(
"INSERT INTO jc_contact (first_name, last_name, phone, email) VALUES (?, ?, ?, ?)");
for (int i = 0; i < 10; i++) {
// Fill in the request parameters
stmt.setString(1, "FirstName_" + i);
stmt.setString(2, "LastNAme_" + i);
stmt.setString(3, "phone_" + i);
stmt.setString(4, "email_" + i);
// The request is not executed, but fits into the buffer,
// which is then executed immediately for all commands
stmt.addBatch();
}
// Execute all requests at once
int[] results = stmt.executeBatch();
Em vez de executar a consulta com o método execute() , nós a agrupamos com o método addBatch() .
E então, quando houver várias centenas de solicitações, você poderá enviá-las todas de uma vez para o servidor chamando o comando executeBatch() .
Saudável. O método executeBatch() retorna um array de inteiros — int[]. Cada célula nesta matriz contém um número que indica o número de linhas modificadas pela consulta correspondente. Se a solicitação número 3 no lote mudou 5 linhas, a 3ª célula da matriz conterá o número 5.