Even after closing the connection, data still exists in h2 database tables - java

As I surfed in many H2 database tutorials it was given that by default, closing the last connection to a database closes the database. For an in-memory database, this means the content is lost.
I have created Employee1 table, inserted records and closed the connection. But still I am able to retrieve the Employee1 data if I reconnect the same db after sometime. Why the data still existing?
package connection;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Connector {
static Connection conn = null;
static Statement stmt = null;
public static void main(String[] args) {
System.out.println("Welcome!");
Connector connector = new Connector();
connector.createConnection();
connector.createTable("Employee2");
connector.insertRecord("Employee2");
connector.readRecord("Employee2");
connector.readRecord("Employee1"); //Employee1 Table which is created in previous execution but still it reads the data
connector.closeConnection();
}
public void createConnection() {
try {
System.out.println("Creating connection");
// STEP 1: Register JDBC driver
Class.forName("org.h2.Driver");
// STEP 2: Open a connection
System.out.println("Connecting to database...");
conn = DriverManager.getConnection("jdbc:h2:mem/db1", "sa", "");
} catch (SQLException se) {
// Handle errors for JDBC
se.printStackTrace();
} catch (Exception e) {
// Handle errors for Class.forName
e.printStackTrace();
}
}
public void createTable(String tableName) {
try {
// STEP 3: Execute a query
System.out.println("Creating table in given database with the name of ..." + tableName);
stmt = conn.createStatement();
String sql = "CREATE TABLE " + tableName + "(id INTEGER not NULL, " + " first VARCHAR(255), "
+ " last VARCHAR(255), " + " age INTEGER, " + " PRIMARY KEY ( id ))";
stmt.executeUpdate(sql);
System.out.println("Created table in given database...");
} catch (SQLException se) {
// Handle errors for JDBC
se.printStackTrace();
} catch (Exception e) {
// Handle errors for Class.forName
e.printStackTrace();
}
}
public void insertRecord(String tableName) {
try {
// STEP 3: Execute a query
stmt = conn.createStatement();
String sql = "INSERT INTO " + tableName + " VALUES (500, 'Zara', 'Ali', 18)";
stmt.executeUpdate(sql);
sql = "INSERT INTO " + tableName + " VALUES (501, 'Mahnaz', 'Fatma', 25)";
stmt.executeUpdate(sql);
sql = "INSERT INTO " + tableName + " VALUES (502, 'Zaid', 'Khan', 30)";
stmt.executeUpdate(sql);
sql = "INSERT INTO " + tableName + " VALUES(503, 'Sumit', 'Mittal', 28)";
stmt.executeUpdate(sql);
System.out.println("Inserted records into the table...");
} catch (SQLException se) {
// Handle errors for JDBC
se.printStackTrace();
} catch (Exception e) {
// Handle errors for Class.forName
e.printStackTrace();
}
}
public void readRecord(String tableName) {
try {
System.out.println("Reading data from "+tableName);
stmt = conn.createStatement();
String sql = "SELECT id, first, last, age FROM " + tableName;
ResultSet rs = stmt.executeQuery(sql);
// STEP 4: Extract data from result set
while (rs.next()) {
// Retrieve by column name
int id = rs.getInt("id");
int age = rs.getInt("age");
String first = rs.getString("first");
String last = rs.getString("last");
// Display values
System.out.print("ID: " + id);
System.out.print(", Age: " + age);
System.out.print(", First: " + first);
System.out.println(", Last: " + last);
}
// STEP 5: Clean-up environment
rs.close();
} catch (SQLException se) {
// Handle errors for JDBC
se.printStackTrace();
} catch (Exception e) {
// Handle errors for Class.forName
e.printStackTrace();
} finally {
// finally block used to close resources
try {
if (stmt != null)
stmt.close();
} catch (SQLException se2) {
} // nothing we can do
} // end try
}
public void closeConnection() {
try {
if (conn != null) {
conn.close();
System.out.println("Connection Closed..");
}
} catch (SQLException se) {
se.printStackTrace();
} // end finally try
}
}
Output of above program:
Welcome!
Creating connection
Connecting to database...
Creating table in given database with the name of ...Employee2
Created table in given database...
Inserted records into the table...
Reading data from Employee2
ID: 500, Age: 18, First: Zara, Last: Ali
ID: 501, Age: 25, First: Mahnaz, Last: Fatma
ID: 502, Age: 30, First: Zaid, Last: Khan
ID: 503, Age: 28, First: Sumit, Last: Mittal
Reading data from Employee1
ID: 400, Age: 18, First: freeze, Last: Ali
ID: 401, Age: 25, First: dora, Last: Fatma
ID: 402, Age: 30, First: xer, Last: Khan
ID: 403, Age: 28, First: kilo, Last: Mittal
Connection Closed..

As you can see here
jdbc:h2:mem/db1
Connects to a local database file with a relative path of mem/db1 so the data still exists because it's saved id a file.
For an in memory database the connection String should be:
jdbc:h2:mem:db1
Notice the difference between / and :

Related

how to insert username and check user name is duplicate in database

public static ArrayList<User_Database> getUsername() {
ArrayList<User_Database> list_Username = new ArrayList<User_Database>();
try {
Class.forName(driver);
String sql = "SELECT user_name FROM users";
Connection connect = DriverManager.getConnection(url, user, password);
Statement state = connect.createStatement();
ResultSet rs = state.executeQuery(sql);
while (rs.next()) {
String user_name = rs.getString("user_name");
User_Database userDB = new User_Database(user_name);
list_Username.add(userDB);
System.out.printf(" %s \n", user_name);
}
rs.close();
} catch (SQLException e) {
System.out.println(e.getMessage());
} catch (ClassNotFoundException e) {
System.out.println(e.getMessage());
}
return list_Username;
}
public static void createNewUser(User_Database us) {
getAllUser();
try {
Class.forName(driver);
Connection connect = DriverManager.getConnection(url, user, password);
Statement state = connect.createStatement();
String sql = "INSERT INTO users VALUES (0, '" + us.user_name + "' , '" + us.user_password + "' , '"
+ us.email + "') ";
if (getAllUser().equals(us.user_name)) {
System.out.println("Username not available");
} else {
state.executeUpdate(sql);
state.close();
System.out.println("Insert Database Success");
}
} catch (SQLException e) {
System.out.println(e.getMessage());
} catch (ClassNotFoundException e) {
System.out.println(e.getMessage());
}
}
You're calling getAllUser() and I don't know what is does. Let's suppose that you want to call getUsername() instead, which is the method that you present here and that returns all the usernames that you have in your DB in an ArrayList<User_Database>.
When you do if (getAllUser().equals(us.user_name)) you're trying to compare an ArrayList with a String, which is wrong. Please, find the correction to your code bellow:
public static void createNewUser(User_Database us) {
try {
Class.forName(driver);
Connection connect = DriverManager.getConnection(url, user, password);
Statement state = connect.createStatement();
String sql = "INSERT INTO users VALUES (0, '" + us.user_name + "' , '" + us.user_password + "' , '"
+ us.email + "') ";
boolean isUnique = true;
for(User_Database user: getUsername()) {
if(user.user_name.equals(us.user_name)) {
isUnique = false;
break;
}
}
if (!isUnique) {
System.out.println("Username not available");
} else {
state.executeUpdate(sql);
state.close();
System.out.println("Insert Database Success");
}
} catch (SQLException e) {
System.out.println(e.getMessage());
} catch (ClassNotFoundException e) {
System.out.println(e.getMessage());
}
}
Other notes
Close your statement outside the try catch block, e.g. inside a finally block. This way you ensure that even in the occurence of an exception it will be closed.
Don't forget to close the connection too.
Try to not directly insert the information given by users in your queries, since it can lead to serious problems in your DB (e.g., SQL Injection). Try to see this and use PreparedStatement instead.
Another important consideration:
Since you're checking for the uniqueness of usernames, an ArrayList might not be the best (in terms of performance) to achieve what you want, since you have to go through it when you want to check if there is already a username in your DB or not (O(N)). Instead, try to get all usernames and put them in a HashSet. With set, you just have to try to add the username to it; you will get a true if username is unique or false if it is already in the set (O(1)).
Hope it helped.

java sqlite - Error: function not yet implemented for SQLite

I created the following class in java to make using SQLite easier when I code.
import java.sql.*;
public class Dbm {
//We want to use the connection througout the whole class so it is
//provided as a class level private variable
private Connection c = null;
//This constructor openes or creates the database provided by the arguement
//NameOfDatabase
public Dbm(String NameOfDatabase){
try {
//Database is checked for in project folder, if doesnt exist then creates database
c = DriverManager.getConnection("jdbc:sqlite:" + NameOfDatabase);
} catch ( Exception e ) {
System.err.println( e.getClass().getName() + ": " + e.getMessage() );
System.exit(0);
}
System.out.println("Opened database successfully");
}
public void CloseDB(){
try{
c.close();
System.out.println("Closed Database Successfull");
}
catch (Exception e){
System.out.println("Failed to close Database due to error: " + e.getMessage());
}
}
public void ExecuteNoReturnQuery(String SqlCommand){
//creates a statment to execute the query
try{
Statement stmt = null;
stmt = c.createStatement();
stmt.executeUpdate(SqlCommand);
stmt.close();
System.out.println("Sql query executed successfull");
} catch (Exception e){
System.out.println("Failed to execute query due to error: " + e.getMessage());
}
}
// this method returns a ResultSet for a query which can be iterated throughd
public ResultSet ExecuteSqlQueryWithReturn(String SqlCommand){
try{
Statement stmt = null;
stmt = c.createStatement();
ResultSet rs = stmt.executeQuery(SqlCommand);
return rs;
}catch (Exception e){
System.out.println("An Error has ocured while executing this query" + e.getMessage());
}
return null;
}
}
Here is the main code in the program
import java.sql.*;
public class InstaText {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Dbm db = new Dbm("people.db");
ResultSet rs = db.ExecuteSqlQueryWithReturn("select * from people;");
try{
String name = "";
int age = 0;
String address = "";
while (rs.isLast() == false){
name = rs.getString("name");
age = rs.getInt("age");
address = rs.getString("address");
System.out.println("Name is " + name +" age is " + age + " Address is " + address);
rs.next();
}
}catch (Exception e ){
System.out.println("Error: " + e.getMessage());
}
db.CloseDB();
}
}
But when I execute it I get the following output:
Opened database successfully
Error: function not yet implemented for SQLite
Closed Database Successfull
So how do I solve the Error "Error: function not yet implemented for SQLite"?
I am running the NetBeans Ide with the latest JDBC on mac os sierra.
Edit: Here is the output after adding e.printstacktrace(); in the catch block:
Opened database successfully
Error: function not yet implemented for SQLite
java.sql.SQLException: function not yet implemented for SQLite
Closed Database Successfull
at org.sqlite.jdbc3.JDBC3ResultSet.isLast(JDBC3ResultSet.java:155)
at instatext.InstaText.main(InstaText.java:24)
The problem is not your select query but the isLast() method you are using on the ResultSet instance to retrieve the result. Try the next() method, it should work :
while (rs.next()){
name = rs.getString("name");
age = rs.getInt("age");
address = rs.getString("address");
System.out.println("Name is " + name +" age is " + age + " Address is " + address);
rs.next();
}
You can read here :
https://github.com/bonitasoft/bonita-connector-database/issues/1
that with SQLLite, you may have some limitations with the isLast() method :
According to JDBC documentation
(http://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html)
calls to isLast() and first() methods are forbidden if the result set
type is TYPE_FORWARD_ONLY (e.g SQLite).

Create and connect to an SQL database using Java

I have a Java program that connects to an SQL database, and can write and read from it, however, in order to use the program, I first have to open Workbench, and run an SQL query in there.
Obviously, this isn't a great solution, so how can I create and connect to a database all within the Java code?
I've searched online, including the Oracle site, but can't see to get it.
Below is my code.
public Connection ConnectNow() //Connect to the database
{
try
{
Class.forName("com.mysql.jdbc.Driver").newInstance();
}
catch (Exception ex)
{
System.out.println("Error 1");
ex.getMessage();
}
final String dbURL = "jdbc:mysql://localhost/game1"; //replace 'assignex' with database name
Connection conn = null;
try
{
conn = DriverManager.getConnection(dbURL, "root", "password");
System.out.println("\n== Connection Successful ==");
return conn;
}
catch (SQLException ex)
{
System.out.println("Error 2");
System.out.println("SQLException: " + ex.getMessage());
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
return null;
}
}
public void CreateDatabase()
{
try
{
Connection conn = ConnectNow();
Statement stmt = conn.createStatement();
String createDatabase = "CREATE DATABASE IF NOT EXISTS game1"; //creates database
stmt.executeUpdate(createDatabase);
conn.close();
stmt.close();
System.out.println("<< Database created successfully >>");
}
catch (Exception ex)
{
System.out.println("Error 7");
ex.getMessage();
ex.printStackTrace();
}
}
public void CreateTable() //creates a table within the database
{
try
{
Connection conn = ConnectNow();
Statement stmt = conn.createStatement();
String createTable = "CREATE TABLE IF NOT EXISTS user" +
"(firstname VARCHAR(255), " + //AUTO_INCREMENT to add numbers automatically
" surname VARCHAR(255), " +
" day INTEGER, " +
" month INTEGER, " +
" year INTEGER, " +
" username VARCHAR(255) NOT NULL, " +
" password VARCHAR(255), " +
" PRIMARY KEY (username))";
stmt.executeUpdate(createTable);
conn.close();
stmt.close();
System.out.println("<< Table created successfully >>");
}
catch (Exception ex)
{
System.out.println("Error 6");
ex.getMessage();
ex.printStackTrace();
}
}
Presumably, it's something to do with me attempting to connect before creating the database, but I can't find the solution to implement this correctly.
Help is much appreciated.
You already answered you own question. Your connection URL (jdbc:mysql://localhost/game1) specifies the database (game1) to connect to, but that database does not exist. If you look at your Exception output is is probably telling to exactly that. Your app should NOT be creating the database. It should just be connecting to it and modifying it. You can try to set the URL to not include the database name and then just use the MySQL USE command to specify a database but that is a lot of un-nessasary work. Just do not have the app create it's database.
maybe you could try declaring your port and host separately as strings like the following and create the database then you should be okay.
`import java.sql.*;
public class Test {
public static void main(String args[]) {
Connection con;
try {
**String server = "localhost";
String port = "50000";** //generic port for DB2 jdbc
String url = "jdbc:db2://"+server+":"+port+"/sample"; String userid = ”userid";
String password = ”password";`

JDBC update using prepared statement

I am trying to update a table using Java JDBC. The method I am using does not throw any errors but the table is not updating. The create table method is below:
public static void Table()
{
Connection c = null;
Statement stmt = null;
try {
Class.forName("org.sqlite.JDBC");
c = DriverManager.getConnection("jdbc:sqlite:WalkerTechCars.db");
System.out.println("Opened database successfully");
stmt = c.createStatement();
String sql = "CREATE TABLE IF NOT EXISTS CUSTOMERS2 " +
"(PHONE TEXT PRIMARY KEY NOT NULL," +
" SURNAME TEXT NOT NULL, " +
" FIRSTNAME TEXT NOT NULL, " +
" HOME TEXT, " +
" ADDRESS TEXT, " +
" POSTCODE Text)";
stmt.executeUpdate(sql);
stmt.close();
c.close();
} catch ( Exception e ) {
System.err.println( e.getClass().getName() + ": " + e.getMessage() );
System.exit(0);
}
System.out.println("Customers2 created successfully");
}
The update method is below:
public static void updateCustomers()
{
Connection c = null;
PreparedStatement pstmt = null;
try {
Class.forName("org.sqlite.JDBC");
c = DriverManager.getConnection("jdbc:sqlite:WalkerTechCars.db");
c.setAutoCommit(false);
System.out.println("Opened database successfully");
String query = "UPDATE CUSTOMERS2 set ADDRESS = ? where PHONE = ? ";
pstmt = c.prepareStatement(query); // create a statement
pstmt.setString(1, "1"); // set input parameter 1
pstmt.setString(2, "DOES THIS WORK"); // set input parameter 2
pstmt.executeUpdate(); // execute update statement
pstmt.close();
c.close();
} catch ( Exception e ) {
System.err.println( e.getClass().getName() + ": " + e.getMessage() );
System.exit(0);
}
System.out.println("Update Completed successfully HELLO");
}
I have tried to find some clear instructions on this but cant find any. I do not really understand JDBC and prepared statement very well
When autoCommit is false (c.setAutoCommit(false);), you must manually commit the transaction...
Add...
c.commit()
After pstmt.executeUpdate();
You code also has a flaw, in that if some kind of error occurs during the preparation or execution of the statement, both the Connection and PreparedStatement could be left open, causing a resource leak
If you're using Java 7+ you can use the try-with-resources feature, for example...
try {
Class.forName("org.sqlite.JDBC");
try (Connection c = DriverManager.getConnection("jdbc:sqlite:WalkerTechCars.db")) {
c.setAutoCommit(false);
System.out.println("Opened database successfully");
String query = "UPDATE CUSTOMERS2 set ADDRESS = ? where PHONE = ? ";
try (PreparedStatement pstmt = c.prepareStatement(query)) {
pstmt.setString(1, "1"); // set input parameter 1
pstmt.setString(2, "DOES THIS WORK"); // set input parameter 2
pstmt.executeUpdate(); // execute update statement
c.commit();
}
} catch (SQLException exp) {
exp.printStackTrace();
}
} catch (ClassNotFoundException exp) {
exp.printStackTrace();
System.out.println("Failed to load driver");
}
This will ensure that regardless of how you leave the try block the resource will be closed.
You might also consider taking a look at the JDBC(TM) Database Access
Your update method will set ADDRESS to 1 if there is any row in table with PHONE = does this work.
Try to put Address in 1st Input parameter and Phone 2nd Input parameter
When a connection is created, it is in auto-commit mode.
We need to use [setAutoCommit] method only when we need to make Auto Commit false and make it manual commit after executing the query.
More details at Oracle site on JDBC Transaction.

Occasional "General error" Occurs on INSERT into POSTGRES Database from Java

I'm trying to insert a collection of data from Java into a Postgres database. Both the JVM and the database are 64-bit. Querying the database and viewing the output showed that the code correctly inserted 54 rows into the database before the JVM crashed. Five other entries returned identical errors, which I had logged to stderr before continuing execution. This is one of the errors, and they all have the same information:
Could not execute SQL insert: General error
Error code: 0
SQL State: S1000
DB Connection Status: OPEN
java.sql.SQLException: General error
at sun.jdbc.odbc.JdbcOdbc.createSQLException(Unknown Source)
at sun.jdbc.odbc.JdbcOdbc.standardError(Unknown Source)
at sun.jdbc.odbc.JdbcOdbc.SQLExecute(Unknown Source)
at sun.jdbc.odbc.JdbcOdbcPreparedStatement.execute(Unknown Source)
at sun.jdbc.odbc.JdbcOdbcPreparedStatement.executeUpdate(Unknown Source)
at shadowlandsCrawler.Database.storeAccount(Database.java:70)
at shadowlandsCrawler.ShadowlandsCrawler.main(ShadowlandsCrawler.java:82)
I went into the shell, and I was able to manually insert the erroneous data successfully. Visual inspection of the data showed nothing other than simple ASCII. I tried closing the database connection after each insert, but the results were identical to multiple inserts on one connection.
While the JVM crashing may be related to the SQL errors, I'm only concerned right now with the cause of these exceptions, not with the crash.
Here is my database class with access details obscured:
import java.sql.*;
public class Database {
static Database singletonDB;
private Connection hauntingDB;
private PreparedStatement statement;
private Database() throws SQLException, ClassNotFoundException{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
hauntingDB = DriverManager.getConnection("jdbc:odbc:HauntingAccounts", "REDACTED", "REDACTED");
String sqlCommand = "INSERT INTO \"Accounts\" (\"Title\", \"Author\", \"Story\", \"Words\") VALUES (?, ?, ?, ?);";
statement = hauntingDB.prepareStatement(sqlCommand);
}
public static Database init() throws SQLException, ClassNotFoundException{
if(singletonDB == null){
singletonDB = new Database();
}
return singletonDB;
}
public void close(){
try {
hauntingDB.close();
} catch (SQLException e) {
System.err.println("Cannot close database, or it is already closed: " + e.getMessage());
}
}
public boolean storeAccount(Story hauntingAccount) throws Exception{
boolean accountStored = false;
System.err.println("----INSERTING ENTRY----");
System.err.println("Title: " + hauntingAccount.getTitle());
System.err.println("Author: " + hauntingAccount.getAuthor());
if(hauntingAccount.getTitle().length() == 0 || hauntingAccount.getAuthor().length() == 0){
System.err.println("URL: " + hauntingAccount.getPageURL());
throw new Exception("TITLE OR AUTHOR IS EMPTY!!!");
}
try{
statement.setString(1, hauntingAccount.getTitle());
statement.setString(2, hauntingAccount.getAuthor());
statement.setString(3, hauntingAccount.getStory());
statement.setString(4, hauntingAccount.getStory().toLowerCase());
statement.executeUpdate();
System.err.println("SUCCESS!");
accountStored = true;
}
catch(SQLException e){
String dbClosed = "UNKNOWN";
try {
dbClosed = hauntingDB.isClosed() ? "CLOSED" : "OPEN";
} catch (SQLException e1) {
System.err.println("Could not get DB connection state.");
}
System.err.println("-------------------------------------------");
System.err.println("Could not execute SQL insert: " + e.getMessage());
System.err.println("Error code: " + e.getErrorCode());
System.err.println("SQL State: " + e.getSQLState());
System.err.println("DB Connection Status: " + dbClosed);
e.printStackTrace(System.err);
System.err.println("Title: " + hauntingAccount.getTitle());
System.err.println("Author: " + hauntingAccount.getAuthor());
System.err.println("Page URL: " + hauntingAccount.getPageURL());
System.err.println("-------------------------------------------");
}
finally{
try {
SQLWarning warning = statement.getWarnings();
while (warning != null) {
System.err.println("-------------------------------------------");
System.err.println("Message: " + warning.getMessage());
System.err.print("Error code: " + warning.getErrorCode());
System.err.println("SQL State: " + warning.getSQLState());
System.err.println("Title: " + hauntingAccount.getTitle());
System.err.println("Author: " + hauntingAccount.getAuthor());
System.err.println("Page URL: " + hauntingAccount.getPageURL());
System.err.println("-------------------------------------------");
warning = warning.getNextWarning();
}
} catch (SQLException e) {
// Ignore
}
}
return accountStored;
}
}

Categories

Resources