sqlite编码问题
最近遇到了一个XX的需求,就是我用java从后端拿到最近数据同步到前台给PD用,PD只要GBK格式的。操作系统是win7,数据库是sqlite3。看起来很简单,分分钟的事情。
1.编码格式转换 prepareStatement.setString(1,newString("什么东西".getBytes("gbk"),"utf-8")); publicbyte[]getBytes(Charsetcharset)使用给定的charset将此String编码到byte序列,并将结果存储到新的byte数组。 publicString(byte[]bytes,Charsetcharset)通过使用指定的charset解码指定的byte数组,构造一个新的String。 我发现在这里无论是如何进行转码,入库到sqlite,无一例外的全是乱码。
在控制台打印的是这么一堆东西。
库里面是这么一堆东西,结果没有一个是正确的。命令行的默认编码是936(gbk的),这样放到PB里面才是正确的。
我怀疑是不是编译环境编码不对,换成gbk,utf-8。都不好用。 我在本机搭了一个简易的PD环境,连库,检索。全乱码。 第一种方式不行。
2.修改jdbc驱动
刚开始是这个版本。看了下源码。 在prepareStatement.setString()这一步并不进行转码。 在excuteUpdate()才做了处理
也就是说无论你setString里面传的什么东西,通通不灵,全给你用utf-8转换到byte数组里面。 问题找到,修改重新打包。在自己运行,不行,乱码。放在别人机器上,解决。然后开始比对环境我32位,他64。好的。 到这里应该解决了吧。没有,线上说必须用32位的。 在改,下一步是不是就该改jdk的东西了。感觉蛋疼。这个路先不走了。换条路。 3.使用odbc驱动
也可以,不论jdk是64的还是32的,也不用关心jdbc驱动,而且现在做的项目是部在win7上。 但问题又来了,我这里面使用的是多线程读写操作。一直会报SQLLOGICERROR,然后就卡着不动了。在网上找了篇文章,才发现。Sqlite的锁机制。
在SQLite中,锁和事务是紧密联系的。为了有效地使用事务,需要了解一些关于如何加锁的知识。 如果一个连接想要写数据库,它必须首先获得一个保留锁。一个数据库上同时只能有一个保留锁。保留锁可以与共享锁共存,保留锁是写数据库的第1阶段。保留锁即不阻止其它拥有共享锁的连接继续读数据库,也不阻止其它连接获得新的共享锁。一旦一个连接获得了保留锁,它就可以开始处理数据库修改操作了,尽管这些修改只能在缓冲区中进行,而不是实际地写到磁盘。对读出内容所做的修改保存在内存缓冲区中。当连接想要提交修改(或事务)时,需要将保留锁提升为排它锁。为了得到排它锁,还必须首先将保留锁提升为未决锁。获得未决锁之后,其它连接就不能再获得新的共享锁了,但已经拥有共享锁的连接仍然可以继续正常读数据库。此时,拥有未决锁的连接等待其它拥有共享锁的连接完成工作并释放其共享锁。一旦所有其它共享锁都被释放,拥有未决锁的连接就可以将其锁提升至排它锁,此时就可以自由地对数据库进行修改了。所有以前对缓冲区所做的修改都会被写到数据库文件。 事务的种类SQLite有三种不同的事务,使用不同的锁状态。事务可以开始于:DEFERRED、MMEDIATE或EXCLUSIVE。事务类型在BEGIN命令中指定:BEGIN[DEFERRED|IMMEDIATE|EXCLUSIVE]TRANSACTION;一个DEFERRED事务不获取任何锁(直到它需要锁的时候),BEGIN语句本身也不会做什么事情——它开始于UNLOCK状态。默认情况下就是这样的,如果仅仅用BEGIN开始一个事务,那么事务就是DEFERRED的,同时它不会获取任何锁;当对数据库进行第一次读操作时,它会获取SHARED锁;同样,当进行第一次写操作时,它会获取RESERVED锁。由BEGIN开始的IMMEDIATE事务会尝试获取RESERVED锁。如果成功,BEGINIMMEDIATE保证没有别的连接可以写数据库。但是,别的连接可以对数据库进行读操作;但是,RESERVED锁会阻止其它连接的BEGINIMMEDIATE或者BEGINEXCLUSIVE命令,当其它连接执行上述命令时,会返回SQLITE_BUSY错误。这时你就可以对数据库进行修改操作了,但是你还不能提交,当你COMMIT时,会返回SQLITE_BUSY错误,这意味着还有其它的读事务没有完成,得等它们执行完后才能提交事务。EXCLUSIVE事务会试着获取对数据库的EXCLUSIVE锁。这与IMMEDIATE类似,但是一旦成功,EXCLUSIVE事务保证没有其它的连接,所以就可对数据库进行读写操作了。上节那个例子的问题在于两个连接最终都想写数据库,但是它们都没有放弃各自原来的锁最终,SHARED锁导致了问题的出现。如果两个连接都以BEGINIMMEDIATE开始事务,那么死锁就不会发生。在这种情况下,在同一时刻只能有一个连接进入BEGINIMMEDIATE,其它的连接就得等待。BEGINIMMEDIATE和BEGINEXCLUSIVE通常被写事务使用。就像同步机制一样,它防止了死锁的产生。基本的准则是:如果你正在使用的数据库没有其它的连接,用BEGIN就足够了。但是,如果你使用的数据库有其它的连接也会对数据库进行写操作,就得使用BEGINIMMEDIATE或BEGINEXCLUSIVE开始你的事务。事务的生命周期有一些关于代码和事务的问题需要关注。首先需要知道哪个对象运行在哪个事务之下。另一个问题是持续时间——一个事务何时开始,何时结束,从哪一点开始影响其它连接?第一个问题与API直接关联,第二个与SQL的一般概念及SQLite的特殊实现关联。一个连接(connection)可以包含多个语句(statement),而且每个连接有一个与数据库关联的B-tree和一个pager。Pager在连接中起着很重要的作用,因为它管理事务、锁、内存缓冲以及负责崩溃恢复(crashrecovery)。当你进行数据库写操作时,记住最重要的一件事:在任何时候,只在一个事务下执行一个连接。这回答了第一个问题。关于第二个问题,一般来说,一个事务的生命周期和语句差不多,你也可以手动结束它。默认情况下,事务自动提交,当然你也可以通过BEGIN..COMMIT手动提交。接下来的问题是事务如何与锁关联。锁的状态大多数情况下,锁的生命周期在事务的生命周期之中。它们不一定同时开始,但总时同时结束。当你结束一个事务时,也会释放它相关的锁。或者说,锁直到事务结束或系统崩溃时才会释放。如果系统在事务没有结束的情况下崩溃,那么下一个访问数据库的连接会处理这种情况。读事务我们先来看看SELECT语句执行时锁的状态变化过程,非常简单:一个连接执行SELECT语句,触发一个事务,从UNLOCKED到SHARED,当事务COMMIT时,又回到UNLOCKED,就这么简单。那么,当你运行两个语句时会发生什么呢?这时如何加锁呢?这依赖于你是否运行在自动提交状态。考虑下面的例子(为了简单,这里用了伪码):db=open('foods.db')db.exec('BEGIN')db.exec('SELECT*FROMepisodes')db.exec('COMMIT')db.close()由于显式地使用了BEGIN和COMMIT,两个SELECT命令在一个事务下执行。第一个exec()执行时,连接处于SHARED,然后第二个exec()执行。当事务提交时,连接又从SHARED回到UNLOCKED状态,状态变化如下: UNLOCKED→PENDING→SHARED→UNLOCKED如果没有BEGIN和COMMIT两行,两个SELECT都运行于自动提交状态,状态变化如下: 这篇翻译自:http://www.cnblogs.com/cxjchen/p/3153553.html 摘过来的 然后我默默的改成了单线程。就这样。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- ReactNative Demo - NavigationView 使用
- swift中的文件操作
- c# – 无法在我的查询中添加User-Defined-Data Type参数
- Oracle函数-单行函数-字符单行函数
- c – 如果打开设备,QSerialPort会导致程序停止(无限循环?)
- ruby-on-rails-3 – rails 3机架中间件问题,未定义方法`每个
- [转]XML::Parser perl module is required for intltool错误
- Ruby围绕方法定义中的参数括起来
- c – 返回对象存储在哪里?
- PostgreSQL的Storage(2)-file 和 smgr