Java crash when database is empty - java

I am using the SQLite JDBC driver to access a database, for some reason the application terminates if there are no rows in the database with little explanation as to why it happened.
If the database is not empty it works perfectly fine;
This is where the termination occurs:
public static CustomFillTable Select(String table, String[] column, Object operand) throws SQLException
{
Connection connection = null;
PreparedStatement ps = null;
try
{
StringBuilder query = new StringBuilder();
query.append("select ");
for(int i = 0; i < column.length; i++)
{
query.append(column[i]);
if(i < column.length -1)
{
query.append(",");
}
}
query.append(" from ");
query.append(table);
//Verify usage of where clause
if(operand != null)
{
query.append(" where ");
query.append(operand);
}
//Termination occurs here
connection = DriverManager.getConnection(_connectionString);
connection.setAutoCommit(false);
ps = connection.prepareStatement(query.toString());
ResultSet rs = ps.executeQuery();
connection.commit();
CustomFillTable model = new CustomFillTable(rs);
while(rs.next())
{
System.out.println("id = " + rs.getString("id"));
System.out.println("name = " + rs.getString("name"));
}
return model;
}
The application closes at the DriverManager.getConnection line, something I don't find to be related to whether the database is populated or not.
Does anybody know how to fix this problem? I've posted the log dump information here.
Edit:
Connection String -
"jdbc:sqlite:D:\Documents\Uni\Semester 2\Languages, Platforms and Tools\Assignment\Java\SQLiteAssignment\mydatabasefile.db"

After looking at the vendors website it seems it is something that has been addressed in a later build. I ended up changing driver anyway but I thought this might be of some use to people.

Related

You have an error in your SQL syntax but query runs in MySQL workbench

Query doesn't work in IntelliJ but it does in SQL workbench. On other queries the updatePreparedStatement method works. I've checked my query for syntax errors and strangely enough it does run in sql workbench. Can somebody help a noob out?
public void updatePreparedStatement(String queryWithParameters, Object ... values) {
ArrayList<Map<String, Object>> result = new ArrayList<>();
try(PreparedStatement ps = this.connection.prepareStatement(queryWithParameters)) {
for(int i=0; i<values.length; i++) {
ps.setObject(i+1, values[i]);
}
int rs = ps.executeUpdate();
}catch (SQLException e){
e.printStackTrace();
}
}
public void assignOrdersToDeliveryRoute(BigInteger routeNumber, int[] orderNumbers){
DbConnection connection = new DbConnection();
System.out.println(Arrays.toString(orderNumbers));
StringBuilder orderNumberString = new StringBuilder();
int index =1;
for (int orderNumber : orderNumbers) {
String order = String.valueOf(orderNumber);
if (index < orderNumbers.length ){
orderNumberString.append(order).append(",");
}
else {
orderNumberString.append(order);
}
index++;
}
System.out.println(orderNumberString);
String query = "SET FOREIGN_KEY_CHECKS=0; UPDATE bestelling SET bezorgroutenummer = ? WHERE bestelnummer IN (" + orderNumberString + ")";
System.out.println(query);
connection.updatePreparedStatement(query, routeNumber);
}
https://dev.mysql.com/doc/refman/8.0/en/sql-prepared-statements.html says:
SQL syntax for prepared statements does not support multi-statements (that is, multiple statements within a single string separated by ; characters).
Run your statements one at a time.

Java SQL Server Application Stuck On statement.executeUpdate()

I have a rather annoying issue. In the piece of code below, I am trying to insert a new row to the "RevisionDispersion" table in my database. However, whenever I call stmt.executeUpdate() the program freezes and there ends up being no transaction to the database. No matter how long I wait; the database just won't be updated. Below is the code of interest:
private static final String INSERT_DISPERSION = "insert into RevisionDispersion("
+ Assignments.ID + ", "
+ Persons.EMAIL + ", "
+ Handins.ID + ")"
+ " values(?, ?, ?)";
public static void disperse(DataSource source, Assignment assignment) throws Exception
{
List<String> handins = assignment.getHandins();
//used to decide who checks which assignment
int maxRNG = Math.max(1, handins.size() / assignment.getPeerCount());
int rng = new Random().nextInt(maxRNG);
PreparedStatement stmt = null;
Connection con = null;
try{
//Get the connection, set it to TRANSACTION_SERIALIZABLE and set autocommit to false
con = source.getConnection();
configureConnection(con);
//Prepare the statement to insert the new dispersion
stmt = con.prepareStatement(INSERT_DISPERSION);
stmt.setString(1, assignment.getID());
//Iterate over all hand-ins and decide from which peer a peer receives feedback
for(int i = 0; i < handins.size(); i++)
{
HandIn handin = new HandIn(source.getConnection(), handins.get(i));
String student = handin.getEmail();
stmt.setString(2, student);
for(int j = 1; j <= assignment.getPeerCount(); j++)
{
HandIn otherHandin = new HandIn(source.getConnection(), handins.get(j * rng));
stmt.setString(3, otherHandin.getId());
stmt.executeUpdate();
}
}
con.commit();
}catch(Exception e){
throw e;
}finally{
closeQuietly(con, stmt);
}
}
//This method is originally in the DBAO class, but I put it here for you folks.
protected static void configureConnection(Connection connection) throws SQLException
{
connection.setAutoCommit(false);
connection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
}
This problem occurs in no other places in the application. Whenever I run the SQL statement in SQL Server Management Studio, with identical parameters, it does not get stuck and it inserts the new rows just fine. After deleting the rows and trying the same in the application, it gets stuck.
Can anyone point me in the right direction of what is going wrong? I've been trying for 3 hours straight now...
Stuff I already tried
-use stmt.addBatch() rather than executeUpdate() (did not make a difference. It would get stuck at executeBatch())
-Check if all connections are being closed properly; they are.
-Check if other statements/resultsets are still open that use RevisionDispersion table (there are none still open. Even if there were, should not make a difference I think?)
-Completely delete the database and set it back up
I solved the issue...
In a different piece of code I had the following:
private static final String GET_NOT_DISPERSED = "select * from Assignments where "
+ Assignments.CLOSE_DATE + "<=? and "
+ Assignments.PEER_START_DATE + ">=? and "
+ Assignments.ID + " not in(select " + Assignments.ID + " from RevisionDispersion)";
private void makeMailDispersion() throws Exception
{
DateTime currentDate = DateTime.getCurrentDateTime();
PreparedStatement assignmentsStmt = null;
ResultSet assignments = null;
Connection con = null;
try{
con = source.getConnection();
configureConnection(con);
assignmentsStmt = con.prepareStatement(GET_NOT_DISPERSED);
assignmentsStmt.setString(1, currentDate.toString());
assignmentsStmt.setString(2, currentDate.toString());
assignments = assignmentsStmt.executeQuery();
ArrayList<Assignment> requiresDispersion = new ArrayList<>();
assignments.close();
assignmentsStmt.close();
while(assignments.next())
{
Assignment assignment = new Assignment(source.getConnection(), assignments.getString(Assignments.ID));
AssignmentDisperser.disperse(source, assignment);
}
}catch(Exception e){
throw e;
}finally{
closeQuietly(con, assignmentsStmt, assignments);
}
}
In this piece of code, I closed the variables 'assignments' and 'assignmentsStmt'. I thought this would be sufficient to unlock the table after having used the GET_NOT_DISPERSED query. Apparently it was not: the table was still locked.
What I had to do in order to fix it: aside from calling assignments.close() and assignmentsStmt.close() I also had to call con.close(). That completely unlocked the table and allowed the code to run properly.

A lock could not obtained within the time requested issue

The title is the error I'm getting, when I click load my program freezes. I assume it's because I'm doing a statement inside a statement, but from what I see it's the only solution to my issue. By loading, I want to just repopulate the list of patients, but to do so I need to do their conditions also. The code works, the bottom method is what I'm trying to fix. I think the issue is that I have 2 statements open but I am not sure.
load:
public void DatabaseLoad()
{
try
{
String Name = "Wayne";
String Pass= "Wayne";
String Host = "jdbc:derby://localhost:1527/Patients";
Connection con = DriverManager.getConnection( Host,Name, Pass);
PatientList.clear();
Statement stmt8 = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
String SQL8 = "SELECT * FROM PATIENTS";
ResultSet rs8 = stmt8.executeQuery( SQL8 );
ArrayList<PatientCondition> PatientConditions1 = new ArrayList();
while(rs8.next())
{
PatientConditions1 = LoadPatientConditions();
}
Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
String SQL = "SELECT * FROM PATIENTS";
ResultSet rs = stmt.executeQuery( SQL );
while(rs.next())
{
int id = (rs.getInt("ID"));
String name = (rs.getString("NAME"));
int age = (rs.getInt("AGE"));
String address = (rs.getString("ADDRESS"));
String sex = (rs.getString("SEX"));
String phone = (rs.getString("PHONE"));
Patient p = new Patient(id, name, age, address, sex, phone,
PatientConditions1);
PatientList.add(p);
}
UpdateTable();
UpdateAllViews();
DefaultListModel PatientListModel = new DefaultListModel();
for (Patient s : PatientList) {
PatientListModel.addElement(s.getAccountNumber() + "-" + s.getName());
}
PatientJList.setModel(PatientListModel);
}
catch(SQLException err)
{
System.out.println(err.getMessage());
}
}
This is the method that returns the ArrayList of patient conditions
public ArrayList LoadPatientConditions()
{
ArrayList<PatientCondition> PatientConditionsTemp = new ArrayList();
try
{
String Name = "Wayne";
String Pass= "Wayne";
String Host = "jdbc:derby://localhost:1527/Patients";
Connection con = DriverManager.getConnection( Host,Name, Pass);
Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
String SQL = "SELECT * FROM PATIENTCONDITIONS";
ResultSet rs5 = stmt.executeQuery( SQL );
int e = 0;
while(rs5.next())
{
e++;
String ConName = (rs5.getString("CONDITION"));
PatientCondition k = new PatientCondition(e,ConName);
PatientConditionsTemp.add(k);
}
}
catch(SQLException err)
{
System.out.println(err.getMessage());
}
return PatientConditionsTemp;
}
I had a similar problem.
I was connecting to derby db hosted on local server.
I created 2 simultaneous connections:
With squirrel
With ij tool
When a connection makes a modification on a table, it first gets a lock for the particular table.
This lock is released by the connection only after committing the transaction.
Thus if the second connection tries to read/write the same table, a msg prompts saying:
ERROR 40XL1: A lock could not be obtained within the time requested
To fix this, the connection which modified the table has to commit its transaction.
Hope this helps !
Here is a good place to start: http://wiki.apache.org/db-derby/LockDebugging
You need to close your statement and result set as well so that when you restart your program they won't be open. Add stmt.close(); and rs.close(); at the end of your lines of code within the try and catch statement.
Why could you not use the same connection object to do both the queries?
Like pass that connection object to the LoadPatientConditions() as a parameter and use it there.

compare integer text field value with mysql data in java

I want to check whether the newly entered data is already in the table
code:
txtNo = new JTextField();
{
try {
Class.forName("com.mysql.jdbc.Driver");
String srcurl1 = "jdbc:mysql://localhost:3306/DB_name";
Connection con = DriverManager.getConnection(srcurl1,"root","paswrd");
Statement stmt1 = con.createStatement();
ResultSet rs1 = stmt1.executeQuery("select No from bank where No='"+txtNo.getText()+"' ");
int ch =rs1.getInt("No");
int ch4= Integer.parseInt(txtNo.getText());
if(ch==ch4) // input 58 == 58
System.out.println("already exits");
}
catch(Exception e)
{
System.out.println("Exception:"+e);
}
}
Error :
Exception:java.sql.SQLException: Illegal operation on empty result set.
You need to check if the result set has elements or not:
while(rs1.next())
{
int ch = rs1.getInt("No");
// ...
}
You get this exception when the select statement returns an empty set. Add a try/catch block which acts upon the knowledge that the data is not already in the table in the catch block.
You need to check the ResultSet first to check to see that it contains rows:
if (rs1.next()) {
int ch =rs1.getInt("No");
...
}
The easiest way to check whether a particular record exists in the database might be just as follows:
Select 1 from bank where No = [your_supplied_value]
This query would return 1 if it finds a row in your database with the supplied data or return an empty resultset. So, all you need to check is whether ANY value is returned in the resultset or whether it is emtpy.
Here's a sample code to get you started:
txtNo = new JTextField();
{
try {
String compareText = txtNo.getText().trim();
if(compareText.length() > 0){
Class.forName("com.mysql.jdbc.Driver");
String srcurl1 = "jdbc:mysql://localhost:3306/DB_name";
Connection con = DriverManager.getConnection(srcurl1,"root","paswrd");
Statement stmt1 = con.createStatement();
ResultSet rs1 = stmt1.executeQuery("select 1 from bank where No='"+txtNo.getText()+"' ");
boolean isPresent = rs1.next();
if(isPresent){
System.out.println("Already exists!!");
}
}
}
catch(Exception e)
{
System.out.println("Exception:"+e);
}
}
I hope this is not your final code, because there're several problems with it:
You're not managing your resources properly. Once you're done querying your database, you should consider closing your resultset, statement and connection objects.
Note that I checked whether the text in the JTextField is empty or not. This is a good way of preventing a call to the database when you know that the text field had no value in it.
I would suggest using a PreparedStatement rather than a Statement for querying to your database.
A ResultSet is initially positioned before the first row. So you need to call next() to move it to the next row (and check that it returns true) before you call one of the getXXX() methods.
JTextField input = new JTextField();
ArrayList < Integer > list = new ArrayList < Integer > ();
int integerv = Integer.parseInt(input.getText());
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/DB_name", "root", "yourpassword");
Statement stm = con.createStatement();
ResultSet rs = stm.executeQuery("select column_name from table_name");
while (rs.next()) {
list.add(rs.getInt(1));
}
for (int a = 0; a < list.Size(); a++) {
if (a.get(a) == integerv) {
System.out.println("Match found");
break;
} else {
System.out.println("Match not found");
break;
}
}
} catch (Exception e) {
System.out.println("Error :" + e.getMessage());
}

Java PreparedStatement RETURN_GENERATED_KEYS not working

I am trying to get the identity column returned to my java program when doing a SQL insert. I am getting the following error when running the code
Uncaught exception thrown in one of the service methods of the
servlet: Cocoon. Exception thrown : java.lang.AbstractMethodError: java/sql
/Connection.prepareStatement(Ljava/lang/String;I)Ljava/sql/PreparedStatement;
Here is the code I am running.
private void insertUserInputParameters(ReportData rptData){
UserInputParameters userParams = rptData.getUserInputData();
StringBuilder sql = new StringBuilder();
PreparedStatement pstmt = null;
ResultSet rs = null;
int userDataId = -1;
//Get a database connection.
sl = ServiceLocator.getInstance();
ds = sl.getDataSource("jdbc/collegeguide");
con = ds.getConnection();
con.setReadOnly(false);
sql.append("insert into cpgusrdtaf (statecd, addr1, addr2, city, state, ");
sql.append("zipcode, dependent, shdindic, marstatus, residency, prntatge, ");
sql.append("fincome, mincome, pincome, taxspaid, taxreturn, elig1040, ");
sql.append("gincome, pcash, inetwrth, bnetwrth, pbenefit, paddlinf, ");
sql.append("puntax, pdslcwrk, smstatus, sresidncy, studtr, stud1040, ");
sql.append("sadjinc, sincome, spincome, sdslcwrk, studtax, scash, ");
sql.append("sinvest, snetwrth, saddlinf, suntax, househld, nmbrsch, ");
sql.append("studact, studsat, schools, housing) ");
sql.append("values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?, ");
sql.append("?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
//This line of code is where I get the error**
pstmt = con.prepareStatement(sql.toString(), Statement.RETURN_GENERATED_KEYS);
//If I remove the 'Statement.RETURN_GENERATED_KEYS' I do not get the error.**
pstmt = con.prepareStatement(sql.toString());
setStatementValues(pstmt, userParams);
pstmt.executeUpdate();
rs = pstmt.getGeneratedKeys();
if(rs.next()){
userDataId = rs.getInt(1);
}
I am not allowed to use stored procedures, so I cannot go that route. Any help would be greatly appreciated
I am using java 1.5
Thanks in advance
Doug
Assuming the arguments/parameters are balanced
(please confirm the query executes natively, and that the driver supports the RETURN_GENERATED_KEYS),
Can you try to use RETURN_GENERATED_KEYS as part of the argument to an executeUpdate call?
pstmt = con.createStatement();
pstmt.executeUpdate(sql.toString(), Statement.RETURN_GENERATED_KEYS);
EDIT:
Just read your note about using DB2. According to http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/index.jsp?topic=%2Fcom.ibm.db2.luw.apdv.java.doc%2Fsrc%2Ftpc%2Fimjcc_t0057053.html
_Restriction: For IBM Data Server Driver for JDBC and SQLJ version 3.57 or later, the following form is not valid for inserting rows into a view on a DB2® for z/OS® data server.
Connection.prepareStatement(sql-statement,
Statement.RETURN_GENERATED_KEYS);_
this way it works for me:
prepStmt = con.prepareStatement(sql, new String[]{"NameOfIDField"});
I once had a problem with an oracle db where this was not working if the table has many fields.
But the above is working for me even with 60 fields.
My JT400.jar file was an older version. I downloaded the latest jar file from sourceforge and the problem was solved.
Try with Statement
Statement st = null;
ResultSet rs = null;
st = con.createStatement();
String query = " INSERT INTO refac_folios
([usuario], [estatus]) VALUES ('" + usuario + "'," + Vista_FoliosRefacciones.ESTATUS_CREADO )" ;
Integer afectadas = st .executeUpdate( query, Statement.RETURN_GENERATED_KEYS );
if (afectadas > 0){
rs = st.getGeneratedKeys();
if (rs .next()) {
folio = rs.getInt(1);
}
rs.close();
}
st.close();

Categories