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.