Can not save binary using setBinaryStream to postgreSQL using java prepared statement - java

I have code to save binary to PostgreSQL, I am using JDK 1.5. but I got error..
And after I print the insert statement, then I try in my postgresql console, something error like this image:
File file = new File("E:\\myimage.gif");
FileInputStream fis;
try {
fis = new FileInputStream(file);
PreparedStatement ps = conn.prepareStatement("INSERT INTO golf_fnb.coba VALUES (?)");
ps.setBinaryStream(1, fis, (int)file.length());
System.out.println("SQl: "+ps);
ps.executeUpdate();
ps.close();
fis.close();
} catch (FileNotFoundException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
and this is the error in my eclipse console:
org.postgresql.util.PSQLException: ERROR: syntax error at or near "\"
at org.postgresql.util.PSQLException.parseServerError(PSQLException.java:139)
at org.postgresql.core.QueryExecutor.executeV3(QueryExecutor.java:152)
at org.postgresql.core.QueryExecutor.execute(QueryExecutor.java:100)
at org.postgresql.core.QueryExecutor.execute(QueryExecutor.java:43)
at org.postgresql.jdbc1.AbstractJdbc1Statement.execute(AbstractJdbc1Statement.java:517)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:50)
at org.postgresql.jdbc1.AbstractJdbc1Statement.executeUpdate(AbstractJdbc1Statement.java:273)
at finger.ConsoleUserInterfaceFactory$ConsoleUserInterface.verify4(ConsoleUserInterfaceFactory.java:605)
at finger.ConsoleUserInterfaceFactory$ConsoleUserInterface.run(ConsoleUserInterfaceFactory.java:117)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:651)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:676)
at java.lang.Thread.run(Thread.java:595)

I think the main error is using the column. Syntax: INSERT INTO TABLE(col1, ...) VALUES(val1, ...).
It just might also be you(or someone having a similar problem) intendedUPDATE golf_fnb SET coba = ? WHERE id = ?`. For the INSERT:
try (FileInputStream fis = new FileInputStream(file);
PreparedStatement ps = conn.prepareStatement("INSERT INTO golf_fnb(coba) VALUES (?)",
Statement.RETURN_GENERATED_KEYS)) {
ps.setBinaryStream(1, fis, (int)file.length());
System.out.println("SQl: "+ps);
int updateCount = ps.executeUpdate();
if (updateCount == 1) {
try (ResultSet rs = ps.getGeneratedKeys()) {
if (rs.next()) {
long id = rs.getLong(1);
System.out.println("ID " + id);
return;
}
}
}
} catch (SQLException | IOException e) {
e.printStackTrace();
}
Used try-with-resources to close all automatically.
The inserted record one might like to find. Assuming a long primary key, added getGeneratedKeys.
\', the apostrophe might give some problem. Manualy one should have \047 instead maybe. I hope this to-octal-conversion by the driver disappears with the new syntax above.

Related

I get an exception that the database is locked and I try to close connection and statement but here is the problem unreachable statement in try block

I get an exception that the database is locked and I try to close connection and statement, but here is the problem unreachable statement in try block.
public static ResultSet getData (String query){
try {
Connection conn = ConnectionProvider.connect();
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(query);
return rs;
try {
conn.close();
st.close();
rs.close();
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e);
return null;
}
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e);
System.out.println(e);
return null;
}
Everything you do after the first return statement in the outer try block can never be reached. The second try block will never be executed, therefore you have some unreachable code here.
I think what you want to do is this:
try {
Connection conn = ConnectionProvider.connect();
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(query);
try {
conn.close();
st.close();
rs.close();
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e);
return null;
}
return rs;
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e);
System.out.println(e);
return null;
}
Although I will say that this may just not be the correct place to use the try-catch. Maybe what you should do here is throw the possible exceptions back to whoever calls this method instead - usually nested try-catch blocks are very rarely actually used/needed in this way. Also if you encounter an exception, you just return null, instead of handling what this means for the rest of your application.
What you could also try is, assuming that at this point your query was successful:
try {
Connection conn = ConnectionProvider.connect();
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(query);
try {
conn.close();
st.close();
rs.close();
} catch (Exception e) {
throw e;
} finally {
return rs;
}
} catch (Exception e) {
throw e;
}
Though for this approach you should really think about what you need to happen in each error case.
As an additional side note, even though I'm aware that many people ignore this:
Always try to use the proper class for the Exceptions you expect in a catch-block, and if it's only for readabilities sake.
There are several things to improve in the piece of code you post.
First, you need to close the resources (Connection, Statement and ResultSet) in reverse order with respect to the opening order. So, first you should close the ResultSet, second the Statement, and finally the Connection.
Closing in the order you are doing might cause problems when closing Statement / ResultSet with the Connection already closed.
By other hand, starting in Java 7, you have the try-with-resources construct, that closes resources for you. You can take a look at The try-with-resources Statement docs.

Can someone tells me what is the error mean from Eclipse debug?

I've just learnt to walk through my code through Eclipse debugger.
However, I do not know why the process kept going back to line 71 - ps.executeUpdate() whereas the console mentioned the error at line 79 and it also mentioned other error lines at other classes. Hope someone can tell me what's going on.
Here's the code on subjectDAOImpl:
public void insertSubject(subject s) throws MyDataException {
try {
openConnection();
String qry = INSERT_QRY1;
//"INSERT INTO hi5project.subject(subject)VALUES (?)";
ps = connection.prepareStatement(qry);
int i = 0;
String[] sub = new String[3];
while(i < sub.length){
String e = s.getSubj();
ps.setString(1, e);
ps.executeUpdate(); - line 71
}
if (ps !=null )
closeConnection();
}catch (SQLException e) {
e.printStackTrace();
throw new MyDataException("DB Error"); - line79
}
}
Controller:
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
subject m = new subject();
manager mgr = new manager();
try {
String[] sub = request.getParameterValues("subject");
int i = 0;
while (i < sub.length) {
sub[i] = m.getSubj();
mgr.insertSubject(m);
out.println("Successful registered subject");
}
} catch (Exception ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
}
}
because you are executing multiple statement i would suggest to use Statement Batching instead
I don't know why you are using :
String[] sub = request.getParameterValues("subject");
int i = 0;
while (i < sub.length) {
sub[i] = m.getSubj();
mgr.insertSubject(m);
out.println("Successful registered subject");
}
I think you need just to use :
String[] sub = request.getParameterValues("subject");
mgr.insertSubject(m);
out.println("Successful registered subject");
and you can change the signature of insertSubject to insertSubject(String[] sub), now you can use this batch to insert the data:
connection.setAutoCommit(false);
try (PreparedStatement insert = connection.prepareStatement(qry)) {
for (String s : sub) {//loop throw your array
insert.setString(1, s);
insert.addBatch();
}
insert.executeBatch();//executing the batch
}
connection.commit();//commit statements to apply changes
Note your loop can not be finish because you don't increment the i, i already change a little of your logic hope this can help you, another thing it seems that the sub array always empty so you always use null

Properly closing JDBC connection objects

As far as I understood, closing the connection objects in finally block is the best practice. However, if rs.close() / ps.close() throws an exception at the finally block, it won't execute the conn.close(). Therefore I used to close connections at two positions (as in sample provided), once directly after use, and secondly additionally in a finally-block using a check for null. But some consider block 1 as redundant code. Is it really redundant or is there proper way to address this issue without closing the connection in two places?
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = dataSource.getConnection(); // geting the connection object
ps = connection.prepareStatement(INSERT_QUERY);
rs = ps.executeQuery();
// some logic here ...
// ---- block 1 ----
ps.close()
ps = null;
rs.close();
rs = null;
conn.close();
conn = null;
// ---- end block 1 ----
} catch (SQLException e) {
// exception handling ...
} finally {
closeQuietly(conn, ps, rs);
}
private void closeQuietly(Connection connection, PreparedStatement ps, ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {}
}
}
is there proper way to address this issue without closing the connection in two places?
Yes:
try (Connection conn = dataSource.getConnection(); // geting the connection object
Prepared Statement ps = connection.prepareStatement(INSERT_QUERY);
ResultSet rs = ps.executeQuery();) {
// ...
}
This is the 'try-with-resources' syntax. Everything declared inside the () after the try is guaranteed to be closed.
Yes, it would be called twice if everything goes fine with your code. That's the reason, people prefer to close any sort of connections (jdbc, stream etc) in the finally block.
As you know, The finally block gets executed whether program executed correctly or not.
So, I would recommend that you should not closing code after the use.
Jitendra
Block 1 is indeed redundant, as closeQuietly will always run due to the finally block.
closeQuietly does the right thing:
As each resource is surrounded by its own try-catch block, the code to cleanup the connection will run even if the block closing the statement or resultset throw exceptions: Those exceptions will be caught and ignored by their try-catch blocks.

quicky getting out of the catch block

I have a try-catch block as defined below and a for-each loop inside it.
try
{
// Doing some JDBC Connections here
Map<String,Connection> connections = new HashMap<>();
while(DeviceRS.next()){
final String ip_address = DeviceRS.getString("Connection_vch");
System.out.println("Value of the IP Address Field:"+ip_address);
connections.put(ip_address,DriverManager.getConnection("jdbc:mysql://" + ip_address + ":3306/test",RemoteUser,RemotePass));
}
for(final String ip : connections.keySet())
{
// Selecting and inserting into database here ...
}// ENd of for loop
}// ENd of try block
catch(SQLException ex){
ex.printStackTrace();
}
So, if something goes wrong with the connection, my program will get stuck in the catch block,printing the stack trace. I want to move onto other connections.
Is there a way can exit the catch block quickly just after printing the stack trace?
Note: I haven't mentioned full code here as I think my question is not concerned with my code.
Changed your code like this. To quickly skip it on its failure.
// Doing some JDBC Connections here
Map<String,Connection> connections = new HashMap<>();
try
{
while(DeviceRS.next()){
try{
final String ip_address = DeviceRS.getString("Connection_vch");
connections.put(ip_address,DriverManager.getConnection("jdbc:mysql://" + ip_address + ":3306/test",RemoteUser,RemotePass));
}
catch(SQLException ex){
ex.printStackTrace();
}
}
catch(Exception ex){
ex.printStackTrace();
System.out.println("in catch block");
//System.exit(0); // dont use this -in real time projects
}finally{
System.out.println("in finally block");
}
for(final String ip : connections.keySet())
{
// Selecting and inserting into database here ...
}// ENd of for loop
}// ENd of try block
I don't think there's fine looking way. But you can make another try-catch block inside your try-catch
try {
// your code here
for(final String ip : connections.keySet()) {
try { // inner catch
// your code, that will be continued if sql exception occurs
} catch (SQLException e) {
e.printStackTrace();
}
}
} catch (SQLException e) {
e.printStackTrace();
}
Like you said if you want if something goes wrong with the connection and you want to move onto another connection,just do this :
boolean check = true;
while(check) {
try {
Map<String,Connection> connections = new HashMap<>();
while(DeviceRS.next()){
final String ip_address = DeviceRS.getString("Connection_vch");
connections.put(ip_address,DriverManager.getConnection("jdbc:mysql://" + ip_address + ":3306/test",RemoteUser,RemotePass));
} // Ends inner while
check = false; //As connection is ok,we don't need to loop back.
for(final String ip : connections.keySet())
{
// Selecting and inserting into database here ...
}
}// Ends try block
catch(SQLException ex){
ex.printStackTrace();
} //Ends catch block
finally{
// close the connection if needed.
} // Ends finally block
}// Ends outer while loop

byte[] to be stored in Oracle

I have a byte[] which is actually an image.
i want to store it in Oracle 11g. I created a BLOB Column in my Table. and by following i tried to insert it.
String imageStr = "xyz...."
byte[] data = imageStr.getBytes();
String sQuery = "insert into Table (LOCATION , BLOB_DATA) Values ('Lahore', data) ";
It throws exception "java.sql.SQLException: ORA-01465: invalid hex number"
I searched it and found that this type of query should be done via PreparedStaement.
so i did something following
PreparedStatement prepStmt = dbConnection.prepareStatement("insert into Table (LOCATION, BLOB_DATA) values(?,?);
prepStmt.setString(1, 'Lahore');
prepStmt.setBytes(2, bytes);
I start getting error on dbConnection.prepareStatement(String) because the DBConnection class is not Java Native class.
It's a Custom class made by Earlier Developers for Database Connection and it do not has prepareStatement(String) function in it.
So what to do now??
1. Should i create a method prepareStatement(String) in DBConnection class?
2. Should i go for first approach?
You can look at my example to store image in db
Statement s;
Connection c;
FileInputStream fis;
PreparedStatement ps;
File file;
try
{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");//your driver
c=DriverManager.getConnection("Jdbc:Odbc:image","scott","tiger");//password and name changes according to your db
s=c.createStatement();
st.execute("Create table ImageStoring(Image_No number(5),Photo blob)");
}
catch(Exception e1)
{
e1.printStackTrace();
}
try
{
file=new File"D:/ARU/Aruphotos/4.jpg");
fis=new FileInputStream(file);
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
c=DriverManager.getConnection("Jdbc:Odbc:image","scott","tiger");
s=c.createStatement();
ps=c.prepareStatement("insert into ImageStoring values(?,?)");
ps.setInt(1,2);
ps.setBinaryStream(2,fis,(int)file.length());
System.out.println("success");
ps.execute();
ps.close();
c.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}

Categories