ORMLite异常:java.sql.SQLException:已请求ResultSet

问题描述 投票:2回答:1

在我们的一个Java应用程序中,我们有一个SQLite DB,多个线程读写同一个DB(不同的表)。但是,这些多线程使用相同的数据库连接对象(ORMLite的DaoManager.createDao())。

每当执行一些insert / update语句时,我们都会随机获取此SQLException(Resultset已请求)。下面是一个这样的实例的堆栈跟踪。

java.sql.SQLException: Unable to run insert stmt on object ABCD-164: INSERT INTO `pos_order` (`bill_number` ,`order_status` ,`order_type` ,`payment_mode` ,`reference_bill_number` ,`table_selected` ,`sub_total` ,`discountable_sub_total` ,`total` ,`total_discount` ,`discount_type` ,`discount_value` ,`total_tax` ,`service_charge` ,`service_tax` ,`vat` ,`delivery_charge` ,`packaging_charge` ,`amount_paid` ,`waiter` ,`delivery_boy` ,`order_source` ,`delivery_source` ,`card_type` ,`card_name` ,`client_creation_time` ,`client_updation_time` ,`order_comment` ,`customer_feedback` ,`is_deleted` ,`payment_status` ,`pos_outlet_id` ,`is_sync` ,`delivery_status` ,`shipment_id` ,`response_code` ,`delivery_time` ,`custom_packaging_charge_enable` ,`custom_delivery_charge_enable` ,`receipt_printed` ,`total_person` ,`order_origin` ,`json` ,`oo_system_id` ,`pre_order` ,`pre_order_time` ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
    at com.j256.ormlite.misc.SqlExceptionUtil.create(SqlExceptionUtil.java:22)
    at com.j256.ormlite.stmt.mapped.MappedCreate.insert(MappedCreate.java:135)
    at com.j256.ormlite.stmt.StatementExecutor.create(StatementExecutor.java:450)
    at com.j256.ormlite.dao.BaseDaoImpl.create(BaseDaoImpl.java:310)
    at com.j256.ormlite.dao.BaseDaoImpl.createOrUpdate(BaseDaoImpl.java:336)
    at com.limetray.pos.dbmanagers.implementations.PosOrderDaoImpl.insert(PosOrderDaoImpl.java:50)
    at com.limetray.pos.controllers.BillingSectionController.lambda$10(BillingSectionController.java:808)
    at com.limetray.pos.utilities.SingleTaskExecutor$1.call(SingleTaskExecutor.java:37)
    at javafx.concurrent.Task$TaskCallable.call(Unknown Source)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.sql.SQLException: ResultSet already requested
    at org.sqlite.jdbc3.JDBC3Statement.getResultSet(JDBC3Statement.java:136)
    at org.sqlite.jdbc3.JDBC3PreparedStatement.executeQuery(JDBC3PreparedStatement.java:69)
    at org.sqlite.jdbc3.JDBC3DatabaseMetaData.getGeneratedKeys(JDBC3DatabaseMetaData.java:1796)
    at org.sqlite.jdbc3.JDBC3Statement.getGeneratedKeys(JDBC3Statement.java:346)
    at com.j256.ormlite.jdbc.JdbcDatabaseConnection.insert(JdbcDatabaseConnection.java:173)
    at com.j256.ormlite.stmt.mapped.MappedCreate.insert(MappedCreate.java:91)
    ... 13 more

任何帮助将非常感激。谢谢。

java sqlite ormlite
1个回答
3
投票

在我们的一个Java应用程序中,我们有一个SQLite DB,多个线程读写同一个DB(不同的表)。

使用SQLite数据库,您一次只能有一个连接。数据库具有内部锁定,可确保没有两个线程同时使用相同的连接,但这并不能阻止DAO允许多个线程导致您遇到的问题。

Caused by: java.sql.SQLException: ResultSet already requested

在您的情况下,因为多个线程使用相同的连接,当一个线程在已经被问到我的另一个线程的连接上请求结果时,会抛出此异常。他们的查询不正确地被交错。

重要的是要意识到这与底层数据库无关。 Sqlite有自己的锁,可以阻止多个线程的并发访问。但在这种情况下,我们遇到使用相同连接的多个线程的问题。

现在,ORMLite没有提供与底层数据库的ConnectionSource单一连接的synchronized,因此您必须自己进行外部锁定。您可以扩展JdbcSingleConnectionSource class并使用ReentrantLock来强制执行控件。也许是这样的:

public class LockedJdbcSingleConnectionSource extends JdbcSingleConnectionSource {

    private final ReentrantLock lock = new ReentrantLock();

    // called from JdbcSingleConnectionSource.getReadOnlyConnection() ...
    public DatabaseConnection getReadWriteConnection() {
        lock.lock();
        return super.getReadWriteConnection();
    }

    public void releaseConnection(DatabaseConnection connection) {
        super.releaseConnection(connection);
        lock.unlock();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.