- 浏览: 73487 次
文章分类
最新评论
-
kevinflynn:
...
ThreadLocal 源码分析 -
kevinflynn:
[url=aaaa][/url]
ThreadLocal 源码分析 -
kevinflynn:
学习到了 感谢楼主。
ThreadLocal 源码分析
目前在网上看到有如下两种获取 connection 的办法:
第一种:
//3.创建Driver对象
Driver driver = (Driver)Class.forName(driverName).newInstance();
Properties info = new Properties(); //driver的connect方法中需要一个Properties型的参数
info.put("user", user);
info.put("password", password);
//4.使用driver的connect方法获取数据库连接
Connection conn = driver.connect(url, info);
第二种:
/3.加载驱动程序,即将数据库厂商提供的Driver接口实现类加载进内存;
// 该驱动类中的静态代码块包含有注册驱动的程序,在加载类时将被执行
Class.forName(driverName);
//4.通过DriverManager类的静态方法getConnection获取数据连接
Connection conn = DriverManager.getConnection(url, user, password);
总结来说就算一种是通过 Dirver 来获取,一种是通过 DriverManager 来获取.
然后进一步调试源码,发现通过 DriverManager 来获取,最终还是转换成通过 Driver 来获取,如下:
所以,这两者本质上是一个东西.
那下面在说下 connection 是什么?或者说 connection 有哪些东西?
说这个之前,我们先看下 Driver 是啥?或者说我们先自定义一个 Driver.
public class SSDriver implements Driver {
private final String URL_PREFIX = "jdbc:smalldb";
static SSDriver ssDriver;
static {
ssDriver = new SSDriver();
try {
DriverManager.registerDriver(ssDriver);
} catch (SQLException e) {
e.printStackTrace();
}
}
// 解析 url
// 例:jdbc:mysql://192.168.0.105:3306/shgb_fz?useUnicode=true&characterEncoding=UTF8&
// autoReconnect=true&zeroDateTimeBehavior=convertToNull
private Properties parse(String url, Properties info) throws SQLException {
Properties props = (Properties)info.clone();
if(!acceptsURL(url)){
return props;
}
int idx1 = url.indexOf(':', 5); // search after "jdbc:"
int idx2 = url.indexOf('?');
if(idx1 > 0){
String dbPath = (idx2 > 0) ? url.substring(idx1 + 1, idx2) : url.substring(idx1 + 1);
props.setProperty("dbpath", dbPath);
}
if(idx2 > 0){
String propsString = url.substring(idx2 + 1);
StringTokenizer tok = new StringTokenizer(propsString, ";");
while(tok.hasMoreTokens()){
String keyValue = tok.nextToken().trim();
if(keyValue.length() > 0){
idx1 = keyValue.indexOf('=');
if(idx1 > 0){
String key = keyValue.substring(0, idx1).toLowerCase().trim();
String value = keyValue.substring(idx1 + 1).trim();
props.put(key, value);
}else{
throw SmallDBException.create(Language.CUSTOM_MESSAGE, "Missing equal in property:" + keyValue);
}
}
}
}
return props;
}
public Connection connect(String url, Properties info) throws SQLException {
if(acceptsURL(url)){
return new SSConnection(parse(url, info));
}
return null;
}
// 检查该 URL 是否合法.
public boolean acceptsURL(String url) throws SQLException {
return url.startsWith(URL_PREFIX);
}
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
Properties props = parse(url, info);
DriverPropertyInfo[] driverInfos = new DriverPropertyInfo[1];
driverInfos[0] = new DriverPropertyInfo("dbpath", props.getProperty("dbpath"));
return driverInfos;
}
public int getMajorVersion() {
return 0;
}
public int getMinorVersion() {
return 20;
}
public boolean jdbcCompliant() {
return true;
}
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
}
然后看下 connection 中做了那些事:
/**
* Connection 应该包含哪些信息了?
* 1.连接那个数据库
* 2.事务隔离级别
* 3.是否自动提交
*/
public class SSConnection implements Connection {
private boolean autoCommit = true;
private Database database;
int isolationLevel = TRANSACTION_READ_COMMITTED;
// 待提交的集合.
private List commitPages = new ArrayList();
// 事务开启时间
private long transactionTime;
private final SSDatabaseMetadata metadata;
private int holdability;
final Logger log;
public SSConnection(Properties props) throws SQLException {
SmallDBException.setLanguage(props.get("locale"));
log = new Logger();
String name = props.getProperty("dbpath");
boolean create = "true".equals(props.getProperty("create"));
database = Database.getDatabase(name, this, create);
metadata = new SSDatabaseMetaData(this);
}
SSConnection(SSConnection conn){
database = conn.database;
metadata = conn.metadata;
log = conn.log;
}
Database getDatabase(boolean returnNull) throws SQLException{
testClosedConnection();
// 打开数据的含义就是读文件.
// 数据库数据的存储本质上也是文件的存储.
if(!returnNull && database == null) throw SmallDBException.create(Language.DB_NOTCONNECTED);
return database;
}
final void testClosedConnection() throws SQLException{
if(isClosed()) throw SmallDBException.create(Language.CONNECTION_CLOSED);
}
Object getMonitor(){
return this;
}
@Override
public Statement createStatement() throws SQLException {
return new SSStatement(this);
}
@Override
public PreparedStatement prepareStatement(String sql) throws SQLException {
return SSPreparedStatement(this, sql);
}
@Override
public CallableStatement prepareCall(String sql) throws SQLException {
return SSCallableStatement(this, sql);
}
@Override
public String nativeSQL(String sql) throws SQLException {
return sql;
}
@Override
public void setAutoCommit(boolean autoCommit) throws SQLException {
if(log.isLogging()) log.println("AutoCommit:"+autoCommit);
if(this.autoCommit != autoCommit){
// 先提交,后改变
commit();
this.autoCommit = autoCommit;
}
}
@Override
public boolean getAutoCommit() throws SQLException {
return autoCommit;
}
/**
* Add a page for later commit or rollback.
*/
void add(TransactionStep storePage) throws SQLException{
testClosedConnection();
synchronized(getMonitor()){
commitPages.add(storePage);
}
}
// TODO 待定
@Override
public void commit() throws SQLException {
log.println("Commit");
testClosedConnection();
synchronized(getMonitor()){
try{
int count = commitPages.size();
for(int i=0; i<count; i++){
TransactionStep page = (TransactionStep)commitPages.get(i);
page.commit();
}
for(int i=0; i<count; i++){
TransactionStep page = (TransactionStep)commitPages.get(i);
page.freeLock();
}
commitPages.clear();
transactionTime = System.currentTimeMillis();
}catch(Throwable e){
rollback();
throw SmallDBException.createFromException(e);
}
}
}
/**
* Discard all changes of a file because it was deleted.
*/
void rollbackFile(RandomAccessFile raFile) throws SQLException{
testClosedConnection();
// remove the all commits that point to this table
synchronized(getMonitor()){
for(int i = commitPages.size() - 1; i >= 0; i--){
TransactionStep page = (TransactionStep)commitPages.get(i);
if(page.raFile == raFile){
page.rollback();
page.freeLock();
}
}
}
}
void rollback(int savepoint) throws SQLException{
testClosedConnection();
synchronized(getMonitor()){
for(int i = commitPages.size() - 1; i >= savepoint; i--){
TransactionStep page = (TransactionStep)commitPages.remove(i);
page.rollback();
page.freeLock();
}
}
}
@Override
public void rollback() throws SQLException {
log.println("Rollback");
testClosedConnection();
synchronized(getMonitor()){
int count = commitPages.size();
for(int i=0; i<count; i++){
TransactionStep page = (TransactionStep)commitPages.get(i);
page.rollback();
page.freeLock();
}
commitPages.clear();
transactionTime = System.currentTimeMillis();
}
}
// 关闭前回滚
@Override
public void close() throws SQLException {
rollback();
database = null;
commitPages = null;
Database.closeConnection(this);
}
@Override
public boolean isClosed() throws SQLException {
return null == commitPages;
}
@Override
public DatabaseMetaData getMetaData() throws SQLException {
return metadata;
}
@Override
public void setReadOnly(boolean readOnly) throws SQLException {
//TODO Connection ReadOnly implementing
}
@Override
public boolean isReadOnly() throws SQLException {
return false;
}
@Override
public void setCatalog(String catalog) throws SQLException {
testClosedConnection();
database = Database.getDatabase(catalog, this, false);
}
@Override
public String getCatalog() throws SQLException {
if(database == null)
return "";
return database.getName();
}
@Override
public void setTransactionIsolation(int level) throws SQLException {
if(!metadata.supportsTransactionIsolationLevel(level)) {
throw SmallSQLException.create(Language.ISOLATION_UNKNOWN, String.valueOf(level));
}
isolationLevel = level;
}
@Override
public int getTransactionIsolation() throws SQLException {
return isolationLevel;
}
@Override
public SQLWarning getWarnings() throws SQLException {
return null;
}
@Override
public void clearWarnings() throws SQLException {
}
@Override
public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
return new SSStatement( this, resultSetType, resultSetConcurrency);
}
@Override
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
return new SSPreparedStatement(this, sql, resultSetType, resultSetConcurrency);
}
@Override
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
return new SSCallableStatement(this, sql, resultSetType, resultSetConcurrency);
}
@Override
public Map<String, Class<?>> getTypeMap() throws SQLException {
return null;
}
@Override
public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
}
@Override
public void setHoldability(int holdability) throws SQLException {
this.holdability = holdability;
}
@Override
public int getHoldability() throws SQLException {
return holdability;
}
int getSavepoint() throws SQLException{
testClosedConnection();
return commitPages.size(); // the call is atomic, that it need not be synchronized
}
@Override
public Savepoint setSavepoint() throws SQLException {
return new SSSavepoint(getSavepoint(), null, transactionTime);;
}
@Override
public Savepoint setSavepoint(String name) throws SQLException {
return new SSSavepoint(getSavepoint(), name, transactionTime);
}
@Override
public void rollback(Savepoint savepoint) throws SQLException {
}
@Override
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
}
@Override
public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
return null;
}
@Override
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
return null;
}
@Override
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
return null;
}
@Override
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
return null;
}
@Override
public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
return null;
}
@Override
public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
return null;
}
@Override
public Clob createClob() throws SQLException {
return null;
}
@Override
public Blob createBlob() throws SQLException {
return null;
}
@Override
public NClob createNClob() throws SQLException {
return null;
}
@Override
public SQLXML createSQLXML() throws SQLException {
return null;
}
@Override
public boolean isValid(int timeout) throws SQLException {
return false;
}
@Override
public void setClientInfo(String name, String value) throws SQLClientInfoException {
}
@Override
public void setClientInfo(Properties properties) throws SQLClientInfoException {
}
@Override
public String getClientInfo(String name) throws SQLException {
return null;
}
@Override
public Properties getClientInfo() throws SQLException {
return null;
}
public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
return null;
}
public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
return null;
}
public void setSchema(String schema) throws SQLException {
}
public String getSchema() throws SQLException {
return null;
}
public void abort(Executor executor) throws SQLException {
}
public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
}
public int getNetworkTimeout() throws SQLException {
return 0;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
}
第一种:
//3.创建Driver对象
Driver driver = (Driver)Class.forName(driverName).newInstance();
Properties info = new Properties(); //driver的connect方法中需要一个Properties型的参数
info.put("user", user);
info.put("password", password);
//4.使用driver的connect方法获取数据库连接
Connection conn = driver.connect(url, info);
第二种:
/3.加载驱动程序,即将数据库厂商提供的Driver接口实现类加载进内存;
// 该驱动类中的静态代码块包含有注册驱动的程序,在加载类时将被执行
Class.forName(driverName);
//4.通过DriverManager类的静态方法getConnection获取数据连接
Connection conn = DriverManager.getConnection(url, user, password);
总结来说就算一种是通过 Dirver 来获取,一种是通过 DriverManager 来获取.
然后进一步调试源码,发现通过 DriverManager 来获取,最终还是转换成通过 Driver 来获取,如下:
所以,这两者本质上是一个东西.
那下面在说下 connection 是什么?或者说 connection 有哪些东西?
说这个之前,我们先看下 Driver 是啥?或者说我们先自定义一个 Driver.
public class SSDriver implements Driver {
private final String URL_PREFIX = "jdbc:smalldb";
static SSDriver ssDriver;
static {
ssDriver = new SSDriver();
try {
DriverManager.registerDriver(ssDriver);
} catch (SQLException e) {
e.printStackTrace();
}
}
// 解析 url
// 例:jdbc:mysql://192.168.0.105:3306/shgb_fz?useUnicode=true&characterEncoding=UTF8&
// autoReconnect=true&zeroDateTimeBehavior=convertToNull
private Properties parse(String url, Properties info) throws SQLException {
Properties props = (Properties)info.clone();
if(!acceptsURL(url)){
return props;
}
int idx1 = url.indexOf(':', 5); // search after "jdbc:"
int idx2 = url.indexOf('?');
if(idx1 > 0){
String dbPath = (idx2 > 0) ? url.substring(idx1 + 1, idx2) : url.substring(idx1 + 1);
props.setProperty("dbpath", dbPath);
}
if(idx2 > 0){
String propsString = url.substring(idx2 + 1);
StringTokenizer tok = new StringTokenizer(propsString, ";");
while(tok.hasMoreTokens()){
String keyValue = tok.nextToken().trim();
if(keyValue.length() > 0){
idx1 = keyValue.indexOf('=');
if(idx1 > 0){
String key = keyValue.substring(0, idx1).toLowerCase().trim();
String value = keyValue.substring(idx1 + 1).trim();
props.put(key, value);
}else{
throw SmallDBException.create(Language.CUSTOM_MESSAGE, "Missing equal in property:" + keyValue);
}
}
}
}
return props;
}
public Connection connect(String url, Properties info) throws SQLException {
if(acceptsURL(url)){
return new SSConnection(parse(url, info));
}
return null;
}
// 检查该 URL 是否合法.
public boolean acceptsURL(String url) throws SQLException {
return url.startsWith(URL_PREFIX);
}
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
Properties props = parse(url, info);
DriverPropertyInfo[] driverInfos = new DriverPropertyInfo[1];
driverInfos[0] = new DriverPropertyInfo("dbpath", props.getProperty("dbpath"));
return driverInfos;
}
public int getMajorVersion() {
return 0;
}
public int getMinorVersion() {
return 20;
}
public boolean jdbcCompliant() {
return true;
}
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
}
然后看下 connection 中做了那些事:
/**
* Connection 应该包含哪些信息了?
* 1.连接那个数据库
* 2.事务隔离级别
* 3.是否自动提交
*/
public class SSConnection implements Connection {
private boolean autoCommit = true;
private Database database;
int isolationLevel = TRANSACTION_READ_COMMITTED;
// 待提交的集合.
private List commitPages = new ArrayList();
// 事务开启时间
private long transactionTime;
private final SSDatabaseMetadata metadata;
private int holdability;
final Logger log;
public SSConnection(Properties props) throws SQLException {
SmallDBException.setLanguage(props.get("locale"));
log = new Logger();
String name = props.getProperty("dbpath");
boolean create = "true".equals(props.getProperty("create"));
database = Database.getDatabase(name, this, create);
metadata = new SSDatabaseMetaData(this);
}
SSConnection(SSConnection conn){
database = conn.database;
metadata = conn.metadata;
log = conn.log;
}
Database getDatabase(boolean returnNull) throws SQLException{
testClosedConnection();
// 打开数据的含义就是读文件.
// 数据库数据的存储本质上也是文件的存储.
if(!returnNull && database == null) throw SmallDBException.create(Language.DB_NOTCONNECTED);
return database;
}
final void testClosedConnection() throws SQLException{
if(isClosed()) throw SmallDBException.create(Language.CONNECTION_CLOSED);
}
Object getMonitor(){
return this;
}
@Override
public Statement createStatement() throws SQLException {
return new SSStatement(this);
}
@Override
public PreparedStatement prepareStatement(String sql) throws SQLException {
return SSPreparedStatement(this, sql);
}
@Override
public CallableStatement prepareCall(String sql) throws SQLException {
return SSCallableStatement(this, sql);
}
@Override
public String nativeSQL(String sql) throws SQLException {
return sql;
}
@Override
public void setAutoCommit(boolean autoCommit) throws SQLException {
if(log.isLogging()) log.println("AutoCommit:"+autoCommit);
if(this.autoCommit != autoCommit){
// 先提交,后改变
commit();
this.autoCommit = autoCommit;
}
}
@Override
public boolean getAutoCommit() throws SQLException {
return autoCommit;
}
/**
* Add a page for later commit or rollback.
*/
void add(TransactionStep storePage) throws SQLException{
testClosedConnection();
synchronized(getMonitor()){
commitPages.add(storePage);
}
}
// TODO 待定
@Override
public void commit() throws SQLException {
log.println("Commit");
testClosedConnection();
synchronized(getMonitor()){
try{
int count = commitPages.size();
for(int i=0; i<count; i++){
TransactionStep page = (TransactionStep)commitPages.get(i);
page.commit();
}
for(int i=0; i<count; i++){
TransactionStep page = (TransactionStep)commitPages.get(i);
page.freeLock();
}
commitPages.clear();
transactionTime = System.currentTimeMillis();
}catch(Throwable e){
rollback();
throw SmallDBException.createFromException(e);
}
}
}
/**
* Discard all changes of a file because it was deleted.
*/
void rollbackFile(RandomAccessFile raFile) throws SQLException{
testClosedConnection();
// remove the all commits that point to this table
synchronized(getMonitor()){
for(int i = commitPages.size() - 1; i >= 0; i--){
TransactionStep page = (TransactionStep)commitPages.get(i);
if(page.raFile == raFile){
page.rollback();
page.freeLock();
}
}
}
}
void rollback(int savepoint) throws SQLException{
testClosedConnection();
synchronized(getMonitor()){
for(int i = commitPages.size() - 1; i >= savepoint; i--){
TransactionStep page = (TransactionStep)commitPages.remove(i);
page.rollback();
page.freeLock();
}
}
}
@Override
public void rollback() throws SQLException {
log.println("Rollback");
testClosedConnection();
synchronized(getMonitor()){
int count = commitPages.size();
for(int i=0; i<count; i++){
TransactionStep page = (TransactionStep)commitPages.get(i);
page.rollback();
page.freeLock();
}
commitPages.clear();
transactionTime = System.currentTimeMillis();
}
}
// 关闭前回滚
@Override
public void close() throws SQLException {
rollback();
database = null;
commitPages = null;
Database.closeConnection(this);
}
@Override
public boolean isClosed() throws SQLException {
return null == commitPages;
}
@Override
public DatabaseMetaData getMetaData() throws SQLException {
return metadata;
}
@Override
public void setReadOnly(boolean readOnly) throws SQLException {
//TODO Connection ReadOnly implementing
}
@Override
public boolean isReadOnly() throws SQLException {
return false;
}
@Override
public void setCatalog(String catalog) throws SQLException {
testClosedConnection();
database = Database.getDatabase(catalog, this, false);
}
@Override
public String getCatalog() throws SQLException {
if(database == null)
return "";
return database.getName();
}
@Override
public void setTransactionIsolation(int level) throws SQLException {
if(!metadata.supportsTransactionIsolationLevel(level)) {
throw SmallSQLException.create(Language.ISOLATION_UNKNOWN, String.valueOf(level));
}
isolationLevel = level;
}
@Override
public int getTransactionIsolation() throws SQLException {
return isolationLevel;
}
@Override
public SQLWarning getWarnings() throws SQLException {
return null;
}
@Override
public void clearWarnings() throws SQLException {
}
@Override
public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
return new SSStatement( this, resultSetType, resultSetConcurrency);
}
@Override
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
return new SSPreparedStatement(this, sql, resultSetType, resultSetConcurrency);
}
@Override
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
return new SSCallableStatement(this, sql, resultSetType, resultSetConcurrency);
}
@Override
public Map<String, Class<?>> getTypeMap() throws SQLException {
return null;
}
@Override
public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
}
@Override
public void setHoldability(int holdability) throws SQLException {
this.holdability = holdability;
}
@Override
public int getHoldability() throws SQLException {
return holdability;
}
int getSavepoint() throws SQLException{
testClosedConnection();
return commitPages.size(); // the call is atomic, that it need not be synchronized
}
@Override
public Savepoint setSavepoint() throws SQLException {
return new SSSavepoint(getSavepoint(), null, transactionTime);;
}
@Override
public Savepoint setSavepoint(String name) throws SQLException {
return new SSSavepoint(getSavepoint(), name, transactionTime);
}
@Override
public void rollback(Savepoint savepoint) throws SQLException {
}
@Override
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
}
@Override
public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
return null;
}
@Override
public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
return null;
}
@Override
public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
return null;
}
@Override
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
return null;
}
@Override
public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
return null;
}
@Override
public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
return null;
}
@Override
public Clob createClob() throws SQLException {
return null;
}
@Override
public Blob createBlob() throws SQLException {
return null;
}
@Override
public NClob createNClob() throws SQLException {
return null;
}
@Override
public SQLXML createSQLXML() throws SQLException {
return null;
}
@Override
public boolean isValid(int timeout) throws SQLException {
return false;
}
@Override
public void setClientInfo(String name, String value) throws SQLClientInfoException {
}
@Override
public void setClientInfo(Properties properties) throws SQLClientInfoException {
}
@Override
public String getClientInfo(String name) throws SQLException {
return null;
}
@Override
public Properties getClientInfo() throws SQLException {
return null;
}
public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
return null;
}
public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
return null;
}
public void setSchema(String schema) throws SQLException {
}
public String getSchema() throws SQLException {
return null;
}
public void abort(Executor executor) throws SQLException {
}
public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
}
public int getNetworkTimeout() throws SQLException {
return 0;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
}
相关推荐
对于这样的问题,解决的办法就是keep single sqlite connection,保持单个SqliteOpenHelper实例,同时对所有数据库操作的方法添加synchronized关键字。完美解决sqlite的 database locked 或者是 error 5: database ...
对于这样的问题,解决的办法就是keep single sqlite connection,保持单个SqliteOpenHelper实例,同时对所有数据库操作的方法添加synchronized关键字。完美解决sqlite的 database locked 或者是 error 5: database ...
从本质上来说就是调用者(程序员)和实现者(数据库厂商)之间的协议。JDBC的实现由数据库厂商以驱动程序的形式提供。JDBC API 使得开发人员可以使用纯Java的方式来连接数据库,并进行操作。 ODBC:基于C语言的...
书中深入剖析了ado.net的本质,探索了类、接口、属性和方法的工作原理,同时还为其他数据访问api(包括oledb,ado,odbc和jdbc)的程序员,提供了有价值的参考材料。本书适合具有一定数据库基础的开发人员阅读,也可...
MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的...
可以说,这两种方法的实质还是CGI的编程思想,只是在程序中引入了ADO对象而已。 第四、五种暂取名叫“SOM的DHTML法”。这两种方法要求在VI6.0的环境下,利用微软提出的脚本对象模型(Script Object Model)和DHTML...
bb8-rusqlite 此板条箱提供了一个连接管理器,您可以将其与一起使用以提供连接池。...rusqlite允许使用Connection::open_in_memory系列方法创建内存数据库。 内存中SQLite数据库是按连接的,这意味着拥有
使用Python Flask和MongoDB的基本Web应用程序的模板 这是使用Flask和MongoDB的基本Web应用程序的模板。 它使用Flask-Login进行身份验证,使用Flask-Pymongo进行数据库... 它本质上与存储库中的代码相同,但也使用Font
不论什么Java应用服务器实质都是内置了某个版本的JDK。因此掌握 JDK是学好Java的第一步。最主流的JDK是Sun公司发布的JDK,除了Sun之外,还有很多公司和组织都开发了自己的JDK,例如IBM公司开发的JDK,BEA公司的...
什么是“框架”?CI 为什么能被称为框架? “开源”商业模式。 CI 的某些不足(是的,它并不完美)。 1.1 CodeIgniter 能为你做什么? 如果你已经是一位 PHPer,开发过 PHP 应用,CodeIgniter 将会帮助你做得更...
期间看了下Aysnc.js,是用于多个要返回回调函数的事件,将这些事件有序的组织起来,最后只返回一个回调函数,并没有改变异步的本质,而是将多个异步整合为一个异步,从而满足写程序的需求。 错误示范 获取数据库中的...
什么是将行为封装,Command 是最好的说明. 设计模式之 Observer(观察者) 介绍如何使用 Java API 提供的现成 Observer 设计模式之 Iterator(迭代器) 这个模式已经被整合入Java的Collection.在大多数场合下无需自己...
数据集介绍:提供什么是 ADO.NET 数据集、如何对它们进行类型化或非类型化、它们的用途及结构的概述。 用于创建数据集的 Visual Studio 工具:描述 Visual Studio 提供了哪些允许创建数据集的功能,以及在何时选用...
7.7.2 什么是实例变量(Instance Variable) 177 7.8 this关键字:指向对象自己的引用 177 7.8.1 发现问题:当实例变量和局部变量重名 177 7.8.2 经常深藏不露的this关键字 178 7.8.3 在方法中调用方法 179 7.9...
7.7.2 什么是实例变量(Instance Variable) 177 7.8 this关键字:指向对象自己的引用 177 7.8.1 发现问题:当实例变量和局部变量重名 177 7.8.2 经常深藏不露的this关键字 178 7.8.3 在方法中调用方法 179 7.9...
6.3.1对象变量的实质是什么220 6.3.2对象下面的秘密222 6.3.3重述对象关键字226 6.3.4 Class_Terminate事件228 第7章事件、多态性与继承性232 7.1事件232 7.1.1事件和代码复用性232 7.1.2事件的语法233 7.1.3第一个...
6.3.1对象变量的实质是什么220 6.3.2对象下面的秘密222 6.3.3重述对象关键字226 6.3.4 Class_Terminate事件228 第7章事件、多态性与继承性232 7.1事件232 7.1.1事件和代码复用性232 7.1.2事件的语法233 7.1.3第一个...
14.1 什么时候使用XML 14.2 XML简介 14.2.1 XML的优点 14.2.2 格式良好的XML 14.2.3 XML命名空间 14.2.4 XML架构 14.3 基于流的XML处理 14.3.1 写XML文件 14.3.2 读取XML文件 14.4 内存中的XML...