setReadonly(true)
概念:从这一点设置的时间点开始到这个事务结束的过程中,其他事务所提交的数据,该事务将看不见!(查询中不会出现别人在时间点a之后提交的数据)
应用场合:
如果你一次执行单条查询语句,则没有必要启用事务支持,数据库默认支持SQL执行期间的读一致性;
如果你一次执行多条查询语句,例如统计查询,报表查询,在这种场景下,多条查询SQL必须保证整体的读一致性,否则,在前条SQL查询之后,后条SQL查询之前,数据被其他用户改变,则该次整体的统计查询将会出现读数据不一致的状态,此时,应该启用事务支持。
【注意是一次执行多次查询来统计某些信息,这时为了保证数据整体的一致性,要用只读事务】
怎样设置:
对于只读查询,可以指定事务类型为readonly,即只读事务。
由于只读事务不存在数据的修改,因此数据库将会为只读事务提供一些优化手段,例如Oracle对于只读事务,不启动回滚段,不记录回滚log。
当驱动加载完毕后,接下来就是怎样去获取一个连接
Drivermanager.getConnection(url,name,password)
跟踪代码执行到以下一步
private static Connection getConnection(
String url, java.util.Properties info, ClassLoader callerCL) throws SQLException {
java.util.Vector drivers = null;
/*
* When callerCl is null, we should check the application's
* (which is invoking this class indirectly)
* classloader, so that the JDBC driver class outside rt.jar
* can be loaded from here.
*/
synchronized(DriverManager.class) {
// synchronize loading of the correct classloader.
if(callerCL == null) {
callerCL = Thread.currentThread().getContextClassLoader();
}
}
if(url == null) {
throw new SQLException("The url cannot be null", "08001");
}
println("DriverManager.getConnection(\"" + url + "\")");
if (!initialized) {
initialize();
}
synchronized (DriverManager.class){
// use the readcopy of drivers
drivers = readDrivers;
}
// Walk through the loaded drivers attempting to make a connection.
// Remember the first exception that gets raised so we can reraise it.
SQLException reason = null;
for (int i = 0; i < drivers.size(); i++) {
DriverInfo di = (DriverInfo)drivers.elementAt(i);
// If the caller does not have permission to load the driver then
// skip it.
if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {
println(" skipping: " + di);
continue;
}
try {
println(" trying " + di);
//在注册的驱动中得到相应的连接
Connection result = di.driver.connect(url, info);
if (result != null) {
// Success!
println("getConnection returning " + di);
return (result);
}
} catch (SQLException ex) {
if (reason == null) {
reason = ex;
}
}
}
// if we got here nobody could connect.
if (reason != null) {
println("getConnection failed: " + reason);
throw reason;
}
println("getConnection: no suitable driver found for "+ url);
throw new SQLException("No suitable driver found for "+ url, "08001");
}
进入com.mysql.jdbc.Driver下connect(url,info)方法NonRegisteringDriver
public java.sql.Connection connect(String url, Properties info)
throws SQLException {
if (url != null) {
if (StringUtils.startsWithIgnoreCase(url, LOADBALANCE_URL_PREFIX)) {//负载均衡的配置
return connectLoadBalanced(url, info);
} else if (StringUtils.startsWithIgnoreCase(url,
REPLICATION_URL_PREFIX)) {//复制
return connectReplicationConnection(url, info);
}
}
Properties props = null;
if ((props = parseURL(url, info)) == null) {
return null;
}
if (!"1".equals(props.getProperty(NUM_HOSTS_PROPERTY_KEY))) {
return connectFailover(url, info);
}
try {//初始化链接
Connection newConn = com.mysql.jdbc.ConnectionImpl.getInstance(
host(props), port(props), props, database(props), url);
return newConn;
} catch (SQLException sqlEx) {
// Don't wrap SQLExceptions, throw
// them un-changed.
throw sqlEx;
} catch (Exception ex) {
SQLException sqlEx = SQLError.createSQLException(Messages
.getString("NonRegisteringDriver.17") //$NON-NLS-1$
+ ex.toString()
+ Messages.getString("NonRegisteringDriver.18"), //$NON-NLS-1$
SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE, null);
sqlEx.initCause(ex);
throw sqlEx;
}
}
对com.mysql.jdbc.JDBC4Connection的初始化
protected static Connection getInstance(String hostToConnectTo,
int portToConnectTo, Properties info, String databaseToConnectTo,
String url) throws SQLException {
if (!Util.isJdbc4()) {
return new ConnectionImpl(hostToConnectTo, portToConnectTo, info,
databaseToConnectTo, url);
}
//初始化
return (Connection) Util.handleNewInstance(JDBC_4_CONNECTION_CTOR,
new Object[] {
hostToConnectTo, Integer.valueOf(portToConnectTo), info,
databaseToConnectTo, url }, null);
}
进入Jdbc4Connection的代码跟踪
protected ConnectionImpl(String hostToConnectTo, int portToConnectTo, Properties info,
String databaseToConnectTo, String url)
throws SQLException {
this.charsetToNumBytesMap = new HashMap();
this.connectionCreationTimeMillis = System.currentTimeMillis();
this.pointOfOrigin = new Throwable();
if (databaseToConnectTo == null) {
databaseToConnectTo = "";
}
// Stash away for later, used to clone this connection for Statement.cancel
// and Statement.setQueryTimeout().
//
this.origHostToConnectTo = hostToConnectTo;
this.origPortToConnectTo = portToConnectTo;
this.origDatabaseToConnectTo = databaseToConnectTo;
try {
Blob.class.getMethod("truncate", new Class[] {Long.TYPE});
this.isRunningOnJDK13 = false;
} catch (NoSuchMethodException nsme) {
this.isRunningOnJDK13 = true;
}
this.sessionCalendar = new GregorianCalendar();
this.utcCalendar = new GregorianCalendar();
this.utcCalendar.setTimeZone(TimeZone.getTimeZone("GMT"));
this.log = LogFactory.getLogger(getLogger(), LOGGER_INSTANCE_NAME, getExceptionInterceptor());
// We store this per-connection, due to static synchronization
// issues in Java's built-in TimeZone class...
this.defaultTimeZone = Util.getDefaultTimeZone();
if ("GMT".equalsIgnoreCase(this.defaultTimeZone.getID())) {
this.isClientTzUTC = true;
} else {
this.isClientTzUTC = false;
}
this.openStatements = new HashMap();
if (NonRegisteringDriver.isHostPropertiesList(hostToConnectTo)) {
Properties hostSpecificProps = NonRegisteringDriver.expandHostKeyValues(hostToConnectTo);
Enumeration<?> propertyNames = hostSpecificProps.propertyNames();
while (propertyNames.hasMoreElements()) {
String propertyName = propertyNames.nextElement().toString();
String propertyValue = hostSpecificProps.getProperty(propertyName);
info.setProperty(propertyName, propertyValue);
}
} else {
if (hostToConnectTo == null) {
this.host = "localhost";
this.hostPortPair = this.host + ":" + portToConnectTo;
} else {
this.host = hostToConnectTo;
if (hostToConnectTo.indexOf(":") == -1) {
this.hostPortPair = this.host + ":" + portToConnectTo;
} else {
this.hostPortPair = this.host;
}
}
}
this.port = portToConnectTo;
this.database = databaseToConnectTo;
this.myURL = url;
this.user = info.getProperty(NonRegisteringDriver.USER_PROPERTY_KEY);
this.password = info
.getProperty(NonRegisteringDriver.PASSWORD_PROPERTY_KEY);
if ((this.user == null) || this.user.equals("")) {
this.user = "";
}
if (this.password == null) {
this.password = "";
}
this.props = info;
initializeDriverProperties(info);
try { //获取数据库的信息
this.dbmd = getMetaData(false, false);
initializeSafeStatementInterceptors();
//======================================创建远程IO连接
createNewIO(false);
unSafeStatementInterceptors();
} catch (SQLException ex) {
cleanup(ex);
// don't clobber SQL exceptions
throw ex;
} catch (Exception ex) {
cleanup(ex);
StringBuffer mesg = new StringBuffer(128);
if (!getParanoid()) {
mesg.append("Cannot connect to MySQL server on ");
mesg.append(this.host);
mesg.append(":");
mesg.append(this.port);
mesg.append(".\n\n");
mesg.append("Make sure that there is a MySQL server ");
mesg.append("running on the machine/port you are trying ");
mesg
.append("to connect to and that the machine this software is "
+ "running on ");
mesg.append("is able to connect to this host/port "
+ "(i.e. not firewalled). ");
mesg
.append("Also make sure that the server has not been started "
+ "with the --skip-networking ");
mesg.append("flag.\n\n");
} else {
mesg.append("Unable to connect to database.");
}
SQLException sqlEx = SQLError.createSQLException(mesg.toString(),
SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE, getExceptionInterceptor());
sqlEx.initCause(ex);
throw sqlEx;
}
}
分享到:
相关推荐
MySQL Connector/J是官方提供的JDBC驱动程序,它的源代码能帮助开发者深入理解数据库连接、数据传输以及SQL语句在Java中的执行过程。 首先,我们来看看JDBC的概念。JDBC是Java平台上的一个标准接口,由Sun ...
MySQL 8 数据库驱动源码分析 MySQL 是世界上最流行的开源关系型数据库管理系统之一,而 `mysql-connector-java` 是 MySQL 官方提供的用于 Java 应用程序连接到 MySQL 数据库的 JDBC 驱动程序。在 MySQL 8 版本中,...
Java MySQL驱动源码是连接Java应用程序与MySQL数据库的关键组件,其主要实现是通过JDBC(Java Database Connectivity)接口。在Java中,JDBC提供了一组API,使得开发人员能够用标准的Java语言来访问和操作各种数据库...
关于源码分析,MySQL JDBC驱动的源代码可以提供深入理解数据库连接的工作原理、事务处理、批处理以及错误处理机制等。对于开发者来说,阅读源码有助于优化性能,解决特定问题,或者为自定义功能提供灵感。 在工具...
在“mysql-driver:mysql jdbc驱动源码阅读”这个主题中,我们将深入探讨该驱动的工作原理、关键组件以及源码分析。 1. **JDBC驱动类型**: JDBC驱动分为四种类型:Type 1、Type 2、Type 3 和 Type 4。MySQL ...
源码分析对于开发者来说是一个宝贵的学习资源,可以帮助深入理解 MySQL 的内部工作原理。通过查看源码,可以了解 MySQL 如何处理 SQL 语句、管理事务、优化查询、存储和检索数据等。此外,源码分析还能帮助开发者...
在"mysqljdbc src"中,我们探讨的是MySQL JDBC 5的源代码,这为我们提供了深入理解其内部工作原理的机会。 源代码分析通常有助于开发者调试问题、优化性能、学习设计模式以及自定义功能。MySQL JDBC 5源码包含了...
压缩包中的“mysql-connector-java-5.1.18--源码”文件是MySQL的JDBC驱动源代码,通过阅读这些源代码,开发者可以深入了解JDBC驱动的工作原理,以及它是如何与MySQL服务器通信的。此外,这也有助于解决在使用过程中...
这通常通过`Class.forName()`方法完成,例如`Class.forName("com.mysql.jdbc.Driver")`来加载MySQL的JDBC驱动。 2. **建立连接**:使用`DriverManager.getConnection()`方法创建到数据库的连接。参数通常包括数据库...
Eclipse JDBC连接数据库源码分析 在Java编程中,JDBC(Java Database Connectivity)是用于与各种数据库进行交互的一组接口和类。本资源“eclipse-jdbc连接数据库源码”提供了一系列关于如何使用Eclipse IDE进行...
在Java编程中,我们需要与MySQL数据库进行交互,这时就会用到MySQL的Java连接器,即JDBC驱动。本资源包含了MySQL的JDBC驱动jar包——mysql-connector-java-5.1.37-bin.jar,以及相关的源码,这对于Java开发者来说是...
### 二、Oracle JDBC驱动简介 Oracle提供了专门针对其数据库的JDBC驱动程序,该驱动程序使得Java应用程序能够直接与Oracle数据库进行通信。在这个示例中,使用的Oracle JDBC驱动类名为`oracle.jdbc.driver.Oracle...
关于源码分析,MySQL Connector/J的源码可以帮助我们深入理解JDBC驱动的工作原理,包括如何建立网络连接、解析SQL语句以及处理结果集等。源码中包含了如`com.mysql.jdbc.Driver`(驱动注册类)、`...
对于MySQL等支持LIMIT的数据库,分页查询的SQL大致如下: ```sql SELECT * FROM table LIMIT start, pageSize; ``` 这里的`start`表示起始位置(从0开始),`pageSize`表示每页的记录数。 在Java中,使用JDBC进行...
标题中的“jdbc连接数据库:oracle/derby/mysql”是指使用Java Database Connectivity (JDBC) API来与三种不同的数据库...同时,了解并分析JDBC驱动源码有助于深入理解数据库操作的底层机制,提升开发和问题排查能力。
1. **DriverManager**: 这是Java数据库连接的入口点,负责管理所有的JDBC驱动。当Java应用通过`Class.forName()`加载了MySQL的驱动后,`DriverManager`会注册这个驱动,并根据用户提供的URL、用户名和密码建立到...
2. 在Java项目中引入MySQL的JDBC驱动包(例如mysql-connector-java-8.0.16.jar),创建相应的包结构。 3. 定义`Student`实体类,用于表示学生信息。 4. 设计`StudentDao`接口,定义数据库操作方法,如`...
首先,我们需要引入JDBC驱动,这通常是通过在Java代码中添加相应的`import`语句完成的。例如,如果你使用的是MySQL数据库,你需要引入如下导入: ```java import java.sql.Connection; import java.sql....
### Jdbc深入分析 #### 一、JDBC概述与应用场景 **1.1 JDBC概念** JDBC(Java Database Connectivity)是Java中用来对关系型数据库进行访问的一种标准API,它提供了一种统一的方式去访问不同的数据库系统。通过...