实现有价值的IT服务
全部博文(709)
分类: Java
2006-09-04 17:19:48
需要告诉DriverManager应与哪个JDBC驱动建立连接。完成该任务的最简单方法是:在实施了java.sql.Driver接口的类上使用Class.forName()。对于MySQL Connector/J,该类的名称是com.mysql.jdbc.Driver。采用该方法,可使用外部配置文件来提供连接到数据库时将使用的驱动类名和驱动参数。
在下面的Java代码中,介绍了在应用程序的main()方法中注册MySQL Connector/J的方式:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
// Notice, do not import com.mysql.jdbc.*
// or you will have problems!(注意,不要导入com.mysql.jdbc.*,否则// 将出现问题!)
public class LoadDriver {
public static void main(String[] args) {
try {
// The newInstance() call is a work around for some
// broken Java implementations
Class.forName("com.mysql.jdbc.Driver").newInstance();
} catch (Exception ex) {
// handle the error
}
}
在DriverManager中注册了驱动后,通过调用DriverManager.getConnection(),能够获得与特殊数据库相连的连接实例。
示例26.1:从DriverManager获得连接
在本示例中,介绍了从DriverManager获得连接实例的方法。对于getConnection()方法,有一些不同的特性。关于如何使用它们的更多信息,请参阅与JDK一起提供的API文档。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
... try {
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/test?user=monty&password=greatsqldb");
// Do something with the Connection
....
} catch (SQLException ex) {
// handle any errors
System.out.println("SQLException: " + ex.getMessage());
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
}
一旦建立了连接,它可被用于创建语句和PreparedStatements,并检索关于数据库的元数据。在下面数节内,给出了进一步的解释。
使用语句,可执行基本的SQL查询,并通过下面介绍的ResultSet类检索结果。
要想创建语句实例,应通过前面介绍的DriverManager.getConnection()或DataSource.getConnection()方法之一,在检索的连接对象上调用createStatement()方法。
一旦拥有了语句实例,可以与希望使用的SQL一起通过调用executeQuery(String)方法执行SELECT查询。
要想更新数据库中的数据,可使用executeUpdate(String SQL)方法。该方法将返回受更新语句影响的行数。
如果你事先不清楚SQL语句是SELECT或UPDATE/INSERT,应使用execute(String SQL)方法。如果SQL查询是SELECT,本方法将返回“真”,如果SQL查询是UPDATE/INSERT/DELETE,本方法将返回“假”。如果是SELECT查询,能够通过调用getResultSet()方法检索结果。如果是UPDATE/INSERT/DELETE查询,能够通过在语句实例上调用getUpdateCount()检索受影响的行计数。
示例26.2:使用java.sql.Statement执行SELECT查询
// assume conn is an already created JDBC connection Statement stmt = null; ResultSet rs = null; try { stmt = conn.createStatement(); rs = stmt.executeQuery("SELECT foo FROM bar"); // or alternatively, if you don't know ahead of time that // the query will be a SELECT... if (stmt.execute("SELECT foo FROM bar")) { rs = stmt.getResultSet(); } // Now do something with the ResultSet .... } finally { // it is a good idea to release // resources in a finally{} block // in reverse-order of their creation // if they are no-longer needed if (rs != null) { try { rs.close(); } catch (SQLException sqlEx) { // ignore } rs = null; } if (stmt != null) { try { stmt.close(); } catch (SQLException sqlEx) { // ignore } stmt = null; } }
从MySQL服务器5.0版开始,与Connector/J 3.1.1或更新版本一起使用时,可完全实现java.sql.CallableStatement接口,但getParameterMetaData()方法例外。
在MySQL参考手册的“”一节中,介绍了MySQL存储程序的语法。
通过JDBC的CallableStatement接口,Connector/J指明了存储程序的功能。
在下面的示例中,给出了1个存储程序,它返回增量为1的inOutParam的值,并通过inputParam传递了作为ResultSet的字符串。
示例26.3. 存储程序示例
CREATE PROCEDURE demoSp(IN inputParam VARCHAR(255), INOUT inOutParam INT)
BEGIN
DECLARE z INT;
SET z = inOutParam + 1;
SET inOutParam = z;
SELECT inputParam;
SELECT CONCAT('zyxw', inputParam);
END
要想与Connector/J一起使用demoSp,可采取下述步骤:
1. 使用Connection.prepareCall()准备可调用语句。
注意,必须使用JDBC转义语法,而且必须使用包含占位符的圆括号:
示例26.4. 使用Connection.prepareCall()
导入java.sql.CallableStatement:
...
//
// Prepare a call to the stored procedure 'demoSp'
// with two parameters
//
// Notice the use of JDBC-escape syntax ({call ...})
//
CallableStatement cStmt = conn.prepareCall("{call demoSp(?, ?)}");
cStmt.setString(1, "abcdefg");
Connection.prepareCall()是一种开销很大的方法,原因在于驱动程序执行的支持输出参数的元数据检索。出于性能方面的原因,应在你的代码中再次使用CallableStatement实例,通过该方式,使对Connection.prepareCall()的不必要调用降至最低。
2. 注册输出参数(如果有的话)
为了检索输出参数的值(创建存储程序时指定为OUT或INOUT的参数),JDBC要求在CallableStatement接口中使用各种registerOutputParameter()方法来执行语句之前指定它们:
示例26.5. 注册输出参数
导入java.sql.Types:
...
//
// Connector/J supports both named and indexed
// output parameters. You can register output
// parameters using either method, as well
// as retrieve output parameters using either
// method, regardless of what method was
// used to register them.
//
// The following examples show how to use
// the various methods of registering
// output parameters (you should of course
// use only one registration per parameter).
//
//
// Registers the second parameter as output
//
cStmt.registerOutParameter(2);
//
// Registers the second parameter as output, and
// uses the type 'INTEGER' for values returned from
// getObject()
//
cStmt.registerOutParameter(2, Types.INTEGER);
//
// Registers the named parameter 'inOutParam'
//
cStmt.registerOutParameter("inOutParam");
//
// Registers the named parameter 'inOutParam', and
// uses the type 'INTEGER' for values returned from
// getObject()
//
cStmt.registerOutParameter("inOutParam", Types.INTEGER);
...
3. 设置输入参数(如果有的话)
输入以及输入/输出参数是作为PreparedStatement对象而设置的。但是,CallableStatement也支持按名称设置参数:
示例26.6. 设置CallableStatement输入参数
...
//
// Set a parameter by index
//
cStmt.setString(1, "abcdefg");
//
// Alternatively, set a parameter using
// the parameter name
//
cStmt.setString("inputParameter", "abcdefg");
//
// Set
//
cStmt.setInt(2, 1);
//
// Alternatively, set the 'in/out' parameter
// by name
//
cStmt.setInt("inOutParam", 1);
...
4. 执行CallableStatement,并检索任何结果集或输出参数。
尽管CallableStatement支持调用任何语句执行方法(executeUpdate(),executeQuery()或execute()),最灵活的方法是调用execute(),这是因为,采用该方法,你无需事先知道存储程序是否将返回结果集:
示例26.7. 检索结果和输出参数值
...
boolean hadResults = cStmt.execute();
//
// Process all returned result sets
//
while (hadResults) {
ResultSet rs = cStmt.getResultSet();
// process result set
...
hadResults = cStmt.getMoreResults();
}
//
// Retrieve output parameters
//
// Connector/J supports both index-based and
// name-based retrieval
//
int outputValue = cStmt.getInt(1); // index-based
outputValue = cStmt.getInt("inOutParam"); // name-based
...
示例26.8. 使用Statement.getGeneratedKeys()检索AUTO_INCREMENT列的值
Statement stmt = null; ResultSet rs = null; try { // // Create a Statement instance that we can use for // 'normal' result sets assuming you have a // Connection 'conn' to a MySQL database already // available stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_UPDATABLE); // // Issue the DDL queries for the table for this example // stmt.executeUpdate("DROP TABLE IF EXISTS autoIncTutorial"); stmt.executeUpdate( "CREATE TABLE autoIncTutorial (" + "priKey INT NOT NULL AUTO_INCREMENT, " + "dataField VARCHAR(64), PRIMARY KEY (priKey))"); // // Insert one row that will generate an AUTO INCREMENT // key in the 'priKey' field // stmt.executeUpdate( "INSERT INTO autoIncTutorial (dataField) " + "values ('Can I Get the Auto Increment Field?')", Statement.RETURN_GENERATED_KEYS); // // Example of using Statement.getGeneratedKeys() // to retrieve the value of an auto-increment // value // int autoIncKeyFromApi = -1; rs = stmt.getGeneratedKeys(); if (rs.next()) { autoIncKeyFromApi = rs.getInt(1); } else { // throw an exception from here } rs.close(); rs = null; System.out.println("Key returned from getGeneratedKeys():" + autoIncKeyFromApi); } finally { if (rs != null) { try { rs.close(); } catch (SQLException ex) { // ignore } } if (stmt != null) { try { stmt.close(); } catch (SQLException ex) { // ignore } } }
示例26.9. 使用SELECT LAST_INSERT_ID()检索AUTO_INCREMENT列的值
Statement stmt = null; ResultSet rs = null; try { // // Create a Statement instance that we can use for // 'normal' result sets. stmt = conn.createStatement(); // // Issue the DDL queries for the table for this example // stmt.executeUpdate("DROP TABLE IF EXISTS autoIncTutorial"); stmt.executeUpdate( "CREATE TABLE autoIncTutorial (" + "priKey INT NOT NULL AUTO_INCREMENT, " + "dataField VARCHAR(64), PRIMARY KEY (priKey))"); // // Insert one row that will generate an AUTO INCREMENT // key in the 'priKey' field // stmt.executeUpdate( "INSERT INTO autoIncTutorial (dataField) " + "values ('Can I Get the Auto Increment Field?')"); // // Use the MySQL LAST_INSERT_ID() // function to do the same thing as getGeneratedKeys() // int autoIncKeyFromFunc = -1; rs = stmt.executeQuery("SELECT LAST_INSERT_ID()"); if (rs.next()) { autoIncKeyFromFunc = rs.getInt(1); } else { // throw an exception from here } rs.close(); System.out.println("Key returned from " + "'SELECT LAST_INSERT_ID()': " + autoIncKeyFromFunc); } finally { if (rs != null) { try { rs.close(); } catch (SQLException ex) { // ignore } } if (stmt != null) { try { stmt.close(); } catch (SQLException ex) { // ignore } } }
示例26.10. 在可更新的ResultSets中检索AUTO_INCREMENT列的值
Statement stmt = null; ResultSet rs = null; try { // // Create a Statement instance that we can use for // 'normal' result sets as well as an 'updatable' // one, assuming you have a Connection 'conn' to // a MySQL database already available // stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_UPDATABLE); // // Issue the DDL queries for the table for this example // stmt.executeUpdate("DROP TABLE IF EXISTS autoIncTutorial"); stmt.executeUpdate( "CREATE TABLE autoIncTutorial (" + "priKey INT NOT NULL AUTO_INCREMENT, " + "dataField VARCHAR(64), PRIMARY KEY (priKey))"); // // Example of retrieving an AUTO INCREMENT key // from an updatable result set // rs = stmt.executeQuery("SELECT priKey, dataField " + "FROM autoIncTutorial"); rs.moveToInsertRow(); rs.updateString("dataField", "AUTO INCREMENT here?"); rs.insertRow(); // // the driver adds rows at the end // rs.last(); // // We should now be on the row we just inserted // int autoIncKeyFromRS = rs.getInt("priKey"); rs.close(); rs = null; System.out.println("Key returned for inserted row: " + autoIncKeyFromRS); } finally { if (rs != null) { try { rs.close(); } catch (SQLException ex) { // ignore } } if (stmt != null) { try { stmt.close(); } catch (SQLException ex) { // ignore } } }
用于MySQL Connector/J的JDBC URL格式如下,方括号“[, ]”的项为可选项:
jdbc:mysql://[host][,failoverhost...][:port]/[database][?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]...
如果未指定主机名,默认为“127.0.0.1”。如果未指定端口,默认为“3306”,它是MySQL服务器的默认端口号。
jdbc:mysql://[host:port],[host:port].../[database][?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]...
如果未指定数据库,将使用无“当前”数据库进行连接。在这种情况下,需要在连接实例上调用“setCatalog()”方法,或在SQL中使用数据库名指定完整的表名(即“SELECT dbname.tablename.colname FROM dbname.tablename...”)。不指定连接时使用的数据库,该选项通常仅在创建用于处理多个数据库的工具时才有用,例如GUI数据库管理器。
MySQL Connector/J支持故障切换功能。这样,就允许驱动程序切换至“从”主机上,并仍能执行只读查询。仅当连接处于autoCommit(true)状态时,才会出现故障切换,这是因为当事务正在进行时,无法可靠地保证故障切换。在事务/连接结束后,大多数应用服务器和连接池均会将autoCommit设置为“真”。
故障切换功能具有下述行为方式:
如果URL属性“autoReconnect”为“假”:故障切换仅会在连接初始化过程中出现,当驱动程序判断第1台主机再次可用时,将返回。
如果URL属性“autoReconnect”为“真”:当驱动程序判断连接失败时(在任意查询之前),将出现故障切换,而且当驱动程序判断第1台主机再次可用时(发出queriesBeforeRetryMaster查询之后),将返回第1台主机。
在任何一种情况下,当你连接到经过故障切换的服务器时,会将连接设置为只读状态,因此,对于会更改数据的查询来说,将抛出异常(MySQL服务器不会处理该查询)。
配置属性定义了Connector/J与MySQL服务器进行连接的方式。除非作了其他说明,否则可以为DataSource对象或Connection对象设置属性。
可采用下述方式的一种设置Configuration(配置)属性:
· 在java.sql.DataSource的MySQL实施实例上使用set*()方法(它是使用java.sql.DataSource实施实例时的首选方法):
o com.mysql.jdbc.jdbc2.optional.MysqlDataSource
o com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
· 作为传递给DriverManager.getConnection()或Driver.connect()的java.util.Properties实例中的 键/值对。
· 作为URL中的JDBC URL参数,以传递给java.sql.DriverManager.getConnection()、java.sql.Driver.connect()、或javax.sql.DataSource的setURL()方法的MySQL实施实例。
如果你用来配置JDBC URL的方法是基于XML的,需要使用XML字符“&”来隔开配置参数,“&”是XML的保留字符。
在下面的表各中,列出了这些属性:
表26.1. 连接属性
属性名 |
定义 |
要求? |
默认值 |
版本 |
Connection/Authentication(连接/鉴定) | ||||
user |
连接的用户 |
No |
|
全部 |
password |
连接时使用的密码。 |
No |
|
全部 |
socketFactory |
驱动程序用于创建与服务器套接字连接的类的名称。该类必须实现了接口“com.mysql.jdbc.SocketFactory”,并有公共无参量构造函数。 |
No |
com.mysql.jdbc.StandardSocketFactory |
3.0.3 |
connectTimeout |
套接字连接的超时(单位为毫秒),0表示无超时。仅对JDK-1.4或更新版本有效。默认值为“0”。 |
No |
0 |
3.0.1 |
socketTimeout |
网络套接字连接的超时(默认值0表示无超时)。 |
No |
0 |
3.0.1 |
useConfigs |
在解析URL属性或应用用户指定的属性之前,加载由逗号“,”分隔的配置属性列表。在文档的“配置”部分中解释了这些配置。 |
No |
|
3.1.5 |
interactiveClient |
设置CLIENT_INTERACTIVE标志,根据INTERACTIVE_TIMEOUT而不是WAIT_TIMEOUT向MySQL通报超时连接。 |
No |
false |
3.1.0 |
propertiesTransform |
com.mysql.jdbc.ConnectionPropertiesTransform的1个实施实例,在尝试连接之前,驱动程序将使用它来更改传递给驱动的URL属性。 |
No |
|
3.1.4 |
useCompression |
与服务器进行通信时采用zlib压缩(真/假)? 默认值为“假”。 |
No |
false |
3.0.17 |
High Availability and Clustering(高可用性和簇集) | ||||
autoReconnect |
驱动程序是否应尝试再次建立失效的和/或死连接? 如果允许,对于在失效或死连接上发出的查询(属于当前事务),驱动程序将抛出异常,但在新事务的连接上发出下一个查询时,将尝试再连接。不推荐使用该特性,这是因为,当应用程序不能恰当处理SQLExceptions时,它会造成与会话状态和数据一致性有关的副作用,设计它的目的仅用于下述情况,即,当你无法配置应用程序来恰当处理因死连接和/或无效连接导致的SQLExceptions时。作为可选方式,可将MySQL服务器变量“wait_timeout”设置为较高的值,而不是默认的8小时。 |
No |
false |
1.1 |
autoReconnectForPools |
使用适合于连接池的再连接策略(默认值为“假”)。 |
No |
false |
3.1.3 |
failOverReadOnly |
在autoReconnect模式下出现故障切换时,是否应将连接设置为“只读”? |
No |
true |
3.0.12 |
reconnectAtTxEnd |
如果将autoReconnect设置为“真”,在每次事务结束后驱动程序是否应尝试再连接? |
No |
false |
3.0.10 |
roundRobinLoadBalance |
启用了autoReconnect而且failoverReadonly为“假”时,是否应按照循环方式挑选要连接的主机? |
No |
false |
3.1.2 |
queriesBeforeRetryMaster |
出现故障切换(使用多主机故障切换)并返回主机之前发出的查询数。无论首先满足了哪个条件,“queriesBeforeRetryMaster”或“secondsBeforeRetryMaster”,均会再次与主机进行连接。默认值为“50”。 |
No |
50 |
3.0.2 |
secondsBeforeRetryMaster |
出现故障切换后,在尝试再次连接到主服务器之前,驱动程序应等待的时间? 无论首先满足了哪个条件,“queriesBeforeRetryMaster”或“secondsBeforeRetryMaster”,均会再次与主机进行连接。单位为秒,默认值为30。 |
No |
30 |
3.0.2 |
enableDeprecatedAutoreconnect |
自3.2版开始,自动再连接功能受到冷落,在3.3版中将删除该功能。将该属性设置为“真”可禁止检查配置的特性。 |
No |
false |
3.2.1 |
Security(安全) | ||||
allowMultiQueries |
在一条语句中,允许使用“;”来分隔多条查询(真/假,默认值为“假”)。 |
No |
false |
3.1.1 |
useSSL |
与服务器进行通信时使用SSL(真/假),默认值为“假”。 |
No |
false |
3.0.2 |
requireSSL |
要求SSL连接,useSSL=true? 默认值为“假”。 |
No |
false |
3.1.0 |
allowUrlInLocalInfile |
驱动程序在是“LOAD DATA LOCAL INFILE”语句中否允许URL? |
No |
false |
3.1.4 |
paranoid |
采取措施,防止在错误信息中泄漏敏感信息,并可可能时清除保存敏感数据的数据结构? 默认值为“假”。 |
No |
false |
3.0.1 |
Performance Extensions(性能扩展) | ||||
metadataCacheSize |
如果将cacheResultSetMetaData设置为“真”,对cacheResultSetMetadata的查询次数(默认值为50)。 |
No |
50 |
3.1.1 |
prepStmtCacheSize |
如果允许预处理语句缓冲功能,应缓冲处理多少条预处理语句? |
No |
25 |
3.0.10 |
prepStmtCacheSqlLimit |
如果允许预处理语句缓冲功能,驱动程序将执行解析缓冲处理的最大SQL是什么? |
No |
256 |
3.0.10 |
maintainTimeStats |
驱动程序是否应维持各种内部定时器,以允许空闲时间计算,以及与服务器的连接失败时允许提供更详细的错误消息? 将该属性设置为“假”,对于每次查询,至少能减少两次对System.getCurrentTimeMillis()的调用。 |
No |
true |
3.1.9 |
blobSendChunkSize |
组块,当通过ServerPreparedStatements发送BLOB/CLOB时使用。 |
No |
1048576 |
3.1.9 |
cacheCallableStmts |
驱动程序是否应对CallableStatements的解析过程执行缓冲处理。 |
No |
false |
3.1.2 |
cachePrepStmts |
驱动程序是否应对客户端预处理语句的PreparedStatements的解析过程执行缓冲处理,是否应检查服务器端预处理语句的适用性以及服务器端预处理语句本身? |
No |
false |
3.0.10 |
cacheResultSetMetadata |
驱动程序是否应对用于Statements和PreparedStatements的ResultSetMetaData执行缓冲处理? 要求 JDK-1.4+,真/假,默认为“假”。 |
No |
false |
3.1.1 |
cacheServerConfiguration |
驱动程序是否应根据每条URL对“HOW VARIABLES”和“SHOW COLLATION”的结果执行缓冲处理? |
No |
false |
3.1.5 |
dontTrackOpenResources |
JDBC规范要求驱动程序自动跟踪和关闭资源,但是,如果你的应用程序不能明确调用作用在语句或结果集上的close(),可能会导致内存泄漏。将该属性设置为“真”,可放宽该限制,对于某些应用程序,会提供更高的内存效率。 |
No |
false |
3.1.7 |
dynamicCalendars |
需要时,驱动程序是否应检索默认日历,或根据连接/会话对其进行缓冲处理? |
No |
false |
3.1.5 |
elideSetAutoCommits |
如果使用MySQL-4.1或更高版本,当服务器的状态与Connection.setAutoCommit(boolean)请求的状态不匹配时,驱动程序是否仅应发出“set autocommit=n”查询? |
No |
false |
3.1.3 |
holdResultsOpenOverStatementClose |
驱动程序是否应按照JDBC规范的要求关闭Statement.close()上的结果集? |
No |
false |
3.1.7 |
locatorFetchBufferSize |
如果将“emulateLocators”配置为“真”,当获取关于getBinaryInputStream的BLOB数据时,缓冲区的大小应是多少? |
No |
1048576 |
3.2.1 |
useFastIntParsing |
是否使用内部“String->Integer”转换子程序来避免创建过多对象? |
No |
true |
3.1.4 |
useLocalSessionState |
驱动程序是否应引用autocommit的内部值,以及由Connection.setAutoCommit()和Connection.setTransactionIsolation()设置的事务隔离,而不是查询数据库? |
No |
false |
3.1.7 |
useNewIO |
驱动程序是否应将java.nio.* interfaces用于网络通信(真/假),默认为“假”。 |
No |
false |
3.1.0 |
useReadAheadInput |
从服务器读取数据时,是否使用较新的、优化的非成组缓冲输入流? |
No |
true |
3.1.5 |
Debuging/Profiling(调试/仿形) | ||||
logger |
实现了com.mysql.jdbc.log.Log的类的名称,com.mysql.jdbc.log.Log用于记录消息(默认为“com.mysql.jdbc.log.StandardLogger”,它会将日志记录到STDERR)。 |
No |
com.mysql.jdbc.log.StandardLogger |
3.1.1 |
profileSQL |
跟踪查询以及它们对已配制记录器的执行/获取次数(真/假),默认为“假”。 |
No |
false |
3.1.0 |
reportMetricsIntervalMillis |
如果允许“gatherPerfMetrics”,记录它们的频率是多少(单位毫秒)? |
No |
30000 |
3.1.2 |
maxQuerySizeToLog |
调试或仿形时,控制将记录的查询的最大长度/大小。 |
No |
2048 |
3.1.3 |
packetDebugBufferSize |
当“enablePacketDebug”为“真”时,需要保留的最大信息包数目。 |
No |
20 |
3.1.3 |
slowQueryThresholdMillis |
如果允许“logSlowQueries”,在将查询记录为“慢”之前的查询时间是多少(毫秒)? |
No |
2000 |
3.1.2 |
useUsageAdvisor |
驱动程序是否应发出“使用情况”警告,就DBC和MySQL Connector/J的恰当和高效使用给出建议(真/假,默认为“假”)? |
No |
false |
3.1.1 |
autoGenerateTestcaseScript |
驱动程序是否应将正在执行的SQL(包括服务器端预处理语句)转储到STDERR? |
No |
false |
3.1.9 |
dumpQueriesOnException |
驱动程序是否应将发送至服务器的查询内容转储到SQLExceptions中? |
No |
false |
3.1.3 |
enablePacketDebug |
允许时,将保留“packetDebugBufferSize”信息包的环形缓冲区,并当在驱动程序代码的关键区域抛出异常时进行转储。 |
No |
false |
3.1.3 |
explainSlowQueries |
如果允许了“logSlowQueries”,驱动程序是否应在服务器上自动发出“EXPLAIN”,并以WARN级别将结果发送给配置好的日志? |
No |
false |
3.1.2 |
logSlowQueries |
是否要记录时间长于“slowQueryThresholdMillis”的查询? |
No |
false |
3.1.2 |
traceProtocol |
是否应记录跟踪级网络协议? |
No |
false |
3.1.2 |
Miscellaneous(其他) | ||||
useUnicode |
处理字符串时,驱动程序是否应使用Unicode字符编码? 仅应在驱动程序无法确定字符集映射,或你正在强制驱动程序使用MySQL不是固有支持的字符集时(如UTF-8)才应使用。真/假,默认为“真”。 |
No |
false |
1.1g |
characterEncoding |
如果“useUnicode”被设置为“真”,处理字符串时,驱动程序应使用什么字符编码? 默认为“autodetect”。 |
No |
|
1.1g |
characterSetResults |
字符集,用于通知服务器以何种字符集返回结果。 |
No |
|
3.0.13 |
connectionCollation |
如果设置了它,将通知服务器通过“set collation_connection”使用该校对。 |
No |
|
3.0.13 |
sessionVariables |
以逗号隔开的“名称/值”对列表,当驱动程序建立了连接后,以“SET SESSION ...”的方式将其发送给服务器。 |
No |
|
3.1.8 |
allowNanAndInf |
驱动程序是否应在PreparedStatement.setDouble()中允许NaN或+/- INF值? |
No |
false |
3.1.5 |
autoDeserialize |
驱动程序是否应自动检测并串并转换保存在BLOB字段中的对象? |
No |
false |
3.1.5 |
capitalizeTypeNames |
是否将DatabaseMetaData中的类型名转换为大写? 通常仅在使用WebObjects时有用,真/假。默认为“假”。 |
No |
false |
2.0.7 |
clobberStreamingResults |
这会使“流式”结果集被自动关闭,如果在所有数据尚未从服务器中读取完之前,执行了另一查询,正在从服务器流出的任何未完成数据均将丢失。 |
No |
false |
3.0.9 |
continueBatchOnError |
如果一条语句失败,驱动程序是否应继续处理批命令? JDBC规范允许任何一种方式(默认为“真”)。 |
No |
true |
3.0.3 |
createDatabaseIfNotExist |
如果不存在,创建URL中给定的数据库。假定用户具有创建数据库的权限。 |
No |
false |
3.1.9 |
emptyStringsConvertToZero |
驱动程序是否应允许从空字符串字段到数值“0”的转换? |
No |
true |
3.1.8 |
emulateLocators |
N/A |
No |
false |
3.1.0 |
emulateUnsupportedPstmts |
驱动程序是否应检测不被服务器支持的预处理语句,并用客户端模拟版替换它们? |
No |
true |
3.1.7 |
ignoreNonTxTables |
是否忽略关于回退的非事务表? 默认值为“假”。 |
No |
false |
3.0.9 |
jdbcCompliantTruncation |
连接到支持告警的服务器时(MySQL 4.1.0和更高版本),当按照JDBC的要求截短数据时,驱动程序是否应抛出java.sql.DataTruncation异常? |
No |
true |
3.1.2 |
maxRows |
返回的最大行数(0,默认值表示返回所有行)。 |
No |
-1 |
all versions |
noDatetimeStringSync |
不保证ResultSet.getDatetimeType().toString().equals(ResultSet.getString()。 |
No |
false |
3.1.7 |
nullCatalogMeansCurrent |
当DatabaseMetadataMethods请求“目录”参数时,值“Null”是否意味着使用当前目录? 它不兼容JDBC,但符合驱动程序早期版本的传统行为。 |
No |
true |
3.1.8 |
nullNamePatternMatchesAll |
接受*pattern参数的DatabaseMetaData方法是否应将null按对待“%”的相同方式处理(不兼容JDBC,但驱动程序的早期版本能接受与规范的这类偏离)。 |
No |
true |
3.1.8 |
pedantic |
严格遵守JDBC规范。 |
No |
false |
3.0.0 |
relaxAutoCommit |
如果驱动程序所连接的MySQL服务器的版本不支持事务,仍允许调用commit()、rollback()和setAutoCommit()?真/假,默认为“假”。 |
No |
false |
2.0.13 |
retainStatementAfterResultSetClose |
调用ResultSet.close()后,驱动程序是否应将语句引用保存在结果集中? 在JDBC-4.0后,与JDBC不兼容。 |
No |
false |
3.1.11 |
rollbackOnPooledClose |
当连接池中的逻辑连接关闭时,驱动程序是否应发出rollback()? |
No |
true |
3.0.15 |
runningCTS13 |
允许在Sun与JDBC兼容的testsuite 1.3版中处理缺陷。 |
No |
false |
3.1.7 |
serverTimezone |
覆盖时区的检测/映射。当服务器的时区为映射到Java时区时使用。 |
No |
|
3.0.2 |
strictFloatingPoint |
仅在兼容性测试的早期版本中使用。 |
No |
false |
3.0.0 |
strictUpdates |
驱动程序是否应对可更新结果集进行严格检查(选择所有的主键)?真/假,默认为“真”。 |
No |
true |
3.0.4 |
tinyInt1isBit |
驱动程序是否应将数据类型TINYINT(1)当作BIT类型对待?创建表时,服务器会执行BIT -> TINYINT(1)操作。 |
No |
true |
3.0.16 |
transformedBitIsBoolean |
如果驱动程序将TINYINT(1)转换为不同的类型,为了与MySQL-5.0兼容,驱动程序是否应使用BOOLEAN取代BIT?这是因为MySQL-5.0具有BIT类型。 |
No |
false |
3.1.9 |
ultraDevHack |
由于UltraDev已损坏,并为所有语句发出了prepareCall(),需要时,是否要为prepareCall()创建PreparedStatements? 真/假,默认值为“假”。 |
No |
false |
2.0.3 |
useHostsInPrivileges |
在DatabaseMetaData.getColumn/TablePrivileges()中为用户添加“@hostname”。真/假,默认为“真”。 |
No |
true |
3.0.2 |
useOldUTF8Behavior |
与4.0和更早版本的服务器进行通信时,使用UTF-8。 |
No |
false |
3.1.6 |
useOnlyServerErrorMessages |
对服务器返回的错误消息,不事先设定“标准的”SQLState错误消息。 |
No |
true |
3.0.15 |
useServerPrepStmts |
如果服务器支持,是否使用服务器端预处理语句? 默认值为“真”。 |
No |
true |
3.1.0 |
useSqlStateCodes |
使用SQL标准状态码取代“传统的”X/Open/SQL状态码,真/假,默认为“真”。 |
No |
true |
3.1.3 |
useStreamLengthsInPrepStmts |
是否采用PreparedStatement/ResultSet.setXXXStream()方法调用中的流长度参数?真/假,默认为“真”。 |
No |
true |
3.0.2 |
useTimezone |
是否在客户端和服务器时区间转换时间/日期类型(真/假,默认为“假”)? |
No |
false |
3.0.2 |
useUnbufferedInput |
不使用BufferedInputStream来从服务器读取数据。 |
No |
true |
3.0.11 |
yearIsDateType |
JDBC驱动程序是否应将MySQL类型“YEAR”当作java.sql.Date或SHORT对待? |
No |
true |
3.1.9 |
zeroDateTimeBehavior |
当驱动程序遇到全由0组成的DATETIME值时,应出现什么?MySQL使用它来表示无效日期。有效值是“exception”、“round”和“convertToNull”。 |
No |
exception |
3.1.4 |
通过“socketFactory”属性,使用NamedPipeSocketFactory,在Windows NT/2000/XP平台上,通过命名管道,Connector/J也支持对MySQL的访问。如果不使用namedPipePath属性,将使用的默认值。如果使用NamedPipeSocketFactory,将忽略JDBC url中的主机名和端口号。
在URL中添加下述属性可启用NamedPipeSocketFactory:
socketFactory=com.mysql.jdbc.NamedPipeSocketFactory
命名管道仅能当连接到位于相同物理机器上的MySQL时才能正常工作,该机器上应使用了JDBC驱动程序。在简单的性能测试中,命名管道的访问速度比标准的TCP/IP访问块30~50%。
使用com.mysql.jdbc.NamedPipeSocketFactory或com.mysql.jdbc.StandardSocketFactory中的示例代码,可创建你自己的套接字代理。
在本节中,就特定实施方案将如何影响MySQL Connector/J的使用方式,给出了接口层面上的详细介绍。
· Blob
Blob实施不允许“原地”调整(它们是“副本”,正如DatabaseMetaData.locatorsUpdateCopies()方法所指明的那样)。因此,应使用对应的PreparedStatement.setBlob()或ResultSet.updateBlob()(对于可更新结果集)方法,将变化保存到数据库中。
自Connector/J version 3.1.0开始,通过在JDBC URL中添加属性“emulateLocators=true”,能够使用定位器模拟Blob。随后,必须使用带有列值的列别名,在你编写的用于检索Blob的SELECT中,将列值设为Blob列的世纪名称。SELECT还必须仅引用1个表,该表必须有1个主键,而且SELECT必须涵盖构成主键的所有列。随后,驱动程序将延期加载实际的Blob数据,直至检索了Blob并在其上调用了检索方法为止(getInputStream(), getBytes(),等)。
· CallableStatement
自Connector/J 3.1.1开始,当通过CallableStatement接口连接到MySQL 5.0或更高版本时,可支持存储程序。目前,不支持CallableStatement的getParameterMetaData()方法。
· Clob
Clob实施不允许“原地”调整(它们是“副本”,正如DatabaseMetaData.locatorsUpdateCopies()方法所指明的那样)。因此,应使用PreparedStatement.setClob()方法将变更保存到数据库中。JDBC API没有ResultSet.updateClob()方法。
· Connection
与MM.MySQL的早期版本不同,“isClosed()”不会对服务器即行Ping操作以确定服务器是否有效。按照JDBC规范,如果在连接上调用了“closed()”,它仅返回“真”。如果需要确定连接是否依然有效,应发出简单查询,如“SELECT 1”。如果连接不再有效,驱动程序将抛出异常。
· DatabaseMetaData
对于外键信息(getImported/ExportedKeys()和getCrossReference()),仅在“InnoDB”类性的表中可用。但是,驱动程序会使用“SHO
· Driver
· PreparedStatement
PreparedStatements是由驱动程序实现的,这是应为MySQL未提供预处理语句功能。出于该原因,驱动程序不实施getParameterMetaData()或getMetaData(),这是因为,它要求驱动程序在客户端上具有完整的SQL语法分析程序。
从3.1.0版MySQL Connector/J开始,当服务器支持时,将使用服务器端预处理语句和“二进制编码”的结果集。
使用带有“large”参数(这类参数是通过setBinaryStream()、setAsciiStream()、setUnicodeStream()、setBlob()或setClob()设置的)的服务器端预处理语句时应谨慎。如果打算再次执行已将任何“large”参数更改为非“large”参数的语句,需要调用clearParameters(),并再次设置所有参数。其原因如下:
o 设置了参数时,驱动程序会将“large”数据“out-of-band”发送给服务器端的预处理语句(执行预处理语句之前)。
o 一旦完成,将关闭用于读取客户端上数据的流(根据JDBC规范),而且不能再次读取流。
o 如果参数从“large”变为非“large”,驱动程序必须复位预处理语句的服务器端状态,以便允许已更改的参数区带以前的“large”值。这将删除已发送给服务器的所有“large”数据,因而需要通过setBinaryStream()、setAsciiStream()、setUnicodeStream()、setBlob()或setClob()方法再次发送数据。
因而,如果你打算将参数类型更改为非“large”类型,必须调用clearParameters(),并在重新执行预处理语句之前再次设置预处理语句的所有参数。
· ResultSet
在默认情况下,ResultSets(结果集)是可完全检索的,并被保存在内存中。对于大多数情况,这是最有效的操作方式,而且还应归因于更容易实施的MySQL网络协议设计。如果你正在处理具有大量行或大数据的ResultSets,而且无法在JVM内为所需内存分配大量空间,可以通知驱动程序以“流”方式返回结果,一次一行。
要想允许该功能,需要以下述方式创建1个语句实例:
stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
java.sql.ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);
正向、只读结果集,以及Integer.MIN_VALUE的组合用于指示驱动程序以“流”方式按行处理结果集。此后,对于该语句创建的结果集,将按行检索。
对于该方式,有一些需注意的事项。能够在连接上发出任何其他查询之前,应读取结果集中的所有行(或关闭结果集),否则将抛出异常。
能够释放这些锁定语句(无论它们是MyISAM表级锁定,还是某些其他存储引擎如InnoDB中的行级锁定)的最早时刻是完成语句时。
如果语句在事务的范围内,当事务完成后将释放锁定(它意味着语句需首先完成)。与大多数其他数据库一样,在读取了语句上所有的未决结果集或关闭了语句的活动结果集之前,语句不会结束。
因此,如果正在使用“流式”结果,如果希望保持对特定表的同时访问,而这些表被生成结果集的语句所引用,就应尽快地处理“流式”结果。
· ResultSetMetaData
仅当使用MySQL服务器4.0或更高版本时,“isAutoIncrement()”方法才能正确工作。
· Statement
使用版本低于3.2.1的JDBC驱动程序,而且所连接的服务器版本低于5.0.3时,除了像前面介绍的那样切换结果集外,“setFetchSize()”方法不起作用。
MySQL不支持SQL光标,而且JDBC驱动程序也不能模拟它们,因此“setCursorName()”没有效果。
MySQL Connector/J在处理MySQL数据类型和Java数据类型的转换处理方面十分灵活。
尽管可能会出现舍入、溢出或精度损失,当在通常情况下,能够将任何MySQL数据类型转换为java.lang.String,并能将任何数值类型转换为Java数值类型。
从Connector/J 3.1.0开始,按照JDBC规范的要求,JDBC驱动程序将发出警告或抛出DataTruncation异常,除非通过使用“jdbcCompliantTruncation”属性并将其设为“假”,对连接进行相应配置取消了前述要求。
在下面的表格中,列出能可靠工作的转换:
表26.2. 转换表
下述MySQL数据类型 |
总能转换为下述Java类型 |
CHAR, VARCHAR, BLOB, TEXT, ENUM, and SET |
java.lang.String, java.io.InputStream, java.io.Reader, java.sql.Blob, java.sql.Clob |
FLOAT, REAL, DOUBLE PRECISION, NUMERIC, DECIMAL, TINYINT, SMALLINT, MEDIUMINT, INTEGER, BIGINT |
java.lang.String, java.lang.Short, java.lang.Integer, java.lang.Long, java.lang.Double, java.math.BigDecimal 注释:与希望转换的MySQL数据类型相比,如果选择了精度较低的Java数值类型,可能会出现舍入、溢出或精度损失。 |
DATE, TIME, DATETIME, TIMESTAMP |
java.lang.String, java.sql.Date, java.sql.Timestamp |
在MySQL类型和Java类型之间,ResultSet.getObject()方法采用了下述类型转换方式,在可能的情况下遵从JDBC规范:
表26.3. 用于ResultSet.getObject()的MySQL类型和Java类型
MySQL类型名称 |
以Java类返回 |
BIT(1) (new in MySQL-5.0) |
java.lang.Boolean |
BIT( > 1) (new in MySQL-5.0) |
byte[] |
TINYINT |
java.lang.Boolean,如果将配置属性“tinyInt1isBit”设为“真”(默认值),并将存储大小设为“1”;或java.lang.Integer,如果不是的话。 |
BOOL , BOOLEAN |
请参见上面的TINYINT,它们目前是TINYINT(1)的别名。 |
SMALLINT[(M)] [UNSIGNED] |
java.lang.Integer(无论是否为UNSIGNED) |
MEDIUMINT[(M)] [UNSIGNED] |
java.lang.Integer(无论是否为UNSIGNED) |
INT,INTEGER[(M)] [UNSIGNED] |
java.lang.Integer,如果是UNSIGNED,java.lang.Long |
BIGINT[(M)] [UNSIGNED] |
java.lang.Long,如果是UNSIGNED,java.math.BigInteger |
FLOAT[(M,D)] |
java.lang.Float |
DOUBLE[(M,B)] |
java.lang.Double |
DECIMAL[(M[,D])] |
java.math.BigDecimal |
DATE |
java.sql.Date |
DATETIME |
java.sql.Timestamp |
TIMESTAMP[(M)] |
java.sql.Timestamp |
TIME |
java.sql.Time |
YEAR[(2|4)] |
java.sql.Date(日期设为2月1日晚上2点) |
CHAR(M) |
java.lang.String(除非列的字符集是BINARY),然后返回字节[] |
VARCHAR(M) [BINARY] |
java.lang.String(除非列的字符集是BINARY),然后返回字节[] |
BINARY(M) |
byte[] |
VARBINARY(M) |
byte[] |
TINYBLOB |
byte[] |
TINYTEXT |
java.lang.String |
BLOB |
byte[] |
TEXT |
java.lang.String |
MEDIUMBLOB |
byte[] |
MEDIUMTEXT |
java.lang.String |
LONGBLOB |
byte[] |
LONGTEXT |
java.lang.String |
ENUM('value1','value2',...) |
java.lang.String |
SET('value1','value2',...) |
java.lang.String |
对于从JDBC驱动程序发往服务器的所有字符串,均将自动地从固有放热Java Unicode形式转换为客户端字符编码,包括通过Statement.execute()、Statement.executeUpdate()和Statement.executeQuery()发出的所有查询,以及除了用setBytes()、setBinaryStream()、setAsiiStream()、setUnicodeStream()和setBlob()排除的参试之外的所有PreparedStatement和CallableStatement参数。
在MySQL服务器4.1之前,Connector/J支持每连接单一字符编码,能够从服务器配置自动检测到它,也能由用户通过使用useUnicode和characterEncoding属性配置它。
从MySQL服务器4.1版起,Connector/J支持客户端和服务器之间的但以字符编码,以及针对结果集中从服务器返回至客户端的数据的任意数目字符编码。
连接时将自动检测客户端和服务器之间的字符编码。对于由驱动程序使用的编码来说,它是在服务器上通过使用配置变量“character_set”(低于4.1.0的服务器版本)和“character_set_server”(4.1.0和更高的服务器版本)指定的。更多信息,请参见MySQL服务器手册中的一节。
要想覆盖客户端上的自动检测编码功能,可在用于连接到服务器的URL中使用“characterEncoding”属性。
在客户端上指定字符编码时,应使用Java风格名称。在下面的表格中,列出了用于MySQL字符集的Java风格名称:
表26.4. MySQL对Java编码名称的翻译
MySQL字符集名称 | Java风格字符编码名称 |
---|---|
usa7 | US-ASCII |
big5 | Big5 |
gbk | GBK |
sjis | SJIS |
gb2312 | EUC_CN |
ujis | EUC_JP |
euc_kr | EUC_KR |
latin1 | ISO8859_1 |
latin1_de | ISO8859_1 |
german1 | ISO8859_1 |
danish | ISO8859_1 |
latin2 | ISO8859_2 |
czech | ISO8859_2 |
hungarian | ISO8859_2 |
croat | ISO8859_2 |
greek | ISO8859_7 |
hebrew | ISO8859_8 |
latin5 | ISO8859_9 |
latvian | ISO8859_13 |
latvian1 | ISO8859_13 |
estonia | ISO8859_13 |
dos | Cp437 |
pclatin2 | Cp852 |
cp866 | Cp866 |
koi8_ru | KOI8_R |
tis620 | TIS620 |
win1250 | Cp1250 |
win1250ch | Cp1250 |
win1251 | Cp1251 |
cp1251 | Cp1251 |
win1251ukr | Cp1251 |
cp1257 | Cp1257 |
macroman | MacRoman |
macce | MacCentralEurope |
utf8 | UTF-8 |
ucs2 | UnicodeBig |
不要用Connector/J发出查询“set names”,这是因为驱动程序不会检测已变化的字符集,而是会继续使用在初始连接设置中检测到的字符集。
为了允许从客户端发出的多个字符集,应使用“UTF-8”编码,方式是,将utf8配置为默认的服务器字符集,或通过“characterEncoding”属性配置JDBC驱动程序以使用“UTF-8”。