Pregunta

I'm using hsqldb to create cached tables and indexed tables. The data being stored has pretty high frequency so I need to use a connection pool. Also because there is a lot of data I do not call checkpoint on every commit, but rather expect the data to be flushed after 50,000 rows are inserted. So the thing is that I can see the .data file is growing but when I connect with hsqldb client I don't see the tables and the data. So I had 2 simple tests, one inserted single row and one inserted 60,000 rows to new table. In both cases I couldn't see the result in any hsqldb client. (Note that I use shutdown=true) So when I add checkpoint after each commit, it solve the problem. Also if specify in the connection string to use log, it solves the problem (I don't want the log in production though). Also not using pooled connection solved the problem and last is using pooled data source and explicitly close it before shutdown.

So I guess that some connections in the connection pool are not being closed, preventing from the db to somehow commit the changes and make them available for the client. But then, why couldn't I see the result even with 60,000 rows? I also would expect the pool to be closed automatically... What am I doing wrong? What is happening behind the scene?

The code to get the data source looks like this:

Class.forName("org.hsqldb.jdbcDriver");
String url = "jdbc:hsqldb:" + m_dbRoot + dbName + "/db" + ";hsqldb.log_data=false;shutdown=true;hsqldb.nio_data_file=false";
ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(url, user, password);
GenericObjectPool connectionPool = new GenericObjectPool();
KeyedObjectPoolFactory stmtPool = new GenericKeyedObjectPoolFactory(null);
new PoolableConnectionFactory(connectionFactory, connectionPool, stmtPool, null, false, true);
DataSource ds = new PoolingDataSource(connectionPool);

And I'm using this Pooled data source to create table:

Connection c = m_dataSource.getConnection();
Statement st = c.createStatement();
String script = String.format("CREATE CACHED TABLE IF NOT EXISTS %s (id %s NOT NULL, entity %s NOT NULL, PRIMARY KEY (id));", m_tableName, m_idGenerator.getIdType(), TABLE_ENTITY_TYPE);
st.execute(script);
c.close;
st.close();

And insert rows:

Connection c = m_dataSource.getConnection();
c.setAutoCommit(false);
Statement  stmt = c.prepareStatement(m_sqlInsert);
stmt.setObject(1, id);
stmt.setBinaryStream(2, Serializer.Helper.serialize(m_serializer, entity));
stmt.executeUpdate();
stmt.close();
stmt = null;
c.commit();
c.close();
stmt.close();

so the above seems to add data but it cannot be seen. When I explicitly called connectionPool.close(); Then and only then I could see the result. I also tried to use JDBCDataSource and it worked as well. So what is going on? And what is the right way to do this?

¿Fue útil?

Solución

Your method of accessing the database from outside your application process is simply wrong.

Only one java process is supposed to connect to the file: database.

In order to achieve your aim, launch an HSQLDB server within your application, using exactly the same JDBC URL. Then connect to this server from the external client.

See the Guide:

http://www.hsqldb.org/doc/2.0/guide/listeners-chapt.html#lsc_app_start

Update: The OP commented that the external client was used after the application had stopped. Because you have turned the log off with hsqldb.log_data=false, nothing is persisted permanently. You need to perform an explicit CHECKPOINT or SHUTDOWN when your application completes its work. You cannot rely on shutdown=true at all, even without connection pooling.

See the Guide:

http://www.hsqldb.org/doc/2.0/guide/deployment-chapt.html#dec_bulk_operations

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top