null is entered when using prepared statement setcharacterstream h2 database - jdbc

I am trying to add value into clob as give on h2 website using preparedstatement.setcharacterstream(arg,reader) null value is inserted in the database
Connection con=getConnection();
pstmnt=con.prepareStatement(sql);
int paramcounter=1;
for (Object object : param) {
if(paramcounter==1) {
int len=object.toString().length();
Reader rdr=new StringReader(object.toString());
pstmnt.setCharacterStream(1, rdr,len);;
}
else{
pstmnt.setObject(paramcounter, object);
}
paramcounter++;
}
int retvalue=pstmnt.executeUpdate();
closeConnection();

We don't really have enough information to clearly identify why you might be having difficulty, but the following code works for me:
package h2test;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.sql.*;
public class H2testMain {
public static void main(String[] args) {
Connection con = null;
try {
// create an in-memory database ("...mem:...")
con = DriverManager.getConnection("jdbc:h2:mem:");
Statement s = null;
try {
s = con.createStatement();
s.execute("CREATE TABLE Table1 (Column1 CLOB)");
InputStream is = new FileInputStream("C:/__tmp/MIME/stuff.txt");
Reader rdr = new InputStreamReader(is, StandardCharsets.ISO_8859_1);
PreparedStatement ps = con.prepareStatement(
"INSERT INTO Table1 (Column1) VALUES (?)");
ps.setCharacterStream(1, rdr);
ps.executeUpdate();
ResultSet rs = s.executeQuery(
"SELECT Column1 FROM Table1");
int rowNumber = 0;
while (rs.next()) {
String str = rs.getString("Column1");
System.out.println(
String.format(
"Row %d: CLOB is %d character(s) long.",
++rowNumber,
str.length()));
}
rs.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
con.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
It reads the text file
02/15/2014 10:55 358,785 stuff.txt
writes the file contents to a CLOB column in an H2 database, reads the data back from the database, and produces the following console output:
Row 1: CLOB is 358785 character(s) long.

Related

Spring jdbc 'select for update'

I have the following method that I use with Spring JDBC
public String getState() {
String stateLink = template.queryForObject(
"select state_url from state_scrape_queue where in_use = false ORDER BY scrape_timestamp NULLS FIRST LIMIT 1",
(result, rowNum) -> {
return result.getString("state_url");
});
return stateLink;
}
I can't find an example of how to do a for update with Spring JDBC. I want in_use to be set to true using for update.
I need to use select for update since this application will be used in a multi-threaded fashion. I don't want more than one thread to get the same row and the way to prevent that is by using select for update
I was able to do this with plain JDBC, here is the question I asked how to do it with plain JDBC
select "for update" with JDBC?
Anyone know how this would be done?
This is what I came up with, feel free to recommend improvements
public String getState() throws SQLException {
String state = null;
Connection conn = DataSourceUtils.getConnection(template.getDataSource());
try {
conn.setAutoCommit(false);
String[] colNames = { "id", "state_url", "in_use" };
String query = "select " + Stream.of(colNames).collect(Collectors.joining(", "))
+ " from state_scrape_queue where in_use = false ORDER BY scrape_timestamp NULLS FIRST LIMIT 1 FOR UPDATE";
System.out.println(query);
try (Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery(query)) {
while (rs.next()) {
// Get the current values, if you need them.
state = rs.getString(colNames[1]);
rs.updateBoolean(colNames[2], true);
rs.updateRow();
conn.commit();
}
}
} catch (SQLException e) {
conn.setAutoCommit(true);
e.printStackTrace();
} finally {
conn.setAutoCommit(true);
}
return state;
}

stored procedure getting struck from java but working fine from SQL Developer

public void createCostRecord() throws Exception
{
Context ctx = null;
Connection conn = null;
CallableStatement ps = null;
ResultSet rs = null;
boolean spReturn = false;
try{
ctx = new InitialContext();
javax.sql.DataSource ds = (javax.sql.DataSource) ctx.lookup("CSMWebAppjndi");
conn = ds.getConnection();
conn.setAutoCommit(true);
String sp = "{call usp_CreateCostRecords(?,?)}";
ps = conn.prepareCall(sp);
ps.setInt(1, 1000);
ps.setInt(2, 2000);
for(int i=0;i<3;i++)
{
ps.executeQuery();
}
} catch (NamingException e)
{
log.error(e,e);
} catch (SQLException e)
{
log.error(e,e);
}
catch(Exception e)
{
log.error(e,e);
}
finally {
if(rs!=null){
rs.close();
}
if(ps!=null){
ps.close();
}
if(conn != null){
conn.close();
}
if(ctx != null ){
ctx.close();
}
}
}
while calling the above method the line number 23 executeQuery works fine for the first iteration of the for loop,
on second iteration of the for loop its getting struck at executeQuery and the procedure never completes execution.
But the weird thing is while i try the same procedure with same input from SQL developer its getting executed for any number of times without any struck.
Anyone help me to understand why the procedure from java is getting struck at second attempt and but its working fine in SQL developer.

ResultSet doesn't return values for DB2, but it return values if I try to do it manualy

I'm trying to get values from resulset, but it return nothing.
When i'm trying to do it through plain sql it return some values.
List<String> res = new ArrayList<String>();
try {
String query = "SELECT COLUMN_NAME FROM idoc.columns_to_show where user = ? "
+ DAO.DB2_UR_POSTFIX;
Connection connection = Properties.getDocsConnection();
try {
PreparedStatement pr = connection.prepareStatement(query);
try {
pr.setString(1, user.getDomainName());
ResultSet rs = pr.executeQuery();
try {
while (rs.next()) {
res.add(rs.getString("COLUMN_NAME"));
}
} finally {
rs.close();
}
} finally {
pr.close();
}
} finally {
connection.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return res;
Don't use column name "user" it is reserved name for DB2 database.
Therefore I couldn't find any result.

What is the best way to get the max id of table?

What is the best way to get the max id of table? Below I have paste the error and code. So I was planning on using afterLast() method to get the max id but I get an error.
ERROR:
SQLException: feature not supported
Code:
public class ex03 {
public static void main(String[] args) {
String url = "jdbc:ucanaccess://C:/Users/dave_000/My_WorkSpace/Eclipse_Workspaces/workspace-jsp/T_01_JDBC_01.accdb";
Connection con;
// Get Max ID
Statement stmt0;
String query0 = "select * from user";
try {
Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
} catch (java.lang.ClassNotFoundException e) {
System.err.print("ClassNotFoundException: ");
System.err.println(e.getMessage());
}
try {
con = DriverManager.getConnection(url, "", "");
stmt0 = con.createStatement();
// Get last ID
ResultSet rs = stmt0.executeQuery(query0);
rs.afterLast();
int maxID = rs.getInt("ID");
System.out.println(maxID);
pstmt1.close();
con.close();
} catch (SQLException ex) {
System.err.println("SQLException: " + ex.getMessage());
}
}
}
It is much more efficient to use SQL to find the maximum value:
select max(id) from user

preparedStatement.setNull(int parameterIndex, int sqlType)

Question #1
Could you anyone please tell me what is the benefit I will receive using the following code, when sPhoneExt is null ?
if (sPhoneExt == null || sPhoneExt.trim().equals("")) {
stmt.setNull(9, java.sql.Types.INTEGER);
} else {
stmt.setString(9, sPhoneExt);
}
Instead of stmt.setString(9, sPhoneExt);
Because iPhoneType = rset.getInt("phone_type"); will return 0 if the value is SQL NULL; which I don't want.
Question #2
And just curious stmt.setString(9, null) is performed what will be the return of rset.getInt("phone_type")?
Answer #2
getInt() will return zero when it is null in DB. You have to use the below code to know about DB NULL.
if (rs.wasNull()) {
// handle NULL field value
}
I don't see any benefit using setNull in this String case.
It is only used to check empty string "" and insert null in DB. But for that also we can do it like stmt.setString(9, null);
But when sPhoneExt is Integer and holding null, then We cannot perform
stmt.setInt(9, sPhoneExt); since setInt(int, int) API performs; converting (Unboxing) sPhoneExt (Integer) to primitive (int), so you will get NullPointerException. So you are in need of stmt.setNull(9, java.sql.Types.INTEGER);
Finally if you have inserted null in DB for NUMBER (sql type) column; getInt() will return 0 only.
This is irrespective of the below null set mechanism.
stmt.setString(9, null);
stmt.setNull(9, java.sql.Types.INTEGER)
Also Somebody told when the DB NUMBER column has default Value; that default value will be consider differently by the above two lines. But that is not true. Even that case also both the above line performs same way. It is setting NULL value; not the default value.
create table t1 (id number default 1 );
insert into t1 (id) values (2);
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class TestDB {
public static void main(String args[]) {
PreparedStatement stmt = null;
ResultSet rs = null;
Connection con = null;
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
con = DriverManager.getConnection("jdbc:oracle:thin:#10.201.32.92:1521:psprd1", "username", "password");
String query = null;
String l = null;
ResultSet rset = null;
int paramIndex = 1;
query = "UPDATE t1 " + " SET id = ?";
stmt = con.prepareStatement(query);
stmt.setInt(paramIndex++, null);
// stmt.setNull(1, java.sql.Types.INTEGER);
stmt.executeUpdate();
stmt.close();
query = "select id from t1 ";
stmt = con.prepareStatement(query);
rset = stmt.executeQuery();
rset.next();
System.out.println(rset.getString("id"));
} catch (Exception ex) {
ex.printStackTrace();
} finally {
try {
rs.close();
stmt.close();
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

Resources