Hari Krishna Hari Krishna - 24 days ago 14
Java Question

Closing of sessionFactory saves the data to HSQL

I am using HSQL as db and written the application using Hibernate. Find the following application.

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>

<session-factory>
<property name="hibernate.hbm2ddl.auto">create</property>

<!-- Database Connection settings -->
<property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
<property name="connection.url">jdbc:hsqldb:file:employeeDb;shutdown=true;hsqldb.write_delay=false;</property>
<property name="connection.username">sa</property>
<property name="connection.password"></property>

<!-- Enable the logging of all the generated SQL statements to the console -->
<property name="show_sql">true</property>

<!-- Format the generated SQL statement to make it more readable, -->
<property name="format_sql">false</property>

<!-- Hibernate will put comments inside all generated SQL statements to
hint what’s the generated SQL trying to do -->
<property name="use_sql_comments">false</property>

<!-- This property makes Hibernate generate the appropriate SQL for the
chosen database. -->
<property name="dialect">org.hibernate.dialect.HSQLDialect</property>

<!-- mappings for annotated classes -->
<mapping class="com.sample.Employee" />

</session-factory>

</hibernate-configuration>


Employee.java

package com.sample;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Employee {
@Id
private int id;
private String firstName;
private String lastName;
private String designation;
private int age;
private double salary;

public Employee(){

}

public Employee(int id, String firstName, String lastName, String designation, int age, double salary) {
super();
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.designation = designation;
this.age = age;
this.salary = salary;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public String getDesignation() {
return designation;
}

public void setDesignation(String designation) {
this.designation = designation;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public double getSalary() {
return salary;
}

public void setSalary(double salary) {
this.salary = salary;
}

}


TestEmployee.java

package com.sample;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class TestEmployee {

/* Step 1: Create session factory */
private static SessionFactory getSessionFactory() {

SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();

return sessionFactory;
}

public static void main(String args[]) {
Employee emp1 = new Employee(1, "Hari Krishna", "Gurram", "Senior Software Developer", 26, 80000);
Employee emp2 = new Employee(2, "Shreyas", "Desai", "Team Manager", 35, 150000);
Employee emp3 = new Employee(3, "Piyush", "Rai", "Senior Software Developer", 26, 100000);
Employee emp4 = new Employee(4, "Maruti", "Borker", "Software Developer", 26, 60000);

SessionFactory sessionFactory = getSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(emp1);
session.save(emp2);
session.save(emp3);
session.save(emp4);
session.flush();
session.getTransaction().commit();

session.close();
//sessionFactory.close();

}
}


When I un comment the line 'sessionFactory.close()' in the file 'TestEmployee.java' application saves the data perfectly. But when I comment the line 'sessionFactory.close()', my data is not getting saved. Why do I need to close the sessionFactory? Is there any way that I can persist the data without closing sessionFactory?

Find the stack trace

INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@a22cb6a] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
Hibernate: create table Employee (id integer not null, age integer not null, designation varchar(255), firstName varchar(255), lastName varchar(255), salary double not null, primary key (id))
Nov 09, 2016 6:22:08 PM org.hibernate.tool.schema.internal.ExceptionHandlerLoggedImpl handleException
WARN: GenerationTarget encountered exception accepting command : Error executing DDL via JDBC Statement
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL via JDBC Statement
at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:67)
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.applySqlString(AbstractSchemaMigrator.java:524)
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.applySqlStrings(AbstractSchemaMigrator.java:470)
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.createTable(AbstractSchemaMigrator.java:273)
at org.hibernate.tool.schema.internal.GroupedSchemaMigratorImpl.performTablesMigration(GroupedSchemaMigratorImpl.java:71)
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.performMigration(AbstractSchemaMigrator.java:203)
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.doMigration(AbstractSchemaMigrator.java:110)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:177)
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:66)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:309)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:445)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:710)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:726)
at com.sample.TestEmployee.<clinit>(TestEmployee.java:8)
Caused by: java.sql.SQLException: Table already exists: EMPLOYEE in statement [create table Employee]
at org.hsqldb.jdbc.Util.sqlException(Unknown Source)
at org.hsqldb.jdbc.jdbcStatement.fetchResult(Unknown Source)
at org.hsqldb.jdbc.jdbcStatement.execute(Unknown Source)
at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:54)
... 13 more

Hibernate: insert into Employee (age, designation, firstName, lastName, salary, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into Employee (age, designation, firstName, lastName, salary, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into Employee (age, designation, firstName, lastName, salary, id) values (?, ?, ?, ?, ?, ?)
Hibernate: insert into Employee (age, designation, firstName, lastName, salary, id) values (?, ?, ?, ?, ?, ?)
Nov 09, 2016 6:22:08 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop
INFO: HHH10001008: Cleaning up connection pool [jdbc:hsqldb:file:employeeDb;shutdown=true;hsqldb.write_delay=false;]

Answer

As your comments clarified the situation, this is normal behaviour for HSQLDB. It will store all shanged from workfiles to persistent log file (due to shutdown=true).In order for it to work, you need to shutdown the factory before application terminates. To automate this process simply use shutdown hook Runtime.addShutdownHook(Thread) like this

Runtime.getRuntime().addShutdownHook(new Thread(){
    public void run(){

       //CLOSE SESSION FACTORY HERE
     }
});

So basicly, your changes were persisted in your case, but you could not see them from the outside of the application as they were not restored when you boot up HSQLDB again in different process (eg from build in db viewer or Eclipse IDE db tools)

Comments