JDBC connection hangs at executing rs.next() - java

I'm trying to read from a mySQL server (in my LAN) a huge resultSet. I implemented it the way I found looking for the setFetchSize method: BalusC's Example. So I did:
con = DriverManager.getConnection(url, user, password);
//con.setAutoCommit(false);
st = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
st.setFetchSize(Integer.MIN_VALUE);
rs = st.executeQuery(query);
int count = 0;
while (rs.next ()) {
// Process entry
String rsc = rs.getString ("resource");
String tpc = rs.getString("topic");
System.out.println(count + ": " + rsc);
++count;
}
Although, it hangs at row 1077 at the line rs.next(). It doesn't throw exception.
EDIT:
After a timeout something new happened. It returned this error
message:
JDWP exit error JVMTI_ERROR_NONE(0): getting frame location [../../../src/share/back/stepControl.c:641]
This error seems to be unrelated.
EDIT2: I've coded a PHP script for retrieving results by stream and happens exactly the same. So it has nothing to do with JDBC... I don't know what is going on!!

The second error message is a deadlock in the Eclipse debugger when hot-swapping and/or JRebel (source):
It is a known problem, actually two problems.
1) Eclipse debugger deadlocks sometimes on hot-swapping (true for any version of JRebel).
2) JVM crash on hotswapping - it is true for JRebel 4M1.
We are expecting bugfix release soon (3.6.2 together with Eclipse plugin) - It will fix first problem. Second problem should be fixed with 4M2 release.
Suggestions:
Update Eclipse to 3.7.2 and JRebel to the latest release
Start the application again.
Use logging/System.out.println() to debug
Check the log of your mysql server for problems (harddisk, network)
Run the query in a SQL workbench (to see whether this is a problem in the query/the server or your code)

OKay, the problem was at the query itself.
I've found that streaming is very sensitive on how query is built. If I make a little change (like adding SELECT DISTINCT) it buffers or hangs. Finally, I left a column out of the query and worked...

Related

Catch SQL RaiseError in jsp

I am developing a database and some JSP Pages to perform CRUD operations on it.
I cannot catch exceptions related to my SQL Code in my JSP Code.
For Example:
I have this part of code where I raise an error in T-SQL:
IF #existing > 0
BEGIN
RAISERROR ('ID primário ja existe', 1, 1)
RETURN 0
END
IF (#CategoriaId IS NULL)
BEGIN
RAISERROR('O CategoriaId não pode ser nulo',1,1)
RETURN 0
END
I need to call the function where I raise those errors in JSP code.
Heres a part of the JSP Code:
try
{
rs = stmt.executeQuery(sql);
}
catch (Exception u)
{
out.println(u.toString());
}
And it never returns the error from T-SQL.
However I know that the function reaches the catch statement because if I throw a println("test") in there it writes test on the jsp page.
I always get this exception : >com.microsoft.sqlserver.jdbc.SQLServerException: The statement did not return a result set.
This is an insert operation I'm doing, and if I write the correct values it inserts without any problems. But even when it inserts it throws that exception.
Edit: I tried u.getMessage() already
You really should read the exception message you get.
The reason you don't get the exception from the database is probably because it's masked by the exception you get from the java.
I'm a .net guy myself, the last time I've worked with java was about 17 years ago, so I'm not familiar with the correct method you should use, but it's probably not executeQuery.
According to this post, you should use execute instead.
Update
After our conversation in the comments I've done some digging and found this pearl in MSDN.
Note this part:
A RAISERROR severity of 11 to 19 executed in the TRY block of a TRY…CATCH construct causes control to transfer to the associated CATCH block. Specify a severity of 10 or lower to return messages using RAISERROR without invoking a CATCH block.
This means that your raiserror's severity parameter should be somewhere within the range of 11 to 19.
I was struggling with this with a Spring Boot project of mine. The Exception thrown would not contain the RAISERROR that exists in a MSSQL table's trigger. The ExceptionUtils.getRootCauseMessage(e) would only get the message "The transaction ended in the trigger".
Up until now I had the MSSQL Driver loaded through my projects maven pom.xml file.
The moment I placed the MSSQL Driver in my JVMs jre/lib/ext folder the RAISERROR messages where included in the Java Exception.

Huge time accessing database from Java

I'm a junior java programmer and I've finally made my first program, all by myself, apart from school :).
The basics are: you can store data on it and retrieve it anytime. The main thing is, I want to be able to run this program on another computer (as a runable .jar file).
Therefore I had to install JRE and microsoft access 2010 drivers (they both are 32 bit), and the program works perfect, but there is 1 small problem.
It takes ages (literaly, 17 seconds) to store or delete something from the database.
What is the cause of this? Can I change it?
Edit:
Here's the code to insert an object of the class Woord into the database.
public static void ToevoegenWoord(Woord woord) {
try (Connection conn = DriverManager.getConnection("jdbc:odbc:DatabaseSenne")) {
PreparedStatement addWoord =
conn.prepareStatement("INSERT INTO Woorden VALUES (?)");
addWoord.setString(1, woord.getWoord());
addWoord.executeUpdate();
} catch (SQLException ex) {
for (Throwable t : ex) {
System.out.println("Het woord kond niet worden toegevoegd aan de databank.");
t.printStackTrace();
}
}
}
Most likely creating Connection every time is slow operation in your case (especially using JDBC-ODBC bridge). To confirm this try to put print statements with timestamp before and after the line that get Connection from DriverManager. If that's the case consider not to open connection on every request but open it once and reuse, better yet use some sort of Connection Pooling, there are plenty of options available.
If that's mot the case then actual insert could be slow as well. Again simple profiling with print statements should help you to discover where your code is spending most of the time.
First of all, congrats on your first independent foray. To answer your question / elaborate on maximdim's answer, the concern is that calling:
try (Connection conn = DriverManager.getConnection("jdbc:odbc:DatabaseSenne")) {
every time you're using this function may be a major bottleneck (or perhaps another section of your code is.) Most importantly, you will want to understand the concept of using logging or even standard print statements to help diagnose where you are seeing an issue. Wrapping individual lines of code like so:
System.out.println("Before Connection retrieval: " + new Date().getTime());
try (Connection conn = DriverManager.getConnection("jdbc:odbc:DatabaseSenne")) {
System.out.println("AFTER Connection retrieval: " + new Date().getTime());
...to see how many milliseconds pass for each call can help you determine exactly where your bottleneck lies.
Advise: use another database, like Derby, hsqldb. They are not so different from MSAccess, (= can use a file based DB), but perform better (than JDBC/ODBC). And can even be embedded in the application (without extra installation of the DB).

MBO ResultSet Filters - JDBC Driver

I am attempting to combine two disparate data sources into one MBO. The sybase documentation states that you have to develop a custom result set filter in java. Ok. No big deal. I am somewhat familiar with JDBC Rowsets so I think I can probably handle this. So I go grab JConnect 7 and am attempting to use the JDBC driver in my result set filter to get a result set that I can use to filter the data set returned from the web service I am connecting to. I have tested my connection with the simple test below:
try
{
DriverManager.registerDriver((Driver)Class.forName("com.sybase.jdbc4.jdbc.SybDriver").newInstance());
Connection conn = DriverManager.getConnection("jdbc:sybase:Tds:localhost:5500", "dba", "sql");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("Select * from traveler where traveler_id = 1");
while (rs.next())
{
System.out.println(rs.getRow());
}
} catch (Exception se)
{
se.printStackTrace();
}
Of which I get a rowcount of one back, which is what I am expecting. The problem is when I implement this same code in the ResultSet filter class, and attempt to preview it in the MBO, I get the following error in the eclipse debug console (distilled for clarity):
22:14:20 [ERROR] [ExecuteSection]: Execution error
java.lang.reflect.InvocationTargetException...
[...]
Caused by: java.lang.UnsatisfiedLinkError: no dbjodbc11 in java.library.path
This looks like a classpath issue, but I have the Jconnect jar in my build path, and that is verified by the fact that my little test runs successfully. Is this an eclipse issue.. is eclipse using a different classpath when executing code for the Mobile workspace project?
Can't remember the exact path right now, but there is a third-party lib folder under the <SybaseInstallation>/UnwiredWorkspace folder. Try adding your jar there.

Java/Oracle: executing a prepared statement fails on a second iteration of a loop (not all variables bound). Why?

I'm debugging a Java App, which connects to Oracle DB via a thin client.
The code looks as follows: (i'm trying to simplify the use case here so pardon me if t does not actually comile)
Connection conn = myEnv.getDbConnection();
CallableStatement call = conn.prepareCall(
"{ ? = call SomePackage.SomeFunction (?)}");
call.registerOutParameter(1, OracleTypes.CURSOR);
for (int runCount = 0; runCount <= 1; runCount++) {
currency = getCurrency(runCount); // NOTE: [0]=CAD, [1]=USD
call.setString(2, currency);
try { call.execute(); } catch { // BREAKS HERE! }
ResultSet rset = (ResultSet)call.getObject(1);
... more code that I think is irrelevant as it does not use/affect "call"
}
When I run this code, the following happens:
First iteration of the loop, currency is set to "CAN".
Entire code of the loop runs perfectly fine.
Second iteration of the loop,currency is set to "USD".
The "execute()" call throws SQLException, as follows:
ORA-01008: not all variables bound
Why?
My initial suspicion was that it somehow related to registerOutParameter call before the loop that doesn't get called on 2d iteration. But moving that call inside the loop does not fix the problem. It seems that execute() call un-binds something but having both bindings inside the loop does not help.
What am I missing?
If it's something obvious, please be gendle - I know very little about Oracle and thin client, and Googling witrh miriad of fancy queries returned no love.
One additional clue: this design seemed to have worked before when the app was on Oracle 9 with OCI drivers. The reason I'm debuggin it is someone "upgraded" it to Oracle 10.2 thi client and it broke.
My next step should probably be bringing in entire CallableStatement into the loop, but that kind of defeats the whole idea of why I though prepared statements are used in the first place, no?
Have you tried adding call.clearParameters() into the loop? Perhaps it would reset some internal state on the object that it needs to execute again.
The explanation obtained via Oracle Support call was that this version of Java (1.3) was not compatible with new Oracle. Java 1.4 fixed the issue.

How can I update my MySQL database from a Java applet?

I'm new to Java and I need some advice/information on how to debug my Java Applet.
I have created a applet that simply updates a MySQL database. The applet seems to load in the web page with no errors. When I click on my button to update the database it seems to actually make the call to the applet, BUT nothing happens, i.e. no new inserts are made to the database, and the page returns properly.
I have taken the applet code and tested it in a Java desktop app. It works fine, no changes other than removing the "extend Applet" modifier. In the desktop app the database gets updated properly.
If I was given some pointers on how to write to the Java Console window that might help me in debugging the code - but I don't know how to do that. I'm not sure what else to try to find the issue. Everything seems correct to me.
BTW: I'm using Netbeans 6.7 in Windows 7 with the MySQL server and Glassfish 2.1 on a CENTOS (Linux) system.
Here is my code for the applet:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.me.db;
import java.applet.*;
import java.sql.*;
/**
*
* #author Rick
*/
public class dbapplet extends Applet {
/**
* Initialization method that will be called after the applet is loaded
* into the browser.
*/
public void init() {
// TODO start asynchronous download of heavy resources
}
public long SaveToDatabase(String subject, String note, int priority,
String category, String isOpen, String currentSession) {
Connection con = null;
Statement stmt = null;
StringBuilder sb = new StringBuilder();
long lastInsertId = -1;
try {
//build the insert
int IsOpen = (isOpen.contains("1")) ? 1 : 2;
sb.append("INSERT INTO 'LogDetails' ('category', 'priority',
'subject', 'note', 'is_open', 'has_attachements') VALUES");
sb.append(" (");
sb.append("'" + category + "',");
sb.append(priority + ",");
sb.append("'" + subject + "',");
sb.append("'" + note + "',");
sb.append("b'" + IsOpen + "',");
sb.append("b'0');");
//connect and execute the insert
String dbURL = "jdbc:mysql://localhost/authentication";
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection(dbURL, "xxxxxxx", "yyyyyyyy");
stmt = con.createStatement();
stmt.execute(sb.toString());
//get the last inserted id
ResultSet rs = null;
rs = stmt.executeQuery("SELECT LAST_INSERT_ID()");
if (rs.next()) {
lastInsertId = rs.getLong(1);
}
rs.close();
} catch (Exception e) { //database problem
System.out.println("Error " + e.getMessage());
System.out.println(sb.toString());
}
return lastInsertId;
} //end of SaveToDatabase
public void QuickSaveToDataBase() {
//disgard the result for now - lets see if we can get this working
this.SaveToDatabase("Quick Save", "Testing of the Quick Save Function",
1, "Testing", "1", "skjdkjd-junk");
}
}
JDBC in Applet should be avoided if all possible. Here are the security issues you will be facing,
You have to open up your database to all IP addresses unless this is an inhouse or enterprise app.
Your database password will be in the applet, readable by anyone with a little reverse-engineering.
If you really want do this, you need to use trusted Applet by signing it.
Since you've got localhost as the server's address..., unless you're running the mysql server on the same box, this will cause a problem. Also, I believe there are security restrictions that disallow contacting localhost over a port from a Java Applet.
Hope this helps.
Applets run in a sandbox that (when in browser) dramatically restrict what they can do. In general, they can't open up connection to any host other than the one they were served up from.
This site: http://www.securingjava.com/chapter-two/chapter-two-2.html is a little dated, but gives you a good general idea for what restrictions you'll be facing.
The most likely reason for the failure is a classloader exception. The applet's classloader is a URLClassloader that can load classes only from certain URLs due to the security implications.
In this case, the applet classloader is most likely unable to load the MySQL JDBC driver. If you have to make the applet work, place the MySQL driver's jar files in an area on the web server that is accessible by the applet, and use the archive attribute of the applet tag to enable the classloader to load the driver.
Why should you not do this?
Although the answer given above will work technically, it is a really bad practice to expose your database on the internet or a DMZ(de-militarized zone); that normally includes an intranet as well in certain companies. Presumably, you are doing this for studying applets and not for production usage. ZZ Coder has already pointed this out.

Categories