I am trying to add records to a table in an HSQL database through Java.
I have an HSQL database I made through OpenOffice, renamed the .odb file to .zip and extracted the SCRIPT and PROPERTIES files (It has no data in it at the moment) to a folder "\database" in my java project folder.
The table looks like this in the SCRIPT file
CREATE CACHED TABLE PUBLIC."Season"("SeasonID" INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL PRIMARY KEY,"Year" VARCHAR(50))
All fine so far, the database connects just fine in Java with this code:
public void connect(){
try{
String dbName = "database\\db";
con = DriverManager.getConnection("jdbc:hsqldb:file:" + dbName, // filenames prefix
"sa", // user
""); // pass
}catch (Exception e){
e.printStackTrace();
}
}
I have the following code to insert a record into "Season".
public void addSeason(String year){
int result = 0;
try {
stmt = con.createStatement();
result = stmt.executeUpdate("INSERT INTO \"Season\"(\"Year\") VALUES ('" + year + "')");
con.commit();
stmt.close();
}catch (Exception e) {
e.printStackTrace();
}
System.out.println(result + " rows affected");
}
I have a final function called printTables():
private void printTables(){
try {
stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM \"Season\"");
System.out.println("SeasonID\tYear");
while(rs.next()){
System.out.println(rs.getInt("SeasonID") + "\t\t" + rs.getString("Year"));
}
}catch (Exception e) {
e.printStackTrace(System.out);
}
}
Now if I run this sequence of functions:
connect();
printTables();
addSeason("2010");
printTables();
I get this output:
SeasonID Year
1 rows affected
SeasonID Year
0 2010
Now when I close the program and start it again I get exactly the same output. So the change made during the first run hasn't been saved to the database. Is there something I'm missing?
It's caused by write delay params in hsqldb, by default has 500ms delay synch from memory to files.
So problem is solved when it's set to false
statement.execute("SET FILES WRITE DELAY FALSE");
or set as you like based on your app behaviour.
So my workaround is to close the connection after every update, then open a new connection any time I want to do something else.
This is pretty unsatisfactory and i'm sure it will cause problems later on if I want to perform queries mid-update. Also it's a time waster.
If I could find a way to ensure that con.close() was called whenever the program was killed that would be fine...
Related
I've tried most of the examples found here and the web, but I can't open a MS access database(2002 or 2013) and get an updatable result set using UCanAccess. The same code using the JDBC:ODBC driver/connection/works. I've written short test code to check concur_updatable to check this, so I must be missing something. I'm using JDK 1.7 on a Win7 machine. I also have another machine with the same results.
This works:
/*
class jdbc, for testing jdbc:odbc CONCUR_UPDATABLE.
*/
import java.sql.*;
public class jdbc {
private static String dbFQN;
public static void main(String[] args) {
try {
dbFQN = ("C:\\phil\\programming\\kpjl2002.mdb");
String database = "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=" + dbFQN;
System.out.println("Loading database: " + database);
Connection conn = DriverManager.getConnection(database, "", "");
Statement s = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
// Fetch records from table
String selTable = "SELECT * FROM " + "tblLibrary" + " ORDER BY Artist, Cat, Cart";
s.execute(selTable);
ResultSet rs = s.getResultSet();
int concurrency = rs.getConcurrency();
if(concurrency == ResultSet.CONCUR_UPDATABLE)
{
System.out.println("rs is updatable");
} else {
System.out.println("rs Not updatable");
}
s.close();
conn.close();
} //close try
catch (Exception ex) {
ex.printStackTrace();
} //close catch
} //close main method
} //close dbAccess class
The output is that rs is updatable.
This doesn't work:
/*
class ucan, for testing ucanaccess CONCUR_UPDATABLE.
C:\jdk1.7.0_79\jre\lib\ext\ucanaccess-2.0.9.5.jar
C:\jdk1.7.0_79\jre\lib\ext\hsqldb.jar
C:\jdk1.7.0_79\jre\lib\ext\jackcess-2.1.0.jar
C:\jdk1.7.0_79\jre\lib\ext\commons-lang-2.6.jar
C:\jdk1.7.0_79\jre\lib\ext\commons-logging-1.1.1.jar
also present:
C:\jdk1.7.0_79\jre\lib\ext\commons-logging-1.2.jar
C:\jdk1.7.0_79\jre\lib\ext\commons-lang3-3.4.jar
*/
import java.sql.*;
public class ucan {
private static String dbFQN;
public static void main(String[] args) {
try {
dbFQN = ("C:\\phil\\programming\\kpjl2002.mdb");
String database = "jdbc:ucanaccess://" + dbFQN;
System.out.println("Loading database: " + database);
Connection conn = DriverManager.getConnection(database, "", "");
Statement s = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
// Fetch records from table
String selTable = "SELECT * FROM " + "tblLibrary" + " ORDER BY Artist, Cat, Cart";
s.execute(selTable);
ResultSet rs = s.getResultSet();
int concurrency = rs.getConcurrency();
if(concurrency == ResultSet.CONCUR_UPDATABLE)
{
System.out.println("rs is updatable");
} else {
System.out.println("rs Not updatable");
}
s.close();
conn.close();
} //close try
catch (Exception ex) {
ex.printStackTrace();
} //close catch
} //close main method
} //close dbAccess class
the output is that rs is Not updatable. So I cannot update or insert rows in the resultset.
The code posted is the operative part of a larger project, where UCanAccess can read the table and put the contents in a jList and jTextarea, with formatting. When I started writing code to update or add a new record, I ran into the problem.
I apologize if this is a bit long.
Anybody have an idea what I'm missing or doing wrong?
BTW, this is one of my 2 fav sites for good, usable Java answers.
UPDATE:
Got an idea from old co-worker, the original database may have been copied from an original Access97 db. to a 2000 db. I had used 2013 Repair and Compact to make "new" 2002 and 2013 db's. Access must retain '97 type even when doing what I did. So, I created a new 2013 dummy db to test, and UCanAccess will report resultset as updatable. I will try to recreate the record data of the current db in a new database file, and see if that works. I'm hoping this is the problem, since UCanAccess doesn't support updatability with Access97 db's. I'll let ya'll know what I find.
Thanks.
I had used 2013 Repair and Compact to make "new" 2002 and 2013 db's. Access must retain '97 type even when doing what I did. So, I created a new 2013 dummy db to test, and UCanAccess will report resultset as updatable.
The "Compact and Repair Database" feature in Access does not change the database file version. If you have (what you suspect to be) an older-version database file then you should use the "Save Database As" feature under "File > Save & Publish" * to convert the database file to a newer version.
* (... at least that's where it is in Access 2010.)
Well, after a nice weekend of eating brats and drinking good beer at Germanfest, I finally got things working. I decided to scrap the MS Access db and put the 472 records in a SQLite db. With that, I was able to get PreparedStatements to work to display the records in a jList and JTextArea, add a new record and update a couple fields in an existing record within the same run of the test application. Did it both as a command line run GUI and from NetBeans 8.0, so I think my problems are solved. After a couple of summer projects get done, I'll get back to re-writing the original VB app using Java.
Thanks Gord, and everyone here.
I am making a GUI and I need to update one column called "OCCURRENCES" whenever a patient needs help. I am using Netbeans (Java). For some reason I am not getting any errors. But My table does not Update. The executeUpdate is returning '0'. I have close all my result set statements and prepared statements at the end of the 'try', 'catch'.Also any other updates like updating from textfields, insertion of new patient and deleting patient from a table is working fine; just having problem with updating this column which initial value I have set to be zero whenever an occurrence happens I would like to call this method to increment value on column. I'm just learning to use sqlite, and I am really confuse please help here is the part of the code I am having problems with, Also it reaches the JOPtionPane message successfully.
try
{
conn = javaConnect.ConnectDB();//Returns Connection
PreparedStatement pst = conn.prepareStatement("UPDATE PEMs SET OCCURRENCES = ? "//1
+ "WHERE ROOM = ?");//2
pst.setInt(1, 1);
pst.setInt(2,1);
pst.executeUpdate();
int updated=pst.executeUpdate(); // get count to see if anything was updated
System.out.println("OCC" + updated);
JOptionPane.showMessageDialog(null, "SUCCESSFULL OCCURRENCE");
}
catch (Exception e){
JOptionPane.showMessageDialog(null, "Error UpdateOccurence :" + e);
e.printStackTrace();`enter code here`
}finally {
try{
rs.close(); pst.close(); }
catch(Exception e) { } }
i have a server that backup the db and send me every time the db...
btw bc i don't want every time send 50mb of db i did a small program with something like
delete from table where timestamp < ?
get the last timestamp of the db and save it for the next backup
in that way i can send only the newest data (few kb instead 50mb)
now i want make another program for merge the different backups ...
i'm "stucked" on the insert part...
public static void merge(String toMerge) {
Connection c, c2 = null;
Statement stmt, stmt2 = null;
try {
Class.forName("org.sqlite.JDBC");
c = DriverManager.getConnection("jdbc:sqlite:merge.db");
System.out.println("Opened merge.db database successfully");
c.setAutoCommit(false);
stmt = c.createStatement();
c2 = DriverManager.getConnection("jdbc:sqlite:" + toMerge);
System.out.println("Opened " + toMerge + " database successfully");
stmt2 = c2.createStatement();
ResultSet rs = stmt2.executeQuery("SELECT * FROM messages;");
String sql;
while (rs.next()) {
sql = "INSERT INTO messages";
stmt.executeUpdate(sql);
}
rs.close();
stmt2.close();
c2.close();
stmt.close();
c.commit();
c.close();
} catch (Exception e) {
System.err.println(e.getClass().getName() + ": " + e.getMessage());
System.exit(0);
}
System.out.println("Operation done successfully");
}
i was thinking on open 2 db... 1 have a standard name "merge.db" (in that way i can merge 2+ db) and the other is the one to merge...
for use this method i open 2 connection (1 for each db) and read every line from db2 and insert in the new db... but here i have a few problem
the db have lots of cols so i need to use 200 getInt/String/Float
i have NULL value
i have a lot of rows
so if i use this method it require a lot of vars and time for make the insert query...
(for now i'm writing this method but if there is a simpler way for do it is better... i was thinking make a class with all the vars and use it for create the sql insert.. in that way i can use the same function for different tables (just need to extend the class for other class))
edit
in the table i have blob real int string values (29 cols in total)
If you had two tables in the same database, you could use a statement like this:
INSERT INTO messages1 SELECT * FROM messages2
When you have two different database files, you can ATTACH one to the other:
ATTACH DATABASE '...' AS toMerge
and then access it by prefixing the table name with the database name:
INSERT INTO messages SELECT * FROM toMerge.messages
I have a web application which is based on SQL Server 2012, and I use Java to update data in the database. (Windows Server 2008, JSP, Tomcat7, Java7)
The relevant code is as follows:
public static synchronized int execute(String dsName, String packageAndFunction, List fields) {
// prepare insertStr
String executeStr = buildStatement(dsName, packageAndFunction, null, fields);
dbConn = DBConnection.getInstance();
Connection conn = dbConn.getConnection();
CallableStatement stmt = null;
int result = RESULT_FAILED;
try {
stmt = conn.prepareCall(executeStr);
// fill statement parameters (each ?)
fillStatement(stmt, fields);
stmt.execute();
result = stmt.getInt(fields.size());
} catch(SQLException e) {
Log.getInstance().write("Exception on executeGeneral (" + packageAndFunction + ") " + e.toString());
} finally {
try {
stmt.close();
dbConn.returnConnection(conn);
} catch(SQLException e) {
Log.getInstance().write("Exception on executeGeneral (" + packageAndFunction + ") " + e.toString());
}
}
return result;
}
About 90% of the time, the code works great. The rest of the time there is some kind of lock on the table which will disappear by itself in perhaps half an hour or so. The lock prevents even simple SELECT queries on the table from executing (in SQL Server Management Studio). In severe cases it has prevented the entire application from working.
I had an idea to use stmt.executeUpdate() instead of stmt.execute(), but I have tried to research this and I do not see any evidence that using stmt.execute() for updating causes locks.
Can anyone help?
Thanks!
It's difficult to diagnose with that code. The next time that it happens, pull up your activity monitor on the SQL server and see what sql command is holding the lock.
I'm using the H2 database in my Java project (embedded mode).
On my computer at home everything works, the connection can be established, but on all other computers I always receive the following error:
org.h2.jdbc.JdbcSQLException: Table "CUSTOMERS" not found; SQL
statement: SELECT * FROM CUSTOMERS [42102-162]
I'm sure, that within the DB everything is alright, it should be something with the connection.
But even if I import the h2-1.3.162.jar file, the error still remains.
String dbClass = "org.h2.Driver";
String dbDriver = "jdbc:h2:~/cc";
String user = "user1";
String pass = "test1";
private Connection conn = null;
private Statement stmt = null;
private ResultSet rs = null;
public void connect() {
boolean done = false;
//load driver
try {
Class.forName(dbClass).newInstance();
System.out.println("driver loaded"); // This is shown in the Compiler
} catch (Exception ex) {
System.out.println("error while loading driver");
System.err.println(ex);
}
// Connection
try {
conn = DriverManager.getConnection(dbDriver, user, pass);
System.out.println("connected"); // This is shown in the Compiler
done = true;
} catch (SQLException ex) {
System.out.println("SQLException: " + ex.getMessage());
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
}
}
public Vector select() {
data = new Vector();
try {
stmt = conn.createStatement();
rs = stmt.executeQuery("SELECT * FROM CUSTOMERS");
while (rs.next()) {
Vector row = new Vector();
row.add(rs.getInt("id"));
row.add(rs.getString("fname"));
row.add(rs.getString("lname"));
row.add(rs.getString("street"));
row.add(rs.getString("city"));
row.add(rs.getString("zip"));
row.add(rs.getString("state"));
row.add(rs.getString("phone"));
row.add(rs.getString("birthday"));
row.add(rs.getString("email"));
row.add(rs.getInt("code"));
data.add(row);
}
rs.close();
stmt.close();
} catch (SQLException ex) {
System.out.println("error while selecting"); // I receive this error
System.err.println(ex);
}
return data;
}
The problem isn't with your connection as you'd receive an exception well before then if it was failing to connect to the database. The exception is pretty clear about what the issue is, as well - it can't find the CUSTOMERS table. That could be because the table doesn't exist at all, or the connection is pointing at the wrong database; try putting in the full schema information of the table, rather than just its name, and see if that works.
I'm sure, that within the DB everything is alright, it should be
something with the connection. But even if I import the h2-1.3.162.jar
file, the error still remains.
Check your assumptions. This one is incorrect.
There's nothing in the message to suggest that you couldn't connect. Either you connected to the wrong database OR the one you did connect to didn't CREATE TABLE CUSTOMERS. (Should be named CUSTOMER, not plural.)
You'll fix your error faster if you stop assuming that everything you did is correct. You should be assuming that everything is wrong.
I'd print the stack trace when you catch that exception. It'll give you more information.
Finally I figured it out!
It had nothing to do with my tables, the database couldn't be found. When trying to connect to a database which can't be found with String dbDriver = "jdbc:h2:~/cc";, a new database with the name cc (in my case) will be created (of course an empty one with no tables) and the connection is established. That's why I haven't received any connection errors.
In the next step I tried to retrieve some data from the new created empty database and therefore received the error, that my table doesn't exist.
So I changed this line: String dbDriver = "jdbc:h2:file:lib/cc"; and copied into the lib directory of my application my old database cc.h2.db.
That's all!
PS: Here is a similiar problem: h2 (embedded mode ) database files problem