我正在进行Stock管理应用程序,它需要经常访问数据库才能查看和编辑数据。在多次重复此过程时,数据库会被锁定。
获得2错误: "数据库的SQLiteConnection对象泄露了!请修复您的应用程序以正确结束正在进行的事务,并在不再需要时关闭数据库。"
" SQLiteDatabaseLockedException:数据库被锁定(代码5):超出重试次数"
获取此错误后,需要很长时间才能完成数据库插入操作。
如何解决此问题。
public synchronized boolean insert(BeanOrderHeader orderHdrItem) throws Exception {
boolean status=false;
try {
//Create Sqlite object to insert order details
db = getSQLiteDatabase();
//Before insert delete records if already exists
deleteOrderData(db,orderHdrItem);
db.beginTransactionNonExclusive();
// db.beginTransaction();
getPaymentPreparedStatement(db,orderHdrItem);
status= true;
db.setTransactionSuccessful();
db.endTransaction();
if(orderHdrItem.isNewOrder())
mCounterProvider.updateOrderBillNumber();
} catch (Exception e) {
e.printStackTrace();
status= false;
throw new Exception("Failed to save the order. Please check the log for details");
}finally{
db.setTransactionSuccessful();
db.endTransaction();
}
return status;
}
protected SQLiteDatabase getSQLiteDatabase() {
if(myDataBase==null)
open();
if(!myDataBase.isOpen())
open();
return myDataBase;
}
public SQLiteStatement getPaymentPreparedStatement(SQLiteDatabase db,BeanOrderHeader
orderHeader) throws Exception{
ArrayList<BeanOrderPayment> orderPaymentlList=orderHeader.getOrderPaymentItems();
SQLiteStatement prep;
String insert_sql="insert into "+"order_payments "+" (" +
"order_id, "+
"payment_mode, "+
"paid_amount, "+
"card_name, "+
"card_type, "+
"card_no, "+
"name_on_card, "+
"card_expiry_month, "+
"card_expiry_year, "+
"card_approval_code, "+
"card_account_type, "+
"company_id, "+
"voucher_id, "+
"voucher_value, "+
"voucher_count, "+
"cashier_id, "+
"payment_date, " +
"payment_time "+
",id " +
",discount_id" +
",discount_code" +
",discount_name" +
",discount_description" +
",discount_price" +
",discount_is_percentage" +
",discount_is_overridable" +
",discount_amount" +
",is_repayment" +
",is_voucher_balance_returned" +
",partial_balance" +
") "+
" values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
prep=db.compileStatement(insert_sql);
int counter=0;
if(mPosOrderUtil==null)
mPosOrderUtil=new PosOrderUtil(getContext());
for (BeanOrderPayment payItem: orderPaymentlList){
prep.bindString(1, payItem.getOrderId());
prep.bindLong(2, payItem.getPaymentMode().getValue());
prep.bindDouble(3, payItem.getPaidAmount());
prep.bindString(4, payItem.getCardName());
prep.bindString(5, payItem.getCardType());
prep.bindString(6, payItem.getCardNo());
prep.bindString(7, payItem.getNameOnCard());
prep.bindLong(8, payItem.getCardExpiryMonth());
prep.bindLong(9, payItem.getCardExpiryYear());
prep.bindString(10, payItem.getCardApprovalCode());
prep.bindString(11, payItem.getAccount());
prep.bindLong(12, payItem.getCompanyId());
prep.bindLong(13, payItem.getVoucherId());
prep.bindDouble(14, payItem.getVoucherValue());
prep.bindLong(15, payItem.getVoucherCount());
prep.bindLong(16, payItem.getCashierID());
prep.bindString(17, payItem.getPaymentDate());
prep.bindString(18, payItem.getPaymentTime());
prep.bindString(19, mPosOrderUtil.appendToId(orderHeader.getOrderId(), counter++)); //Id generated from order id
BeanDiscount disc=payItem.getDiscount();
if(disc!=null){
prep.bindLong(20, disc.getId());
prep.bindString(21, disc.getCode());
prep.bindString(22, disc.getName());
prep.bindString(23, disc.getDescription());
prep.bindDouble(24, disc.getPrice());
prep.bindLong(25, getIntFromBoolean(disc.isPercentage()));
prep.bindLong(26, getIntFromBoolean(disc.isOverridable()));
prep.bindDouble(27, payItem.getPaidAmount());
}
prep.bindLong(28, getIntFromBoolean(payItem.isRepayment()));
prep.bindLong(29, getIntFromBoolean(payItem.isVoucherBalanceReturned()));
prep.bindDouble(30, payItem.getPartialBalance());
prep.executeInsert();
prep.clearBindings();
}
return prep;
}
答案 0 :(得分:2)
您需要在db操作
之后关闭SQLiteHelper类实例dbHelper.close()
答案 1 :(得分:0)
最后,我通过保留SQLiteDatabase实例的单个对象来解决问题。如果数据库结构很复杂,使用单个对象访问所有表中的数据,这样我们就可以轻松管理sq-lite数据库。
db操作后关闭数据库对象以解决数据库泄漏问题
mDatabase.close()
答案 2 :(得分:0)
此SQLiteDatabaseLockedException的另一个原因是启动一个事务,而不是在finally块中关闭它,后来尝试对DB执行某些操作。
为:
SQLiteDatabase db = this.getReadableDatabase();
db.beginTransaction();
//DO some db writing
db.setTransactionSuccessful();
db.endTransaction();
好:
SQLiteDatabase db = this.getReadableDatabase();
db.beginTransaction();
try {
//DO some db writing
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}