Я написал простой Java-код, который пытается хранить файлы в базе данных hsqldb. Все, что он делает, это считывать файлы из определенного каталога и помещать их в БД. Он однопоточный, но я использую объединенные соединения из apache commons.dbcp, чтобы позже справляться с многопоточным доступом.Почему следующий простой кусочек Java-кода использует объединенные соединения из блока commons.dbcp?
Проблема в том, что код блокируется после чтения нескольких файлов.
Пожалуйста, найдите ниже всего исходного кода.
Program.java
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.commons.dbcp.ConnectionFactory;
import org.apache.commons.dbcp.DriverManagerConnectionFactory;
import org.apache.commons.dbcp.PoolableConnectionFactory;
import org.apache.commons.dbcp.PoolingDataSource;
import org.apache.commons.pool.KeyedObjectPoolFactory;
import org.apache.commons.pool.impl.GenericKeyedObjectPoolFactory;
import org.apache.commons.pool.impl.GenericObjectPool;
public class Program {
public static DataSource getPoolingDataSource(String driverClass, String url, String user, String password) throws ClassNotFoundException {
Class.forName(driverClass);
ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(url, user, password);
GenericObjectPool connectionPool = new GenericObjectPool();
KeyedObjectPoolFactory stmtPool = new GenericKeyedObjectPoolFactory(null);
new PoolableConnectionFactory(connectionFactory, connectionPool, stmtPool, null, false, true);
return new PoolingDataSource(connectionPool);
}
public static void main(String[] args) throws ClassNotFoundException, SQLException, IOException, InterruptedException {
String root = args.length == 0 ? "c:/Work/java/ntxdb" : args[0];
Runtime run = Runtime.getRuntime();
Process pr = run.exec("cmd /c del /s/q c:\\tmp\\file.db*");
pr.waitFor();
DataSource ds = getPoolingDataSource("org.hsqldb.jdbcDriver", "jdbc:hsqldb:file:c:/tmp/file.db", "sa", "");
HsqldbFileStorage fs = new HsqldbFileStorage(ds);
putFiles(fs, new File(root));
}
private static void putFiles(HsqldbFileStorage fs, File parent) throws IOException, SQLException {
for (File child : parent.listFiles()) {
if (child.isDirectory()) {
putFiles(fs, child);
} else {
System.out.println(child.getCanonicalPath());
fs.put(child);
}
}
}
}
HsqldbFileStorage.java
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import javax.sql.DataSource;
public class HsqldbFileStorage {
private static final String SET_SQL = "MERGE INTO test" +
" USING (VALUES ?, CAST(? AS BLOB)) I (name, data)" +
" ON (test.name=I.name)" +
" WHEN MATCHED THEN UPDATE SET test.data = I.data" +
" WHEN NOT MATCHED THEN INSERT (name, data) VALUES (I.name, I.data)";
private DataSource m_dataSource;
public HsqldbFileStorage(DataSource dataSource) throws SQLException {
super();
m_dataSource = dataSource;
Connection c = dataSource.getConnection();
c.createStatement().execute("Create Cached Table IF NOT EXISTS test (name VARCHAR(256), data BLOB(10M));");
}
public void put(File file) throws IOException, SQLException {
put(file.getCanonicalPath(), file);
}
public void put(String name, File file) throws IOException, SQLException {
InputStream is = new BufferedInputStream(new FileInputStream(file));
try {
put(name, is);
} finally {
is.close();
}
}
public void put(String name, InputStream data) throws SQLException, IOException {
PreparedStatement set = m_dataSource.getConnection().prepareStatement(SET_SQL);
try {
set.setString(1, name);
set.setBinaryStream(2, data);
set.executeUpdate();
} finally {
set.close();
}
}
}
Код зависит от фонда-ГСБД 1.4, обыкновенные бассейн 1,6 и HSQLDB 2.2.9
Запуск этого в каталоге проекта должен поместить 62 файла в БД (у меня много re файлы там, чем два вышеупомянутых исходных файла), распечатывая строку для каждого файла.
К сожалению, блоки на восьмой файл со следующей трассировки стека:
at java.lang.Object.wait(Object.java:-1)
at java.lang.Object.wait(Object.java:485)
at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1118)
at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:106)
at HsqldbFileStorage.put(HsqldbFileStorage.java:41)
at HsqldbFileStorage.put(HsqldbFileStorage.java:34)
at HsqldbFileStorage.put(HsqldbFileStorage.java:28)
at Program.putFiles(Program.java:42)
at Program.putFiles(Program.java:39)
at Program.putFiles(Program.java:39)
at Program.main(Program.java:33)
Что я делаю не так?
Глупо меня, конечно. Спасибо. – mark