Can Java batch calls to SQL stored procedures? - java

Java: Insert multiple rows into MySQL with PreparedStatement covers batching multiple INSERTs into one operation. I wondered if it is possible to do the same with calls to stored procedures, more specifically with MySQL? If so, what statement class would be used?

If you have your stored procedure like this:
JDBC CallableStatement Stored procedure IN parameter example.
CREATE OR REPLACE PROCEDURE insertEMPLOYEE(
e_id IN EMPLOYEE.EMPLOYEE_ID%TYPE,
e_name IN EMPLOYEE.NAME%TYPE,
e_salary IN EMPLOYEE.SALARY%TYPE)
IS
BEGIN
INSERT INTO EMPLOYEE ("EMPLOYEE_ID", "NAME", "SALARY")
VALUES (e_id, e_name, e_salary);
COMMIT;
END;
You can just use executeBatch() to do as you intend.
Example:
Connection conn = null;
CallableStatement callableStatement = null;
String proc = "{call insertEMPLOYEE(?,?,?)}";
try{
//get connection
conn = JDBCUtil.getConnection();
//create callableStatement
callableStatement = conn.prepareCall(proc);
callableStatement.setInt(1, 7);
callableStatement.setString(2, "Harish Yadav");
callableStatement.setInt(3, 50000);
callableStatement.addBatch();
callableStatement.setInt(1, 8);
callableStatement.setString(2, "Abhishek Rathor");
callableStatement.setInt(3, 50000);
callableStatement.addBatch();
//execute query
callableStatement.executeBatch();
//close connection
callableStatement.close();
conn.close();
System.out.println("Records inserted successfully.");
}catch(Exception e){
e.printStackTrace();
}

You can use executeBatch(). See this example
Note: I haven't validated example by running in my local, but as per documentation it should work.

Related

Correct way of calling reference cursors in PostgreSQL 11 and above using JDBC driver

I need some suggestion on how to get the data through PostgreSQL JDBC driver from stored procedures using reference cursors.
Since PostgreSQL 11, it supports stored procedures with create procedure command instead of create function.
I have a scenario in which I want to fetch data from a stored procedure using a reference cursor.
My stored procedure SQL looks like as shown below
CREATE OR REPLACE PROCEDURE public.pr_sampleuser(
p_firstuser character varying,
INOUT p_qusers refcursor)
LANGUAGE 'plpgsql'
AS $BODY$
BEGIN
OPEN p_qusers FOR
SELECT first_name,last_name,address
FROM public.test_user
WHERE UPPER(first_name) = UPPER(p_firstuser);
END;
$BODY$;
When we want to fetch the data using the JDBC driver, the first thing we need to add to the connection string is escapeSyntaxCallMode=call.
Following is the code-snippet that I am using to fetch the data,
try {
Properties props = new Properties();
props.setProperty("escapeSyntaxCallMode", "call");
Connection conn = DriverManager.getConnection(url,props);
String storedProc = "{call public.pr_sampleuser(?,?)}";
CallableStatement cs = conn.prepareCall(storedProc);
cs.setString(1,"Umesh");
cs.setObject(2,null);
cs.registerOutParameter(2,Types.REF_CURSOR);
conn.setAutoCommit(false);
// run StoredProcedure
cs.execute();
// get refcursor and convert it to ResultSet
ResultSet resultSet = (ResultSet) cs.getObject(2);
while (resultSet.next()) {
String firstName = resultSet.getString("first_name");
String lastname = resultSet.getString("last_name");
String address = resultSet.getString("address");
System.out.println(firstName);
System.out.println(lastname);
System.out.println(address);
}
} catch (SQLException e) {
System.err.format("SQL State: %s\n%s", e.getSQLState(), e.getMessage());
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
In this I am passing the second parameter as null using
cs.setObject(2,null);
I wanted to check if this is the correct way to fetch or if there is any better way to get the data.

Calling PL/SQL package code in a Java Program

I am trying to call a procedure defined with a PL/SQL package in a Java program.
I am aware one can call stored procedures using connection.prepareCall in Jdbc. But there is very little information out there on how to call a procedure within a package.
I am at a stage in development where i am still considering what db framework to use. Just wondering what are the pros and cons of using JDBC for PLSQL ? For this usecase are there better alternatives to JDBC ?
Follow the simple steps below:
public static final String SOME_NAME = "{call schema_name.org_name_pkg.return_something(?,?)}"; // Change the schema name,packagename,and procedure name.
// Simple JDBC Connection Pooling
// Here I am passing param companyId which is IN param to stored procedure which will return me some value.
Connection conn = null;
CallableStatement stmt = null;
ResultSet rset = null;
try {
conn = DriverManager.getConnection("jdbc:mysql://hostname:port/dbname","username", "password");
stmt = conn.prepareCall(SOME_NAME);//We have declared this at the very top
stmt.setString(1, companyid);//Passing CompanyID here
stmt.registerOutParameter(2, OracleTypes.CURSOR);//Refcursor selects the row based upon query results provided in Package.
stmt.execute();
rset = (ResultSet) stmt.getObject(2);
while (rset.next()) {
String orgId=rset.getString("RPT_ORG_ID");
// When using refcursor easy to get the value just by using Column name
String orgName=rset.getString("RPT_ORG_NAME");
// Some Logic based what do you want to do with the data returned back from query
} catch (Exception e) {
LOGGER.error("Error extracting ", e);
} finally {
DBUtils.cleanUp(conn, stmt, rset);
}
// Clean and close you connection

How to insert two strings into my Access database from Java using UCanAccess?

I am trying to add two strings on two separate columns columns of my database using Java but I'm not sure what I am doing wrong. The code I am using
try{
Connection conn = DriverManager.getConnection(
"jdbc:ucanaccess://C:/Users/nevik/Desktop/databaseJava/Employee.accdb");
Statement st = conn.createStatement();
String sql = "Select * from Table2";
ResultSet rs = st.executeQuery(sql);
rs.updateString("user", user);
rs.updateString("pass", pass);
rs.updateRow();
}
catch(SQLException ex){
System.err.println("Error: "+ ex);
}
The first column on my database is user and the next one is pass. I am using UCanAccess in order to access my database.
This is how you normally update a row in java:
String query = "update Table2 set user = ?, pass= ?";
PreparedStatement preparedStmt = conn.prepareStatement(query);
preparedStmt.setInt (1, user);
preparedStmt.setString(2, pass);
// execute the java preparedstatement
preparedStmt.executeUpdate();
First of, you've not updated the position of the current cursor in the ResultSet, which means that it's pointing to nothing...
You could use...
if (rs.next()) {
rs.updateString("user", user);
rs.updateString("pass", pass);
rs.updateRow();
}
But this assumes two things...
You have a database that supports updating values in the ResultSet and
You want to update the existing values.
To insert a value into the database, you should be using the INSERT command, for example...
try(Connection conn = DriverManager.getConnection(
"jdbc:ucanaccess://C:/Users/nevik/Desktop/databaseJava/Employee.accdb")) {
try (PreparedStatement stmt = conn.prepareStatement("INSERT into Table2 (user, pass) VALUES (?, ?)") {
stmt.setString(1, user);
stmt.setString(2, pass);
int rowsUpdated = stmt.executeUpdate();
}
}
catch(SQLException ex){
System.err.println("Error: "+ ex);
}
You might like to take some time to go over a basic SQL tutorial and the JDBC(TM) Database Access trail
As a side note...
You should not be storing passwords in Strings, you should keep them in char arrays and
You should not be storing passwords in the database without encrypting them in some way
#guevarak12
About the original question (how to use updatable ResultSet):
your code is wrong, you have to move the cursor in the right position.
In particular, if you are inserting a new row you have to call rs.moveToInsertRow(); before rs.updateString("user", user).
If you are updating an existent row, you have to move the cursor calling rs.next() and so reach the row to update.
Also you have to create the Statement in a different way:
Statement st =conn.createStatement( ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
See junit examples in the UCanAccess source distribution, class net.ucanaccess.test.CrudTest.
All other comments seem to be correct.

Getting a result back from a stored procedure in Java

I am having the hardest time calling an Oracle stored procedure from a java runtime environment. The stored procedure that I am calling has 2 parameters 1 in and 1 out. Here is how I call the stored procedure... How do you get the resultSet from an Oracle ref_cursor
ds = (DataSource)initialContext.lookup("JDBC/EPCD13DB");
conn = ds.getConnection();
callableStatement = conn.prepareCall(storedProcCall);
callableStatement.setString(1, input1);
callableStatement.registerOutParameter(2, OracleTypes.CURSOR);
callableStatement.execute();//(ResultSet) callableStatement.getObject(1);
ResultSet rs = callableStatement.getResultSet();
while(rs.next()){
Provider tempProv = new Provider();
tempProv.setResourceId(rs.getLong("res_id"));
tempProv.setFirstName(rs.getString("First_Name"));
tempProv.setLastName(rs.getString("Last_Name"));
tempProv.setMiddleName(rs.getString("Middle_Name"));
ObjList.add(tempProv);
}
rs.close();
You should be able to retrieve the ResultSet with:
ResultSet rSet = (ResultSet)callableStatement.getObject(2);
Does this help you? Seems like you have to call getObject and cast it into a result set before querying on the result set.
Credit:: http://www.mkyong.com/jdbc/jdbc-callablestatement-stored-procedure-cursor-example/
I believe it returns only one output(oracle cursor)
ResultSet rs=(ResultSet) callableStatement.getObject(2);
and then iterate your cursor result set for records inside:
while(rs.next()){
Provider tempProv = new Provider();
tempProv.setResourceId(rs.getLong("res_id"));
tempProv.setFirstName(rs.getString("First_Name"));
tempProv.setLastName(rs.getString("Last_Name"));
tempProv.setMiddleName(rs.getString("Middle_Name"));
ObjList.add(tempProv);
}
In spring framework fetching database cursor results can be easily achieved. It has inbuilt classes like maprow, storedprocedure to serve the purpose. PFB the link
http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/jdbc.html#jdbc-simple-jdbc-call-1

How to pass userdefined table type to MSSQL request from Java

Given a simple stored procedure which has a table with a single column of integers as argument:
CREATE PROCEDURE [dbo].[table_sel]
#tbl INT32Table READONLY
AS
BEGIN
SET NOCOUNT ON;
SELECT value FROM #tbl
END
How do I execute this stored procedure from Java? From C# this does what I want:
SqlConnection sqlconn;
System.Data.DataTable tbl = new System.Data.DataTable("INT32Table", "dbo");
tbl.Columns.Add("value", typeof(int));
tbl.Rows.Add(2);
tbl.Rows.Add(3);
tbl.Rows.Add(5);
tbl.Rows.Add(7);
tbl.Rows.Add(11);
using (SqlCommand command = new SqlCommand("table_sel"))
{
command.Connection = sqlconn;
command.Parameters.AddWithValue("#tbl", tbl);
command.CommandType = System.Data.CommandType.StoredProcedure;
SqlDataReader reader = command.ExecuteReader();
//do stuff
}
Oh sorry,
as far as I know there's no such table object in Java, you can use cs.setObject() but then again you should obtain that object from somewhere (query on mssql server ?).
If you're looking for performance on inserts with JDBC then you should consider preparedStatements and batch execution.
java.sql.connection connection = //driver, url, database, credentials ...
try
{
PreparedStatement ps =
connection.prepareStatement("insert into tbl values (?)");
ps.setInt(1, your 1st int);
ps.addBatch();
ps.setInt(1, your 2nd int);
ps.addBatch();
ps.setInt(1, your 3rd int);
ps.addBatch();
ps.executeBatch();
}
catch (SQLException e)
{
// err handling goes here
}
finally
{
// close your resources
}
Regards
S
You Cannt pass TVP's using JDBC. The Microsoft JDBC team is still working on this as they mentioned 2 years ago. Refer the Link :
visit : http://blogs.msdn.com/b/jdbcteam/archive/2012/04/03/how-would-you-use-table-valued-parameters-tvp.aspx
Try some alternate solution instead of using TVP's by passing XML parameter and with OPENXML() in procedure body.
In Java you should use CallableStatement.
eg.
java.sql.connection connection = //driver, url, database, credentials ...
try
{
CallableStatement cs =
connection.prepareCall("{ call table_sel(?) }");
cs.setInt(1, your int);
cs.execute();
}
catch (SQLException e)
{
// err handling goes here
}
finally
{
// close your ressources
}
Regards
S

Categories