CallableStatement in Java wird verwendet, um eine gespeicherte Prozedur aus einem Java-Programm aufzurufen. Gespeicherte Prozeduren sind eine Gruppe von Anweisungen, die wir in der Datenbank für eine bestimmte Aufgabe kompilieren. Gespeicherte Prozeduren sind vorteilhaft, wenn wir es mit mehreren Tabellen und komplexen Szenarien zu tun haben und anstatt mehrere Abfragen an die Datenbank zu senden, können wir die erforderlichen Daten an die gespeicherte Prozedur senden und die Logik im Datenbankserver selbst ausführen lassen.
CallableStatement
Die JDBC-API bietet Unterstützung für die Ausführung von gespeicherten Prozeduren über die Schnittstelle
CallableStatement
. Gespeicherte Prozeduren müssen in der datenbankspezifischen Syntax geschrieben werden, und für mein Tutorial werde ich die Oracle-Datenbank verwenden. Wir werden uns die Standardfunktionen von CallableStatement mit IN- und OUT-Parametern ansehen. Später werden wir uns Oracle-spezifische Beispiele mit STRUCT und Cursor ansehen. Zuerst erstellen wir eine Tabelle für unsere Beispielprogramme mit dem folgenden SQL-Query. create_employee.sql
-- Für Oracle DB
CREATE TABLE EMPLOYEE
(
"EMPID" NUMBER NOT NULL ENABLE,
"NAME" VARCHAR2(10 BYTE) DEFAULT NULL,
"ROLE" VARCHAR2(10 BYTE) DEFAULT NULL,
"CITY" VARCHAR2(10 BYTE) DEFAULT NULL,
"COUNTRY" VARCHAR2(10 BYTE) DEFAULT NULL,
PRIMARY KEY ("EMPID")
);
Lassen Sie uns zunächst eine Hilfsklasse erstellen, um das Oracle-Datenbankverbindungsobjekt zu erhalten. Stellen Sie sicher, dass das Oracle OJDBC-Jar im Build-Pfad des Projekts liegt. DBConnection.java
package com.journaldev.jdbc.storedproc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DBConnection {
private static final String DB_DRIVER_CLASS = "oracle.jdbc.driver.OracleDriver";
private static final String DB_URL = "jdbc:oracle:thin:@localhost:1521:orcl";
private static final String DB_USERNAME = "HR";
private static final String DB_PASSWORD = "oracle";
public static Connection getConnection() {
Connection con = null;
try {
// Laden Sie die Treiberklasse
Class.forName(DB_DRIVER_CLASS);
// Erstellen Sie jetzt die Verbindung
con = DriverManager.getConnection(DB_URL,DB_USERNAME,DB_PASSWORD);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return con;
}
}
Beispiel für CallableStatement
Lassen Sie uns eine einfache gespeicherte Prozedur schreiben, um Daten in die Tabelle „Employee“ einzufügen. insertEmployee.sql
CREATE OR REPLACE PROCEDURE insertEmployee
(in_id IN EMPLOYEE.EMPID%TYPE,
in_name IN EMPLOYEE.NAME%TYPE,
in_role IN EMPLOYEE.ROLE%TYPE,
in_city IN EMPLOYEE.CITY%TYPE,
in_country IN EMPLOYEE.COUNTRY%TYPE,
out_result OUT VARCHAR2)
AS
BEGIN
INSERT INTO EMPLOYEE (EMPID, NAME, ROLE, CITY, COUNTRY)
values (in_id,in_name,in_role,in_city,in_country);
commit;
out_result := 'TRUE';
EXCEPTION
WHEN OTHERS THEN
out_result := 'FALSE';
ROLLBACK;
END;
Wie Sie sehen können, erwartet die „insertEmployee“-Prozedur Eingaben vom Aufrufer, die in die Tabelle „Employee“ eingefügt werden. Wenn die Einfügeanweisung funktioniert, wird TRUE zurückgegeben, andernfalls FALSE im Falle einer Ausnahme. Schauen wir uns an, wie wir CallableStatement
verwenden können, um die gespeicherte Prozedur insertEmployee
auszuführen, um Mitarbeiterdaten einzufügen. JDBCStoredProcedureWrite.java
package com.journaldev.jdbc.storedproc;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Scanner;
public class JDBCStoredProcedureWrite {
public static void main(String[] args) {
Connection con = null;
CallableStatement stmt = null;
// Benutzereingaben lesen
Scanner input = new Scanner(System.in);
System.out.println("Enter Employee ID (int):");
int id = Integer.parseInt(input.nextLine());
System.out.println("Enter Employee Name:");
String name = input.nextLine();
System.out.println("Enter Employee Role:");
String role = input.nextLine();
System.out.println("Enter Employee City:");
String city = input.nextLine();
System.out.println("Enter Employee Country:");
String country = input.nextLine();
try{
con = DBConnection.getConnection();
stmt = con.prepareCall("{call insertEmployee(?,?,?,?,?,?)}");
stmt.setInt(1, id);
stmt.setString(2, name);
stmt.setString(3, role);
stmt.setString(4, city);
stmt.setString(5, country);
// Registrieren Sie den OUT-Parameter, bevor Sie die gespeicherte Prozedur aufrufen
stmt.registerOutParameter(6, java.sql.Types.VARCHAR);
stmt.executeUpdate();
// Lesen Sie jetzt den OUT-Parameter
String result = stmt.getString(6);
System.out.println("Employee Record Save Success::"+result);
}catch(Exception e){
e.printStackTrace();
}finally{
try {
stmt.close();
con.close();
input.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Wir lesen Benutzereingaben, die in der Tabelle Employee gespeichert werden sollen. Das Einzige, was sich von PreparedStatement
unterscheidet, ist die Erstellung eines CallableStatement durch „{call insertEmployee(?,?,?,?,?,?)}
“ und das Setzen des OUT-Parameters mit der Methode CallableStatement registerOutParameter()
. Wir müssen den OUT-Parameter registrieren, bevor wir die gespeicherte Prozedur ausführen. Sobald die gespeicherte Prozedur ausgeführt wurde, können wir die Methode CallableStatement getXXX()
verwenden, um die OUT-Objektdaten abzurufen. Beachten Sie, dass beim Registrieren des OUT-Parameters der Typ des OUT-Parameters über java.sql.Types
angegeben werden muss. Der Code ist allgemein gehalten, sodass wir dieselbe gespeicherte Prozedur auch in anderen relationalen Datenbanken wie MySQL ausführen können. Unten finden Sie die Ausgabe, wenn wir das obige CallableStatement-Beispielprogramm mehrmals ausführen.
Enter Employee ID (int):
1
Enter Employee Name:
Pankaj
Enter Employee Role:
Developer
Enter Employee City:
Bangalore
Enter Employee Country:
India
Employee Record Save Success::TRUE
-----
Enter Employee ID (int):
2
Enter Employee Name:
Pankaj Kumar
Enter Employee Role:
CEO
Enter Employee City:
San Jose
Enter Employee Country:
USA
Employee Record Save Success::FALSE
Beachten Sie, dass die zweite Ausführung fehlgeschlagen ist, weil der übergebene Name größer ist als die Spaltengröße. Wir fangen die Ausnahme in der gespeicherten Prozedur ab und geben in diesem Fall false zurück.
Beispiel für CallableStatement – Gespeicherte Prozedur OUT-Parameter
Jetzt schreiben wir eine gespeicherte Prozedur, um die Mitarbeiterdaten nach ID zu erhalten. Der Benutzer gibt die Mitarbeiter-ID ein, und das Programm zeigt die Mitarbeiterinformationen an. getEmployee.sql
create or replace
PROCEDURE getEmployee
(in_id IN EMPLOYEE.EMPID%TYPE,
out_name OUT EMPLOYEE.NAME%TYPE,
out_role OUT EMPLOYEE.ROLE%TYPE,
out_city OUT EMPLOYEE.CITY%TYPE,
out_country OUT EMPLOYEE.COUNTRY%TYPE
)
AS
BEGIN
SELECT NAME, ROLE, CITY, COUNTRY
INTO out_name, out_role, out_city, out_country
FROM EMPLOYEE
WHERE EMPID = in_id;
END;
Java CallableStatement Beispielprogramm, das die gespeicherte Prozedur getEmployee zum Lesen der Mitarbeiterdaten verwendet; JDBCStoredProcedureRead.java
package com.journaldev.jdbc.storedproc;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Scanner;
public class JDBCStoredProcedureRead {
public static void main(String[] args) {
Connection con = null;
CallableStatement stmt = null;
//Benutzereingaben lesen
Scanner input = new Scanner(System.in);
System.out.println("Enter Employee ID (int):");
int id = Integer.parseInt(input.nextLine());
try{
con = DBConnection.getConnection();
stmt = con.prepareCall("{call getEmployee(?,?,?,?,?)}");
stmt.setInt(1, id);
//Registrieren Sie den OUT-Parameter, bevor Sie die gespeicherte Prozedur aufrufen
stmt.registerOutParameter(2, java.sql.Types.VARCHAR);
stmt.registerOutParameter(3, java.sql.Types.VARCHAR);
stmt.registerOutParameter(4, java.sql.Types.VARCHAR);
stmt.registerOutParameter(5, java.sql.Types.VARCHAR);
stmt.execute();
//Lesen Sie jetzt den OUT-Parameter
String name = stmt.getString(2);
String role = stmt.getString(3);
String city = stmt.getString(4);
String country = stmt.getString(5);
if(name !=null){
System.out.println("Employee Name="+name+",Role="+role+",City="+city+",Country="+country);
}else{
System.out.println("Employee Not Found with ID"+id);
}
}catch(Exception e){
e.printStackTrace();
}finally{
try {
stmt.close();
con.close();
input.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Das Programm ist wieder generisch und funktioniert für jede Datenbank mit derselben gespeicherten Prozedur. Schauen wir uns an, was passiert, wenn wir das obige CallableStatement Beispielprogramm ausführen.
Enter Employee ID (int):
1
Employee Name=Pankaj,Role=Developer,City=Bangalore,Country=India
CallableStatement Beispiel – Gespeicherte Prozedur Oracle CURSOR
Da wir die Mitarbeiterinformationen nach ID lesen, erhalten wir ein einzelnes Ergebnis, und OUT-Parameter funktionieren gut, um die Daten zu lesen. Wenn wir jedoch nach Rolle oder Land suchen, könnten wir mehrere Zeilen erhalten, und in diesem Fall können wir den Oracle CURSOR verwenden, um sie wie ein Resultset zu lesen. getEmployeeByRole.sql
create or replace
PROCEDURE getEmployeeByRole
(in_role IN EMPLOYEE.ROLE%TYPE,
out_cursor_emps OUT SYS_REFCURSOR
)
AS
BEGIN
OPEN out_cursor_emps FOR
SELECT EMPID, NAME, CITY, COUNTRY
FROM EMPLOYEE
WHERE ROLE = in_role;
END;
JDBCStoredProcedureCursor.java
package com.journaldev.jdbc.storedproc;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Scanner;
import oracle.jdbc.OracleTypes;
public class JDBCStoredProcedureCursor {
public static void main(String[] args) {
Connection con = null;
CallableStatement stmt = null;
ResultSet rs = null;
//Benutzereingaben lesen
Scanner input = new Scanner(System.in);
System.out.println("Enter Employee Role:");
String role = input.nextLine();
try{
con = DBConnection.getConnection();
stmt = con.prepareCall("{call getEmployeeByRole(?,?)}");
stmt.setString(1, role);
//Registrieren Sie den OUT-Parameter, bevor Sie die gespeicherte Prozedur aufrufen
stmt.registerOutParameter(2, OracleTypes.CURSOR);
stmt.execute();
//Lesen Sie jetzt den OUT-Parameter
rs = (ResultSet) stmt.getObject(2);
while(rs.next()){
System.out.println("Employee ID="+rs.getInt("empId")+",Name="+rs.getString("name")+
",Role="+role+",City="+rs.getString("city")+
",Country="+rs.getString("country"));
}
}catch(Exception e){
e.printStackTrace();
}finally{
try {
rs.close();
stmt.close();
con.close();
input.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Dieses Programm verwendet Oracle-spezifische Klassen von OJDBC und funktioniert nicht mit anderen Datenbanken. Wir setzen den OUT-Parameter-Typ als OracleTypes.CURSOR
und casten ihn dann in ein ResultSet
-Objekt um. Der andere Teil des Codes ist einfache JDBC-Programmierung. Wenn wir das obige CallableStatement-Beispielprogramm ausführen, erhalten wir die folgende Ausgabe.
Enter Employee Role:
Developer
Employee ID=5,Name=Kumar,Role=Developer,City=San Jose,Country=USA
Employee ID=1,Name=Pankaj,Role=Developer,City=Bangalore,Country=India
Ihre Ausgabe kann je nach Daten in Ihrer Mitarbeiter-Tabelle variieren.
CallableStatement-Beispiel – Oracle-DB-Objekt und STRUCT
Wenn Sie sich die gespeicherten Prozeduren insertEmployee
und getEmployee
ansehen, habe ich alle Parameter der Mitarbeiter-Tabelle in der Prozedur. Wenn die Anzahl der Spalten wächst, kann dies zu Verwirrung und mehr Fehlern führen. Die Oracle-Datenbank bietet die Möglichkeit, Datenbankobjekte zu erstellen, und wir können Oracle STRUCT verwenden, um mit ihnen zu arbeiten. Lassen Sie uns zuerst das Oracle-DB-Objekt für die Spalten der Mitarbeiter-Tabelle definieren. EMPLOYEE_OBJ.sql
create or replace TYPE EMPLOYEE_OBJ AS OBJECT
(
EMPID NUMBER,
NAME VARCHAR2(10),
ROLE VARCHAR2(10),
CITY VARCHAR2(10),
COUNTRY VARCHAR2(10)
);
Jetzt wollen wir die gespeicherte Prozedur insertEmployee mit EMPLOYEE_OBJ neu schreiben. insertEmployeeObject.sql
CREATE OR REPLACE PROCEDURE insertEmployeeObject
(IN_EMPLOYEE_OBJ IN EMPLOYEE_OBJ,
out_result OUT VARCHAR2)
AS
BEGIN
INSERT INTO EMPLOYEE (EMPID, NAME, ROLE, CITY, COUNTRY) values
(IN_EMPLOYEE_OBJ.EMPID, IN_EMPLOYEE_OBJ.NAME, IN_EMPLOYEE_OBJ.ROLE, IN_EMPLOYEE_OBJ.CITY, IN_EMPLOYEE_OBJ.COUNTRY);
commit;
out_result := 'TRUE';
EXCEPTION
WHEN OTHERS THEN
out_result := 'FALSE';
ROLLBACK;
END;
Lassen Sie uns sehen, wie wir die gespeicherte Prozedur insertEmployeeObject
im Java-Programm aufrufen können. JDBCStoredProcedureOracleStruct.java
package com.journaldev.jdbc.storedproc;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Scanner;
import oracle.jdbc.OracleCallableStatement;
import oracle.sql.STRUCT;
import oracle.sql.StructDescriptor;
public class JDBCStoredProcedureOracleStruct {
public static void main(String[] args) {
Connection con = null;
OracleCallableStatement stmt = null;
//Erstellen Sie ein Objektarray für den Aufruf einer gespeicherten Prozedur
Object[] empObjArray = new Object[5];
//Benutzereingaben lesen
Scanner input = new Scanner(System.in);
System.out.println("Enter Employee ID (int):");
empObjArray[0] = Integer.parseInt(input.nextLine());
System.out.println("Enter Employee Name:");
empObjArray[1] = input.nextLine();
System.out.println("Enter Employee Role:");
empObjArray[2] = input.nextLine();
System.out.println("Enter Employee City:");
empObjArray[3] = input.nextLine();
System.out.println("Enter Employee Country:");
empObjArray[4] = input.nextLine();
try{
con = DBConnection.getConnection();
StructDescriptor empStructDesc = StructDescriptor.createDescriptor("EMPLOYEE_OBJ", con);
STRUCT empStruct = new STRUCT(empStructDesc, con, empObjArray);
stmt = (OracleCallableStatement) con.prepareCall("{call insertEmployeeObject(?,?)}");
stmt.setSTRUCT(1, empStruct);
//Melden Sie den OUT-Parameter vor dem Aufrufen der gespeicherten Prozedur
stmt.registerOutParameter(2, java.sql.Types.VARCHAR);
stmt.executeUpdate();
//Lesen Sie jetzt den OUT-Parameter
String result = stmt.getString(2);
System.out.println("Employee Record Save Success::"+result);
}catch(Exception e){
e.printStackTrace();
}finally{
try {
stmt.close();
con.close();
input.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Zunächst erstellen wir ein Objektarray mit derselben Länge wie das Datenbankobjekt EMPLOYEE_OBJ. Dann setzen wir Werte entsprechend den Variablen des EMPLOYEE_OBJ-Objekts. Das ist sehr wichtig, da sonst die Daten in falsche Spalten eingefügt werden. Dann erstellen wir ein oracle.sql.STRUCT
-Objekt mit Hilfe von oracle.sql.StructDescriptor
und unserem Objektarray. Sobald das STRUCT-Objekt erstellt ist, setzen wir es als IN-Parameter für die gespeicherte Prozedur, melden den OUT-Parameter und führen sie aus. Dieser Code ist eng mit der OJDBC-API verbunden und funktioniert nicht für andere Datenbanken. Hier ist die Ausgabe, wenn wir dieses Programm ausführen.
Enter Employee ID (int):
5
Enter Employee Name:
Kumar
Enter Employee Role:
Developer
Enter Employee City:
San Jose
Enter Employee Country:
USA
Employee Record Save Success::TRUE
Wir können das Datenbankobjekt auch als OUT-Parameter verwenden und es lesen, um die Werte aus der Datenbank zu erhalten. Das ist alles für CallableStatement im Java-Beispiel zur Ausführung von gespeicherten Prozeduren, ich hoffe, Sie haben etwas daraus gelernt.
Source:
https://www.digitalocean.com/community/tutorials/callablestatement-in-java-example