| 1 |
1. MySQL Connector/J
|
| 2 |
________________________________________________________
|
| 3 |
|
| 4 |
MySQL provides connectivity for client applications developed
|
| 5 |
in the Java programming language via a JDBC driver, which is
|
| 6 |
called MySQL Connector/J.
|
| 7 |
|
| 8 |
MySQL Connector/J is a JDBC-3.0 Type 4 driver, which means
|
| 9 |
that is pure Java, implements version 3.0 of the JDBC
|
| 10 |
specification, and communicates directly with the MySQL
|
| 11 |
server using the MySQL protocol.
|
| 12 |
|
| 13 |
Although JDBC is useful by itself, we would hope that if you
|
| 14 |
are not familiar with JDBC that after reading the first few
|
| 15 |
sections of this manual, that you would avoid using naked
|
| 16 |
JDBC for all but the most trivial problems and consider using
|
| 17 |
one of the popular persistence frameworks such as Hibernate
|
| 18 |
(http://www.hibernate.org/), Spring's JDBC templates
|
| 19 |
(http://www.springframework.org/) or Ibatis SQL Maps
|
| 20 |
(http://ibatis.apache.org/) to do the majority of repetitive
|
| 21 |
work and heavier lifting that is sometimes required with
|
| 22 |
JDBC.
|
| 23 |
|
| 24 |
This section is not designed to be a complete JDBC tutorial.
|
| 25 |
If you need more information about using JDBC you might be
|
| 26 |
interested in the following online tutorials that are more
|
| 27 |
in-depth than the information presented here:
|
| 28 |
* JDBC Basics
|
| 29 |
(http://java.sun.com/docs/books/tutorial/jdbc/basics/inde
|
| 30 |
x.html) --- A tutorial from Sun covering beginner topics
|
| 31 |
in JDBC
|
| 32 |
* JDBC Short Course
|
| 33 |
(http://java.sun.com/developer/onlineTraining/Database/JD
|
| 34 |
BCShortCourse/index.html) --- A more in-depth tutorial
|
| 35 |
from Sun and JGuru
|
| 36 |
|
| 37 |
1.1. Connector/J Versions
|
| 38 |
|
| 39 |
There are currently three version of MySQL Connector/J
|
| 40 |
available:
|
| 41 |
* Connector/J 3.0 provides core functionality and was
|
| 42 |
designed with connectivity to MySQL 3.x or MySQL 4.1
|
| 43 |
servers, although it will provide basic compatibility
|
| 44 |
with later versions of MySQL. Connector/J 3.0 does not
|
| 45 |
support server-side prepared statements, and does not
|
| 46 |
support any of the features in versions of MySQL later
|
| 47 |
than 4.1.
|
| 48 |
* Connector/J 3.1 was designed for connectivity to MySQL
|
| 49 |
4.1 and MySQL 5.0 servers and provides support for all
|
| 50 |
the functionality in MySQL 5.0 except distributed
|
| 51 |
transaction (XA) support.
|
| 52 |
* Connector/J 5.0 provides support for all the
|
| 53 |
functionality offered by Connector/J 3.1 and includes
|
| 54 |
distributed transaction (XA) support.
|
| 55 |
|
| 56 |
The current recommended version for Connector/J is 5.0. This
|
| 57 |
guide covers all three connector versions, with specific
|
| 58 |
notes given where a setting applies to a specific option.
|
| 59 |
|
| 60 |
1.1.1. Java Versions Supported
|
| 61 |
|
| 62 |
MySQL Connector/J supports Java-2 JVMs, including:
|
| 63 |
* JDK 1.2.x (only for Connector/J 3.1.x or earlier)
|
| 64 |
* JDK 1.3.x
|
| 65 |
* JDK 1.4.x
|
| 66 |
* JDK 1.5.x
|
| 67 |
|
| 68 |
If you are building Connector/J from source using the source
|
| 69 |
distribution (see Section A.2.4, "Installing from the
|
| 70 |
Development Source Tree") then you must use JDK 1.4.x or
|
| 71 |
newer to compiler the Connector package.
|
| 72 |
|
| 73 |
MySQL Connector/J does not support JDK-1.1.x or JDK-1.0.x
|
| 74 |
|
| 75 |
Because of the implementation of java.sql.Savepoint,
|
| 76 |
Connector/J 3.1.0 and newer will not run on JDKs older than
|
| 77 |
1.4 unless the class verifier is turned off (by setting the
|
| 78 |
-Xverify:none option to the Java runtime). This is because
|
| 79 |
the class verifier will try to load the class definition for
|
| 80 |
java.sql.Savepoint even though it is not accessed by the
|
| 81 |
driver unless you actually use savepoint functionality.
|
| 82 |
|
| 83 |
Caching functionality provided by Connector/J 3.1.0 or newer
|
| 84 |
is also not available on JVMs older than 1.4.x, as it relies
|
| 85 |
on java.util.LinkedHashMap which was first available in
|
| 86 |
JDK-1.4.0.
|
| 87 |
|
| 88 |
1.2. Installing Connector/J
|
| 89 |
|
| 90 |
You can install the Connector/J package using two methods,
|
| 91 |
using either the binary or source distribution. The binary
|
| 92 |
distribution provides the easiest methods for installation;
|
| 93 |
the source distribution enables you to customize your
|
| 94 |
installation further. With with either solution, you must
|
| 95 |
|
| 96 |
1.2.1. Installing Connector/J from a Binary Distribution
|
| 97 |
|
| 98 |
The easiest method of installation is to use the binary
|
| 99 |
distribution of the Connector/J package. The binary
|
| 100 |
distribution is available either as a Tar/Gzip or Zip file
|
| 101 |
which you must extract to a suitable location and then
|
| 102 |
optionally make the information about the package available
|
| 103 |
by changing your CLASSPATH (see Section A.2.2, "Installing
|
| 104 |
the Driver and Configuring the CLASSPATH").
|
| 105 |
|
| 106 |
MySQL Connector/J is distributed as a .zip or .tar.gz archive
|
| 107 |
containing the sources, the class files, and the JAR archive
|
| 108 |
named mysql-connector-java-[version]-bin.jar, and starting
|
| 109 |
with Connector/J 3.1.8 a debug build of the driver in a file
|
| 110 |
named mysql-connector-java-[version]-bin-g.jar.
|
| 111 |
|
| 112 |
Starting with Connector/J 3.1.9, the .class files that
|
| 113 |
constitute the JAR files are only included as part of the
|
| 114 |
driver JAR file.
|
| 115 |
|
| 116 |
You should not use the debug build of the driver unless
|
| 117 |
instructed to do so when reporting a problem ors bug to MySQL
|
| 118 |
AB, as it is not designed to be run in production
|
| 119 |
environments, and will have adverse performance impact when
|
| 120 |
used. The debug binary also depends on the Aspect/J runtime
|
| 121 |
library, which is located in the src/lib/aspectjrt.jar file
|
| 122 |
that comes with the Connector/J distribution.
|
| 123 |
|
| 124 |
You will need to use the appropriate graphical or
|
| 125 |
command-line utility to un-archive the distribution (for
|
| 126 |
example, WinZip for the .zip archive, and tar for the .tar.gz
|
| 127 |
archive). Because there are potentially long filenames in the
|
| 128 |
distribution, we use the GNU tar archive format. You will
|
| 129 |
need to use GNU tar (or an application that understands the
|
| 130 |
GNU tar archive format) to unpack the .tar.gz variant of the
|
| 131 |
distribution.
|
| 132 |
|
| 133 |
1.2.2. Installing the Driver and Configuring the CLASSPATH
|
| 134 |
|
| 135 |
Once you have extracted the distribution archive, you can
|
| 136 |
install the driver by placing
|
| 137 |
mysql-connector-java-[version]-bin.jar in your classpath,
|
| 138 |
either by adding the full path to it to your CLASSPATH
|
| 139 |
environment variable, or by directly specifying it with the
|
| 140 |
command line switch -cp when starting your JVM.
|
| 141 |
|
| 142 |
If you are going to use the driver with the JDBC
|
| 143 |
DriverManager, you would use com.mysql.jdbc.Driver as the
|
| 144 |
class that implements java.sql.Driver.
|
| 145 |
|
| 146 |
You can set the CLASSPATH environment variableunder UNIX,
|
| 147 |
Linux or Mac OS X either locally for a user within their
|
| 148 |
.profile, .login or other login file. You can also set it
|
| 149 |
globally by editing the global /etc/profile file.
|
| 150 |
|
| 151 |
For example, under a C shell (csh, tcsh) you would add the
|
| 152 |
Connector/J driver to your CLASSPATH using the following:
|
| 153 |
shell> setenv CLASSPATH /path/to/mysql-connector-java-[version]-bin.ja
|
| 154 |
r:$CLASSPATH
|
| 155 |
|
| 156 |
Or with a Bourne-compatible shell (sh, ksh, bash):
|
| 157 |
export set CLASSPATH=/path/to/mysql-connector-java-[version]-bin.jar:$
|
| 158 |
CLASSPATH
|
| 159 |
|
| 160 |
Within Windows 2000, Windows XP and Windows Server 2003, you
|
| 161 |
must set the environment variable through the System control
|
| 162 |
panel.
|
| 163 |
|
| 164 |
If you want to use MySQL Connector/J with an application
|
| 165 |
server such as Tomcat or JBoss, you will have to read your
|
| 166 |
vendor's documentation for more information on how to
|
| 167 |
configure third-party class libraries, as most application
|
| 168 |
servers ignore the CLASSPATH environment variable. For
|
| 169 |
configuration examples for some J2EE application servers, see
|
| 170 |
Section A.5.2, "Using Connector/J with J2EE and Other Java
|
| 171 |
Frameworks." However, the authoritative source for JDBC
|
| 172 |
connection pool configuration information for your particular
|
| 173 |
application server is the documentation for that application
|
| 174 |
server.
|
| 175 |
|
| 176 |
If you are developing servlets or JSPs, and your application
|
| 177 |
server is J2EE-compliant, you can put the driver's .jar file
|
| 178 |
in the WEB-INF/lib subdirectory of your webapp, as this is a
|
| 179 |
standard location for third party class libraries in J2EE web
|
| 180 |
applications.
|
| 181 |
|
| 182 |
You can also use the MysqlDataSource or
|
| 183 |
MysqlConnectionPoolDataSource classes in the
|
| 184 |
com.mysql.jdbc.jdbc2.optional package, if your J2EE
|
| 185 |
application server supports or requires them. Starting with
|
| 186 |
Connector/J 5.0.0, the javax.sql.XADataSource interface is
|
| 187 |
implemented via the
|
| 188 |
com.mysql.jdbc.jdbc2.optional.MysqlXADataSource class, which
|
| 189 |
supports XA distributed transactions when used in combination
|
| 190 |
with MySQL server version 5.0.
|
| 191 |
|
| 192 |
The various MysqlDataSource classes support the following
|
| 193 |
parameters (through standard set mutators):
|
| 194 |
* user
|
| 195 |
* password
|
| 196 |
* serverName (see the previous section about fail-over
|
| 197 |
hosts)
|
| 198 |
* databaseName
|
| 199 |
* port
|
| 200 |
|
| 201 |
1.2.3. Upgrading from an Older Version
|
| 202 |
|
| 203 |
MySQL AB tries to keep the upgrade process as easy as
|
| 204 |
possible, however as is the case with any software, sometimes
|
| 205 |
changes need to be made in new versions to support new
|
| 206 |
features, improve existing functionality, or comply with new
|
| 207 |
standards.
|
| 208 |
|
| 209 |
This section has information about what users who are
|
| 210 |
upgrading from one version of Connector/J to another (or to a
|
| 211 |
new version of the MySQL server, with respect to JDBC
|
| 212 |
functionality) should be aware of.
|
| 213 |
|
| 214 |
1.2.3.1. Upgrading from MySQL Connector/J 3.0 to 3.1
|
| 215 |
|
| 216 |
Connector/J 3.1 is designed to be backward-compatible with
|
| 217 |
Connector/J 3.0 as much as possible. Major changes are
|
| 218 |
isolated to new functionality exposed in MySQL-4.1 and newer,
|
| 219 |
which includes Unicode character sets, server-side prepared
|
| 220 |
statements, SQLState codes returned in error messages by the
|
| 221 |
server and various performance enhancements that can be
|
| 222 |
enabled or disabled via configuration properties.
|
| 223 |
* Unicode Character Sets --- See the next section, as well
|
| 224 |
as [WARNING: missing xref target (id=charset)] for
|
| 225 |
information on this new feature of MySQL. If you have
|
| 226 |
something misconfigured, it will usually show up as an
|
| 227 |
error with a message similar to Illegal mix of
|
| 228 |
collations.
|
| 229 |
* Server-side Prepared Statements --- Connector/J 3.1 will
|
| 230 |
automatically detect and use server-side prepared
|
| 231 |
statements when they are available (MySQL server version
|
| 232 |
4.1.0 and newer).
|
| 233 |
Starting with version 3.1.7, the driver scans SQL you are
|
| 234 |
preparing via all variants of
|
| 235 |
Connection.prepareStatement() to determine if it is a
|
| 236 |
supported type of statement to prepare on the server
|
| 237 |
side, and if it is not supported by the server, it
|
| 238 |
instead prepares it as a client-side emulated prepared
|
| 239 |
statement. You can disable this feature by passing
|
| 240 |
emulateUnsupportedPstmts=false in your JDBC URL.
|
| 241 |
If your application encounters issues with server-side
|
| 242 |
prepared statements, you can revert to the older
|
| 243 |
client-side emulated prepared statement code that is
|
| 244 |
still presently used for MySQL servers older than 4.1.0
|
| 245 |
with the connection property useServerPrepStmts=false
|
| 246 |
* Datetimes with all-zero components (0000-00-00 ...) ---
|
| 247 |
These values can not be represented reliably in Java.
|
| 248 |
Connector/J 3.0.x always converted them to NULL when
|
| 249 |
being read from a ResultSet.
|
| 250 |
Connector/J 3.1 throws an exception by default when these
|
| 251 |
values are encountered as this is the most correct
|
| 252 |
behavior according to the JDBC and SQL standards. This
|
| 253 |
behavior can be modified using the zeroDateTimeBehavior
|
| 254 |
configuration property. The allowable values are:
|
| 255 |
+ exception (the default), which throws an
|
| 256 |
SQLException with an SQLState of S1009.
|
| 257 |
+ convertToNull, which returns NULL instead of the
|
| 258 |
date.
|
| 259 |
+ round, which rounds the date to the nearest closest
|
| 260 |
value which is 0001-01-01.
|
| 261 |
Starting with Connector/J 3.1.7, ResultSet.getString()
|
| 262 |
can be decoupled from this behavior via
|
| 263 |
noDatetimeStringSync=true (the default value is false) so
|
| 264 |
that you can get retrieve the unaltered all-zero value as
|
| 265 |
a String. It should be noted that this also precludes
|
| 266 |
using any time zone conversions, therefore the driver
|
| 267 |
will not allow you to enable noDatetimeStringSync and
|
| 268 |
useTimezone at the same time.
|
| 269 |
* New SQLState Codes --- Connector/J 3.1 uses SQL:1999
|
| 270 |
SQLState codes returned by the MySQL server (if
|
| 271 |
supported), which are different from the legacy X/Open
|
| 272 |
state codes that Connector/J 3.0 uses. If connected to a
|
| 273 |
MySQL server older than MySQL-4.1.0 (the oldest version
|
| 274 |
to return SQLStates as part of the error code), the
|
| 275 |
driver will use a built-in mapping. You can revert to the
|
| 276 |
old mapping by using the configuration property
|
| 277 |
useSqlStateCodes=false.
|
| 278 |
* ResultSet.getString() --- Calling ResultSet.getString()
|
| 279 |
on a BLOB column will now return the address of the
|
| 280 |
byte[] array that represents it, instead of a String
|
| 281 |
representation of the BLOB. BLOBs have no character set,
|
| 282 |
so they can't be converted to java.lang.Strings without
|
| 283 |
data loss or corruption.
|
| 284 |
To store strings in MySQL with LOB behavior, use one of
|
| 285 |
the TEXT types, which the driver will treat as a
|
| 286 |
java.sql.Clob.
|
| 287 |
* Debug builds --- Starting with Connector/J 3.1.8 a debug
|
| 288 |
build of the driver in a file named
|
| 289 |
mysql-connector-java-[version]-bin-g.jar is shipped
|
| 290 |
alongside the normal binary jar file that is named
|
| 291 |
mysql-connector-java-[version]-bin.jar.
|
| 292 |
Starting with Connector/J 3.1.9, we don't ship the .class
|
| 293 |
files unbundled, they are only available in the JAR
|
| 294 |
archives that ship with the driver.
|
| 295 |
You should not use the debug build of the driver unless
|
| 296 |
instructed to do so when reporting a problem or bug to
|
| 297 |
MySQL AB, as it is not designed to be run in production
|
| 298 |
environments, and will have adverse performance impact
|
| 299 |
when used. The debug binary also depends on the Aspect/J
|
| 300 |
runtime library, which is located in the
|
| 301 |
src/lib/aspectjrt.jar file that comes with the
|
| 302 |
Connector/J distribution.
|
| 303 |
|
| 304 |
1.2.3.2. JDBC-Specific Issues When Upgrading to MySQL Server 4.1 or
|
| 305 |
Newer
|
| 306 |
|
| 307 |
* Using the UTF-8 Character Encoding - Prior to MySQL
|
| 308 |
server version 4.1, the UTF-8 character encoding was not
|
| 309 |
supported by the server, however the JDBC driver could
|
| 310 |
use it, allowing storage of multiple character sets in
|
| 311 |
latin1 tables on the server.
|
| 312 |
Starting with MySQL-4.1, this functionality is
|
| 313 |
deprecated. If you have applications that rely on this
|
| 314 |
functionality, and can not upgrade them to use the
|
| 315 |
official Unicode character support in MySQL server
|
| 316 |
version 4.1 or newer, you should add the following
|
| 317 |
property to your connection URL:
|
| 318 |
useOldUTF8Behavior=true
|
| 319 |
* Server-side Prepared Statements - Connector/J 3.1 will
|
| 320 |
automatically detect and use server-side prepared
|
| 321 |
statements when they are available (MySQL server version
|
| 322 |
4.1.0 and newer). If your application encounters issues
|
| 323 |
with server-side prepared statements, you can revert to
|
| 324 |
the older client-side emulated prepared statement code
|
| 325 |
that is still presently used for MySQL servers older than
|
| 326 |
4.1.0 with the following connection property:
|
| 327 |
useServerPrepStmts=false
|
| 328 |
|
| 329 |
1.2.4. Installing from the Development Source Tree
|
| 330 |
|
| 331 |
Caution. You should read this section only if you are
|
| 332 |
interested in helping us test our new code. If you just want
|
| 333 |
to get MySQL Connector/J up and running on your system, you
|
| 334 |
should use a standard release distribution.
|
| 335 |
|
| 336 |
To install MySQL Connector/J from the development source
|
| 337 |
tree, make sure that you have the following prerequisites:
|
| 338 |
* Subversion, to check out the sources from our repository
|
| 339 |
(available from http://subversion.tigris.org/).
|
| 340 |
* Apache Ant version 1.6 or newer (available from
|
| 341 |
http://ant.apache.org/).
|
| 342 |
* JDK-1.4.2 or later. Although MySQL Connector/J can be
|
| 343 |
installed on older JDKs, to compile it from source you
|
| 344 |
must have at least JDK-1.4.2.
|
| 345 |
|
| 346 |
The Subversion source code repository for MySQL Connector/J
|
| 347 |
is located at http://svn.mysql.com/svnpublic/connector-j. In
|
| 348 |
general, you should not check out the entire repository
|
| 349 |
because it contains every branch and tag for MySQL
|
| 350 |
Connector/J and is quite large.
|
| 351 |
|
| 352 |
To check out and compile a specific branch of MySQL
|
| 353 |
Connector/J, follow these steps:
|
| 354 |
1. At the time of this writing, there are three active
|
| 355 |
branches of Connector/J: branch_3_0, branch_3_1 and
|
| 356 |
branch_5_0. Check out the latest code from the branch
|
| 357 |
that you want with the following command (replacing
|
| 358 |
[major] and [minor] with appropriate version numbers):
|
| 359 |
shell> svn co �
|
| 360 |
http://svn.mysql.com/svnpublic/connector-j/branches/branch_[major]_[mi
|
| 361 |
nor]/connector-j
|
| 362 |
This creates a connector-j subdirectory in the current
|
| 363 |
directory that contains the latest sources for the
|
| 364 |
requested branch.
|
| 365 |
2. Change location to the connector-j directory to make it
|
| 366 |
your current working directory:
|
| 367 |
shell> cd connector-j
|
| 368 |
3. Issue the following command to compile the driver and
|
| 369 |
create a .jar file suitable for installation:
|
| 370 |
shell> ant dist
|
| 371 |
This creates a build directory in the current directory,
|
| 372 |
where all build output will go. A directory is created in
|
| 373 |
the build directory that includes the version number of
|
| 374 |
the sources you are building from. This directory
|
| 375 |
contains the sources, compiled .class files, and a .jar
|
| 376 |
file suitable for deployment. For other possible targets,
|
| 377 |
including ones that will create a fully packaged
|
| 378 |
distribution, issue the following command:
|
| 379 |
shell> ant --projecthelp
|
| 380 |
4. A newly created .jar file containing the JDBC driver will
|
| 381 |
be placed in the directory
|
| 382 |
build/mysql-connector-java-[version].
|
| 383 |
Install the newly created JDBC driver as you would a
|
| 384 |
binary .jar file that you download from MySQL by
|
| 385 |
following the instructions in Section A.2.2, "Installing
|
| 386 |
the Driver and Configuring the CLASSPATH."
|
| 387 |
|
| 388 |
1.3. Connector/J Examples
|
| 389 |
|
| 390 |
Examples of using Connector/J are located throughout this
|
| 391 |
document, this section provides a summary and links to these
|
| 392 |
examples.
|
| 393 |
* Section A.5.1.1, "Obtaining a connection from the
|
| 394 |
DriverManager"
|
| 395 |
* Section A.5.1.2, "Using java.sql.Statement to execute a
|
| 396 |
SELECT query"
|
| 397 |
* Section A.5.1.3, "Stored Procedures"
|
| 398 |
* Section A.5.1.3, "Using Connection.prepareCall()"
|
| 399 |
* Section A.5.1.3, "Registering output parameters"
|
| 400 |
* Section A.5.1.3, "Setting CallableStatement input
|
| 401 |
parameters"
|
| 402 |
* Section A.5.1.3, "Retrieving results and output parameter
|
| 403 |
values"
|
| 404 |
* Section A.5.1.4, "Retrieving AUTO_INCREMENT column values
|
| 405 |
using Statement.getGeneratedKeys()"
|
| 406 |
* Section A.5.1.4, "Retrieving AUTO_INCREMENT column values
|
| 407 |
using SELECT LAST_INSERT_ID()"
|
| 408 |
* Section A.5.1.4, "Retrieving AUTO_INCREMENT column values
|
| 409 |
in Updatable ResultSets"
|
| 410 |
* Section A.5.2.1.1, "Using a connection pool with a J2EE
|
| 411 |
application server"
|
| 412 |
* Section A.5.3, "Example of transaction with retry logic"
|
| 413 |
|
| 414 |
1.4. Connector/J (JDBC) Reference
|
| 415 |
|
| 416 |
This section of the manual contains reference material for
|
| 417 |
MySQL Connector/J, some of which is automatically generated
|
| 418 |
during the Connector/J build process.
|
| 419 |
|
| 420 |
1.4.1. Driver/Datasource Class Names, URL Syntax and Configuration
|
| 421 |
Properties for Connector/J
|
| 422 |
|
| 423 |
The name of the class that implements java.sql.Driver in
|
| 424 |
MySQL Connector/J is com.mysql.jdbc.Driver. The
|
| 425 |
org.gjt.mm.mysql.Driver class name is also usable to remain
|
| 426 |
backward-compatible with MM.MySQL. You should use this class
|
| 427 |
name when registering the driver, or when otherwise
|
| 428 |
configuring software to use MySQL Connector/J.
|
| 429 |
|
| 430 |
The JDBC URL format for MySQL Connector/J is as follows, with
|
| 431 |
items in square brackets ([, ]) being optional:
|
| 432 |
jdbc:mysql://[host][,failoverhost...][:port]/[database] �
|
| 433 |
[?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]...
|
| 434 |
|
| 435 |
If the hostname is not specified, it defaults to 127.0.0.1.
|
| 436 |
If the port is not specified, it defaults to 3306, the
|
| 437 |
default port number for MySQL servers.
|
| 438 |
jdbc:mysql://[host:port],[host:port].../[database] �
|
| 439 |
[?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]...
|
| 440 |
|
| 441 |
If the database is not specified, the connection will be made
|
| 442 |
with no default database. In this case, you will need to
|
| 443 |
either call the setCatalog() method on the Connection
|
| 444 |
instance or fully-specify table names using the database name
|
| 445 |
(i.e. SELECT dbname.tablename.colname FROM
|
| 446 |
dbname.tablename...) in your SQL. Not specifying the database
|
| 447 |
to use upon connection is generally only useful when building
|
| 448 |
tools that work with multiple databases, such as GUI database
|
| 449 |
managers.
|
| 450 |
|
| 451 |
MySQL Connector/J has fail-over support. This allows the
|
| 452 |
driver to fail-over to any number of slave hosts and still
|
| 453 |
perform read-only queries. Fail-over only happens when the
|
| 454 |
connection is in an autoCommit(true) state, because fail-over
|
| 455 |
can not happen reliably when a transaction is in progress.
|
| 456 |
Most application servers and connection pools set autoCommit
|
| 457 |
to true at the end of every transaction/connection use.
|
| 458 |
|
| 459 |
The fail-over functionality has the following behavior:
|
| 460 |
* If the URL property autoReconnect is false: Failover only
|
| 461 |
happens at connection initialization, and failback occurs
|
| 462 |
when the driver determines that the first host has become
|
| 463 |
available again.
|
| 464 |
* If the URL property autoReconnect is true: Failover
|
| 465 |
happens when the driver determines that the connection
|
| 466 |
has failed (before every query), and falls back to the
|
| 467 |
first host when it determines that the host has become
|
| 468 |
available again (after queriesBeforeRetryMaster queries
|
| 469 |
have been issued).
|
| 470 |
|
| 471 |
In either case, whenever you are connected to a "failed-over"
|
| 472 |
server, the connection will be set to read-only state, so
|
| 473 |
queries that would modify data will have exceptions thrown
|
| 474 |
(the query will never be processed by the MySQL server).
|
| 475 |
|
| 476 |
Configuration properties define how Connector/J will make a
|
| 477 |
connection to a MySQL server. Unless otherwise noted,
|
| 478 |
properties can be set for a DataSource object or for a
|
| 479 |
Connection object.
|
| 480 |
|
| 481 |
Configuration Properties can be set in one of the following
|
| 482 |
ways:
|
| 483 |
* Using the set*() methods on MySQL implementations of
|
| 484 |
java.sql.DataSource (which is the preferred method when
|
| 485 |
using implementations of java.sql.DataSource):
|
| 486 |
+ com.mysql.jdbc.jdbc2.optional.MysqlDataSource
|
| 487 |
+ com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDat
|
| 488 |
aSource
|
| 489 |
* As a key/value pair in the java.util.Properties instance
|
| 490 |
passed to DriverManager.getConnection() or
|
| 491 |
Driver.connect()
|
| 492 |
* As a JDBC URL parameter in the URL given to
|
| 493 |
java.sql.DriverManager.getConnection(),
|
| 494 |
java.sql.Driver.connect() or the MySQL implementations of
|
| 495 |
the javax.sql.DataSource setURL() method.
|
| 496 |
Note. If the mechanism you use to configure a JDBC URL
|
| 497 |
is XML-based, you will need to use the XML character
|
| 498 |
literal & to separate configuration parameters, as
|
| 499 |
the ampersand is a reserved character for XML.
|
| 500 |
|
| 501 |
The properties are listed in the following tables.
|
| 502 |
|
| 503 |
Connection/Authentication.
|
| 504 |
Property Name Definition Default Value Since Version
|
| 505 |
user The user to connect as all
|
| 506 |
password The password to use when connecting all
|
| 507 |
socketFactory The name of the class that the driver should
|
| 508 |
use for creating socket connections to the server. This class
|
| 509 |
must implement the interface 'com.mysql.jdbc.SocketFactory'
|
| 510 |
and have public no-args constructor.
|
| 511 |
com.mysql.jdbc.StandardSocketFactory 3.0.3
|
| 512 |
connectTimeout Timeout for socket connect (in milliseconds),
|
| 513 |
with 0 being no timeout. Only works on JDK-1.4 or newer.
|
| 514 |
Defaults to '0'. 0 3.0.1
|
| 515 |
socketTimeout Timeout on network socket operations (0, the
|
| 516 |
default means no timeout). 0 3.0.1
|
| 517 |
useConfigs Load the comma-delimited list of configuration
|
| 518 |
properties before parsing the URL or applying user-specified
|
| 519 |
properties. These configurations are explained in the
|
| 520 |
'Configurations' of the documentation. 3.1.5
|
| 521 |
interactiveClient Set the CLIENT_INTERACTIVE flag, which
|
| 522 |
tells MySQL to timeout connections based on
|
| 523 |
INTERACTIVE_TIMEOUT instead of WAIT_TIMEOUT false 3.1.0
|
| 524 |
propertiesTransform An implementation of
|
| 525 |
com.mysql.jdbc.ConnectionPropertiesTransform that the driver
|
| 526 |
will use to modify URL properties passed to the driver before
|
| 527 |
attempting a connection 3.1.4
|
| 528 |
useCompression Use zlib compression when communicating with
|
| 529 |
the server (true/false)? Defaults to 'false'. false 3.0.17
|
| 530 |
|
| 531 |
High Availability and Clustering.
|
| 532 |
Property Name Definition Default Value Since Version
|
| 533 |
autoReconnect Should the driver try to re-establish stale
|
| 534 |
and/or dead connections? If enabled the driver will throw an
|
| 535 |
exception for a queries issued on a stale or dead connection,
|
| 536 |
which belong to the current transaction, but will attempt
|
| 537 |
reconnect before the next query issued on the connection in a
|
| 538 |
new transaction. The use of this feature is not recommended,
|
| 539 |
because it has side effects related to session state and data
|
| 540 |
consistency when applications don'thandle SQLExceptions
|
| 541 |
properly, and is only designed to be used when you are unable
|
| 542 |
to configure your application to handle SQLExceptions
|
| 543 |
resulting from dead andstale connections properly.
|
| 544 |
Alternatively, investigate setting the MySQL server variable
|
| 545 |
"wait_timeout"to some high value rather than the default of 8
|
| 546 |
hours. false 1.1
|
| 547 |
autoReconnectForPools Use a reconnection strategy appropriate
|
| 548 |
for connection pools (defaults to 'false') false 3.1.3
|
| 549 |
failOverReadOnly When failing over in autoReconnect mode,
|
| 550 |
should the connection be set to 'read-only'? true 3.0.12
|
| 551 |
reconnectAtTxEnd If autoReconnect is set to true, should the
|
| 552 |
driver attempt reconnectionsat the end of every transaction?
|
| 553 |
false 3.0.10
|
| 554 |
roundRobinLoadBalance When autoReconnect is enabled, and
|
| 555 |
failoverReadonly is false, should we pick hosts to connect to
|
| 556 |
on a round-robin basis? false 3.1.2
|
| 557 |
queriesBeforeRetryMaster Number of queries to issue before
|
| 558 |
falling back to master when failed over (when using
|
| 559 |
multi-host failover). Whichever condition is met first,
|
| 560 |
'queriesBeforeRetryMaster' or 'secondsBeforeRetryMaster' will
|
| 561 |
cause an attempt to be made to reconnect to the master.
|
| 562 |
Defaults to 50. 50 3.0.2
|
| 563 |
secondsBeforeRetryMaster How long should the driver wait,
|
| 564 |
when failed over, before attempting to reconnect to the
|
| 565 |
master server? Whichever condition is met first,
|
| 566 |
'queriesBeforeRetryMaster' or 'secondsBeforeRetryMaster' will
|
| 567 |
cause an attempt to be made to reconnect to the master. Time
|
| 568 |
in seconds, defaults to 30 30 3.0.2
|
| 569 |
enableDeprecatedAutoreconnect Auto-reconnect functionality is
|
| 570 |
deprecated starting with version 3.2, and will be removed in
|
| 571 |
version 3.3. Set this property to 'true' to disable the check
|
| 572 |
for the feature being configured. false 3.2.1
|
| 573 |
resourceId A globally unique name that identifies the
|
| 574 |
resource that this datasource or connection is connected to,
|
| 575 |
used for XAResource.isSameRM() when the driver can't
|
| 576 |
determine this value based on hostnames used in the URL 5.0.1
|
| 577 |
|
| 578 |
Security.
|
| 579 |
Property Name Definition Default Value Since Version
|
| 580 |
allowMultiQueries Allow the use of ';' to delimit multiple
|
| 581 |
queries during one statement (true/false, defaults to 'false'
|
| 582 |
false 3.1.1
|
| 583 |
useSSL Use SSL when communicating with the server
|
| 584 |
(true/false), defaults to 'false' false 3.0.2
|
| 585 |
requireSSL Require SSL connection if useSSL=true? (defaults
|
| 586 |
to 'false'). false 3.1.0
|
| 587 |
allowUrlInLocalInfile Should the driver allow URLs in 'LOAD
|
| 588 |
DATA LOCAL INFILE' statements? false 3.1.4
|
| 589 |
paranoid Take measures to prevent exposure sensitive
|
| 590 |
information in error messages and clear data structures
|
| 591 |
holding sensitive data when possible? (defaults to 'false')
|
| 592 |
false 3.0.1
|
| 593 |
|
| 594 |
Performance Extensions.
|
| 595 |
Property Name Definition Default Value Since Version
|
| 596 |
metadataCacheSize The number of queries to
|
| 597 |
cacheResultSetMetadata for if cacheResultSetMetaData is set
|
| 598 |
to 'true' (default 50) 50 3.1.1
|
| 599 |
prepStmtCacheSize If prepared statement caching is enabled,
|
| 600 |
how many prepared statements should be cached? 25 3.0.10
|
| 601 |
prepStmtCacheSqlLimit If prepared statement caching is
|
| 602 |
enabled, what's the largest SQL the driver will cache the
|
| 603 |
parsing for? 256 3.0.10
|
| 604 |
useCursorFetch If connected to MySQL > 5.0.2, and
|
| 605 |
setFetchSize() > 0 on a statement, should that statement use
|
| 606 |
cursor-based fetching to retrieve rows? false 5.0.0
|
| 607 |
blobSendChunkSize Chunk to use when sending BLOB/CLOBs via
|
| 608 |
ServerPreparedStatements 1048576 3.1.9
|
| 609 |
cacheCallableStmts Should the driver cache the parsing stage
|
| 610 |
of CallableStatements false 3.1.2
|
| 611 |
cachePrepStmts Should the driver cache the parsing stage of
|
| 612 |
PreparedStatements of client-side prepared statements, the
|
| 613 |
"check" for suitability of server-side prepared and
|
| 614 |
server-side prepared statements themselves? false 3.0.10
|
| 615 |
cacheResultSetMetadata Should the driver cache
|
| 616 |
ResultSetMetaData for Statements and PreparedStatements?
|
| 617 |
(Req. JDK-1.4+, true/false, default 'false') false 3.1.1
|
| 618 |
cacheServerConfiguration Should the driver cache the results
|
| 619 |
of 'SHOW VARIABLES' and 'SHOW COLLATION' on a per-URL basis?
|
| 620 |
false 3.1.5
|
| 621 |
defaultFetchSize The driver will call setFetchSize(n) with
|
| 622 |
this value on all newly-created Statements 0 3.1.9
|
| 623 |
dontTrackOpenResources The JDBC specification requires the
|
| 624 |
driver to automatically track and close resources, however if
|
| 625 |
your application doesn't do a good job of explicitly calling
|
| 626 |
close() on statements or result sets, this can cause memory
|
| 627 |
leakage. Setting this property to true relaxes this
|
| 628 |
constraint, and can be more memory efficient for some
|
| 629 |
applications. false 3.1.7
|
| 630 |
dynamicCalendars Should the driver retrieve the default
|
| 631 |
calendar when required, or cache it per connection/session?
|
| 632 |
false 3.1.5
|
| 633 |
elideSetAutoCommits If using MySQL-4.1 or newer, should the
|
| 634 |
driver only issue 'set autocommit=n' queries when the
|
| 635 |
server's state doesn't match the requested state by
|
| 636 |
Connection.setAutoCommit(boolean)? false 3.1.3
|
| 637 |
holdResultsOpenOverStatementClose Should the driver close
|
| 638 |
result sets on Statement.close() as required by the JDBC
|
| 639 |
specification? false 3.1.7
|
| 640 |
locatorFetchBufferSize If 'emulateLocators' is configured to
|
| 641 |
'true', what size buffer should be used when fetching BLOB
|
| 642 |
data for getBinaryInputStream? 1048576 3.2.1
|
| 643 |
rewriteBatchedStatements Should the driver use multiqueries
|
| 644 |
(irregardless of the setting of "allowMultiQueries") as well
|
| 645 |
as rewriting of prepared statements for INSERT into
|
| 646 |
multi-value inserts when executeBatch() is called? Notice
|
| 647 |
that this has the potential for SQL injection if using plain
|
| 648 |
java.sql.Statements and your code doesn't sanitize input
|
| 649 |
correctly. Notice that for prepared statements, server-side
|
| 650 |
prepared statements can not currently take advantage of this
|
| 651 |
rewrite option, and that if you don't specify stream lengths
|
| 652 |
when using PreparedStatement.set*Stream(),the driver won't be
|
| 653 |
able to determine the optimium number of parameters per batch
|
| 654 |
and you might receive an error from the driver that the
|
| 655 |
resultant packet is too large. Statement.getGeneratedKeys()
|
| 656 |
for these rewritten statements only works when the entire
|
| 657 |
batch includes INSERT statements. false 3.1.13
|
| 658 |
useFastIntParsing Use internal String->Integer conversion
|
| 659 |
routines to avoid excessive object creation? true 3.1.4
|
| 660 |
useJvmCharsetConverters Always use the character encoding
|
| 661 |
routines built into the JVM, rather than using lookup tables
|
| 662 |
for single-byte character sets? (The default of "true" for
|
| 663 |
this is appropriate for newer JVMs true 5.0.1
|
| 664 |
useLocalSessionState Should the driver refer to the internal
|
| 665 |
values of autocommit and transaction isolation that are set
|
| 666 |
by Connection.setAutoCommit() and
|
| 667 |
Connection.setTransactionIsolation(), rather than querying
|
| 668 |
the database? false 3.1.7
|
| 669 |
useReadAheadInput Use newer, optimized non-blocking, buffered
|
| 670 |
input stream when reading from the server? true 3.1.5
|
| 671 |
|
| 672 |
Debuging/Profiling.
|
| 673 |
Property Name Definition Default Value Since Version
|
| 674 |
logger The name of a class that implements
|
| 675 |
'com.mysql.jdbc.log.Log' that will be used to log messages
|
| 676 |
to.(default is 'com.mysql.jdbc.log.StandardLogger', which
|
| 677 |
logs to STDERR) com.mysql.jdbc.log.StandardLogger 3.1.1
|
| 678 |
profileSQL Trace queries and their execution/fetch times to
|
| 679 |
the configured logger (true/false) defaults to 'false' false
|
| 680 |
3.1.0
|
| 681 |
reportMetricsIntervalMillis If 'gatherPerfMetrics' is
|
| 682 |
enabled, how often should they be logged (in ms)? 30000 3.1.2
|
| 683 |
maxQuerySizeToLog Controls the maximum length/size of a query
|
| 684 |
that will get logged when profiling or tracing 2048 3.1.3
|
| 685 |
packetDebugBufferSize The maximum number of packets to retain
|
| 686 |
when 'enablePacketDebug' is true 20 3.1.3
|
| 687 |
slowQueryThresholdMillis If 'logSlowQueries' is enabled, how
|
| 688 |
long should a query (in ms) before it is logged as 'slow'?
|
| 689 |
2000 3.1.2
|
| 690 |
useUsageAdvisor Should the driver issue 'usage' warnings
|
| 691 |
advising proper and efficient usage of JDBC and MySQL
|
| 692 |
Connector/J to the log (true/false, defaults to 'false')?
|
| 693 |
false 3.1.1
|
| 694 |
autoGenerateTestcaseScript Should the driver dump the SQL it
|
| 695 |
is executing, including server-side prepared statements to
|
| 696 |
STDERR? false 3.1.9
|
| 697 |
dumpMetadataOnColumnNotFound Should the driver dump the
|
| 698 |
field-level metadata of a result set into the exception
|
| 699 |
message when ResultSet.findColumn() fails? false 3.1.13
|
| 700 |
dumpQueriesOnException Should the driver dump the contents of
|
| 701 |
the query sent to the server in the message for
|
| 702 |
SQLExceptions? false 3.1.3
|
| 703 |
enablePacketDebug When enabled, a ring-buffer of
|
| 704 |
'packetDebugBufferSize' packets will be kept, and dumped when
|
| 705 |
exceptions are thrown in key areas in the driver's code false
|
| 706 |
3.1.3
|
| 707 |
explainSlowQueries If 'logSlowQueries' is enabled, should the
|
| 708 |
driver automatically issue an 'EXPLAIN' on the server and
|
| 709 |
send the results to the configured log at a WARN level? false
|
| 710 |
3.1.2
|
| 711 |
logSlowQueries Should queries that take longer than
|
| 712 |
'slowQueryThresholdMillis' be logged? false 3.1.2
|
| 713 |
traceProtocol Should trace-level network protocol be logged?
|
| 714 |
false 3.1.2
|
| 715 |
|
| 716 |
Miscellaneous.
|
| 717 |
Property Name Definition Default Value Since Version
|
| 718 |
useUnicode Should the driver use Unicode character encodings
|
| 719 |
when handling strings? Should only be used when the driver
|
| 720 |
can't determine the character set mapping, or you are trying
|
| 721 |
to 'force' the driver to use a character set that MySQL
|
| 722 |
either doesn't natively support (such as UTF-8), true/false,
|
| 723 |
defaults to 'true' true 1.1g
|
| 724 |
characterEncoding If 'useUnicode' is set to true, what
|
| 725 |
character encoding should the driver use when dealing with
|
| 726 |
strings? (defaults is to 'autodetect') 1.1g
|
| 727 |
characterSetResults Character set to tell the server to
|
| 728 |
return results as. 3.0.13
|
| 729 |
connectionCollation If set, tells the server to use this
|
| 730 |
collation via 'set collation_connection' 3.0.13
|
| 731 |
sessionVariables A comma-separated list of name/value pairs
|
| 732 |
to be sent as SET SESSION ... to the server when the driver
|
| 733 |
connects. 3.1.8
|
| 734 |
allowNanAndInf Should the driver allow NaN or +/- INF values
|
| 735 |
in PreparedStatement.setDouble()? false 3.1.5
|
| 736 |
autoClosePStmtStreams Should the driver automatically call
|
| 737 |
.close() on streams/readers passed as arguments via set*()
|
| 738 |
methods? false 3.1.12
|
| 739 |
autoDeserialize Should the driver automatically detect and
|
| 740 |
de-serialize objects stored in BLOB fields? false 3.1.5
|
| 741 |
capitalizeTypeNames Capitalize type names in
|
| 742 |
DatabaseMetaData? (usually only useful when using WebObjects,
|
| 743 |
true/false, defaults to 'false') false 2.0.7
|
| 744 |
clobCharacterEncoding The character encoding to use for
|
| 745 |
sending and retrieving TEXT, MEDIUMTEXT and LONGTEXT values
|
| 746 |
instead of the configured connection characterEncoding 5.0.0
|
| 747 |
clobberStreamingResults This will cause a 'streaming'
|
| 748 |
ResultSet to be automatically closed, and any outstanding
|
| 749 |
data still streaming from the server to be discarded if
|
| 750 |
another query is executed before all the data has been read
|
| 751 |
from the server. false 3.0.9
|
| 752 |
continueBatchOnError Should the driver continue processing
|
| 753 |
batch commands if one statement fails. The JDBC spec allows
|
| 754 |
either way (defaults to 'true'). true 3.0.3
|
| 755 |
createDatabaseIfNotExist Creates the database given in the
|
| 756 |
URL if it doesn't yet exist. Assumes the configured user has
|
| 757 |
permissions to create databases. false 3.1.9
|
| 758 |
emptyStringsConvertToZero Should the driver allow conversions
|
| 759 |
from empty string fields to numeric values of '0'? true 3.1.8
|
| 760 |
emulateLocators N/A false 3.1.0
|
| 761 |
emulateUnsupportedPstmts Should the driver detect prepared
|
| 762 |
statements that are not supported by the server, and replace
|
| 763 |
them with client-side emulated versions? true 3.1.7
|
| 764 |
ignoreNonTxTables Ignore non-transactional table warning for
|
| 765 |
rollback? (defaults to 'false'). false 3.0.9
|
| 766 |
jdbcCompliantTruncation Should the driver throw
|
| 767 |
java.sql.DataTruncation exceptions when data is truncated as
|
| 768 |
is required by the JDBC specification when connected to a
|
| 769 |
server that supports warnings(MySQL 4.1.0 and newer)? true
|
| 770 |
3.1.2
|
| 771 |
maxRows The maximum number of rows to return (0, the default
|
| 772 |
means return all rows). -1 all versions
|
| 773 |
noAccessToProcedureBodies When determining procedure
|
| 774 |
parameter types for CallableStatements, and the connected
|
| 775 |
user can't access procedure bodies through "SHOW CREATE
|
| 776 |
PROCEDURE" or select on mysql.proc should the driver instead
|
| 777 |
create basic metadata (all parameters reported as INOUT
|
| 778 |
VARCHARs) instead of throwing an exception? false 5.0.3
|
| 779 |
noDatetimeStringSync Don't ensure that
|
| 780 |
ResultSet.getDatetimeType().toString().equals(ResultSet.getSt
|
| 781 |
ring()) false 3.1.7
|
| 782 |
noTimezoneConversionForTimeType Don't convert TIME values
|
| 783 |
using the server timezone if 'useTimezone'='true' false 5.0.0
|
| 784 |
nullCatalogMeansCurrent When DatabaseMetadataMethods ask for
|
| 785 |
a 'catalog' parameter, does the value null mean use the
|
| 786 |
current catalog? (this is not JDBC-compliant, but follows
|
| 787 |
legacy behavior from earlier versions of the driver) true
|
| 788 |
3.1.8
|
| 789 |
nullNamePatternMatchesAll Should DatabaseMetaData methods
|
| 790 |
that accept *pattern parameters treat null the same as '%'
|
| 791 |
(this is not JDBC-compliant, however older versions of the
|
| 792 |
driver accepted this departure from the specification) true
|
| 793 |
3.1.8
|
| 794 |
overrideSupportsIntegrityEnhancementFacility Should the
|
| 795 |
driver return "true" for
|
| 796 |
DatabaseMetaData.supportsIntegrityEnhancementFacility() even
|
| 797 |
if the database doesn't support it to workaround applications
|
| 798 |
that require this method to return "true" to signal support
|
| 799 |
of foreign keys, even though the SQL specification states
|
| 800 |
that this facility contains much more than just foreign key
|
| 801 |
support (one such application being OpenOffice)? false 3.1.12
|
| 802 |
pedantic Follow the JDBC spec to the letter. false 3.0.0
|
| 803 |
pinGlobalTxToPhysicalConnection When using XAConnections,
|
| 804 |
should the driver ensure that operations on a given XID are
|
| 805 |
always routed to the same physical connection? This allows
|
| 806 |
the XAConnection to support "XA START ... JOIN" after "XA
|
| 807 |
END" has been called false 5.0.1
|
| 808 |
processEscapeCodesForPrepStmts Should the driver process
|
| 809 |
escape codes in queries that are prepared? true 3.1.12
|
| 810 |
relaxAutoCommit If the version of MySQL the driver connects
|
| 811 |
to does not support transactions, still allow calls to
|
| 812 |
commit(), rollback() and setAutoCommit() (true/false,
|
| 813 |
defaults to 'false')? false 2.0.13
|
| 814 |
retainStatementAfterResultSetClose Should the driver retain
|
| 815 |
the Statement reference in a ResultSet after
|
| 816 |
ResultSet.close() has been called. This is not JDBC-compliant
|
| 817 |
after JDBC-4.0. false 3.1.11
|
| 818 |
rollbackOnPooledClose Should the driver issue a rollback()
|
| 819 |
when the logical connection in a pool is closed? true 3.0.15
|
| 820 |
runningCTS13 Enables workarounds for bugs in Sun's JDBC
|
| 821 |
compliance testsuite version 1.3 false 3.1.7
|
| 822 |
serverTimezone Override detection/mapping of timezone. Used
|
| 823 |
when timezone from server doesn't map to Java timezone 3.0.2
|
| 824 |
strictFloatingPoint Used only in older versions of compliance
|
| 825 |
test false 3.0.0
|
| 826 |
strictUpdates Should the driver do strict checking (all
|
| 827 |
primary keys selected) of updatable result sets (true, false,
|
| 828 |
defaults to 'true')? true 3.0.4
|
| 829 |
tinyInt1isBit Should the driver treat the datatype TINYINT(1)
|
| 830 |
as the BIT type (because the server silently converts BIT ->
|
| 831 |
TINYINT(1) when creating tables)? true 3.0.16
|
| 832 |
transformedBitIsBoolean If the driver converts TINYINT(1) to
|
| 833 |
a different type, should it use BOOLEAN instead of BIT for
|
| 834 |
future compatibility with MySQL-5.0, as MySQL-5.0 has a BIT
|
| 835 |
type? false 3.1.9
|
| 836 |
ultraDevHack Create PreparedStatements for prepareCall() when
|
| 837 |
required, because UltraDev is broken and issues a
|
| 838 |
prepareCall() for _all_ statements? (true/false, defaults to
|
| 839 |
'false') false 2.0.3
|
| 840 |
useGmtMillisForDatetimes Convert between session timezone and
|
| 841 |
GMT before creating Date and Timestamp instances (value of
|
| 842 |
"false" is legacy behavior, "true" leads to more
|
| 843 |
JDBC-compliant behavior. false 3.1.12
|
| 844 |
useHostsInPrivileges Add '@hostname' to users in
|
| 845 |
DatabaseMetaData.getColumn/TablePrivileges() (true/false),
|
| 846 |
defaults to 'true'. true 3.0.2
|
| 847 |
useInformationSchema When connected to MySQL-5.0.7 or newer,
|
| 848 |
should the driver use the INFORMATION_SCHEMA to derive
|
| 849 |
information used by DatabaseMetaData? false 5.0.0
|
| 850 |
useJDBCCompliantTimezoneShift Should the driver use
|
| 851 |
JDBC-compliant rules when converting TIME/TIMESTAMP/DATETIME
|
| 852 |
values' timezone information for those JDBC arguments which
|
| 853 |
take a java.util.Calendar argument? (Notice that this option
|
| 854 |
is exclusive of the "useTimezone=true" configuration option.)
|
| 855 |
false 5.0.0
|
| 856 |
useOldAliasMetadataBehavior Should the driver use the legacy
|
| 857 |
behavior for "AS" clauses on columns and tables, and only
|
| 858 |
return aliases (if any) for ResultSetMetaData.getColumnName()
|
| 859 |
or ResultSetMetaData.getTableName() rather than the original
|
| 860 |
column/table name? true 5.0.4
|
| 861 |
useOldUTF8Behavior Use the UTF-8 behavior the driver did when
|
| 862 |
communicating with 4.0 and older servers false 3.1.6
|
| 863 |
useOnlyServerErrorMessages Don't prepend 'standard' SQLState
|
| 864 |
error messages to error messages returned by the server. true
|
| 865 |
3.0.15
|
| 866 |
useServerPrepStmts Use server-side prepared statements if the
|
| 867 |
server supports them? (defaults to 'true'). true 3.1.0
|
| 868 |
useSqlStateCodes Use SQL Standard state codes instead of
|
| 869 |
'legacy' X/Open/SQL state codes (true/false), default is
|
| 870 |
'true' true 3.1.3
|
| 871 |
useStreamLengthsInPrepStmts Honor stream length parameter in
|
| 872 |
PreparedStatement/ResultSet.setXXXStream() method calls
|
| 873 |
(true/false, defaults to 'true')? true 3.0.2
|
| 874 |
useTimezone Convert time/date types between client and server
|
| 875 |
timezones (true/false, defaults to 'false')? false 3.0.2
|
| 876 |
useUnbufferedInput Don't use BufferedInputStream for reading
|
| 877 |
data from the server true 3.0.11
|
| 878 |
yearIsDateType Should the JDBC driver treat the MySQL type
|
| 879 |
"YEAR" as a java.sql.Date, or as a SHORT? true 3.1.9
|
| 880 |
zeroDateTimeBehavior What should happen when the driver
|
| 881 |
encounters DATETIME values that are composed entirely of
|
| 882 |
zeroes (used by MySQL to represent invalid dates)? Valid
|
| 883 |
values are 'exception', 'round' and 'convertToNull'.
|
| 884 |
exception 3.1.4
|
| 885 |
|
| 886 |
Connector/J also supports access to MySQL via named pipes on
|
| 887 |
Windows NT/2000/XP using the NamedPipeSocketFactory as a
|
| 888 |
plugin-socket factory via the socketFactory property. If you
|
| 889 |
don't use a namedPipePath property, the default of
|
| 890 |
'\\.\pipe\MySQL' will be used. If you use the
|
| 891 |
NamedPipeSocketFactory, the hostname and port number values
|
| 892 |
in the JDBC url will be ignored. You can enable this feature
|
| 893 |
using:
|
| 894 |
socketFactory=com.mysql.jdbc.NamedPipeSocketFactory
|
| 895 |
|
| 896 |
Named pipes only work when connecting to a MySQL server on
|
| 897 |
the same physical machine as the one the JDBC driver is being
|
| 898 |
used on. In simple performance tests, it appears that named
|
| 899 |
pipe access is between 30%-50% faster than the standard
|
| 900 |
TCP/IP access.
|
| 901 |
|
| 902 |
You can create your own socket factories by following the
|
| 903 |
example code in com.mysql.jdbc.NamedPipeSocketFactory, or
|
| 904 |
com.mysql.jdbc.StandardSocketFactory.
|
| 905 |
|
| 906 |
1.4.2. JDBC API Implementation Notes
|
| 907 |
|
| 908 |
MySQL Connector/J passes all of the tests in the
|
| 909 |
publicly-available version of Sun's JDBC compliance test
|
| 910 |
suite. However, in many places the JDBC specification is
|
| 911 |
vague about how certain functionality should be implemented,
|
| 912 |
or the specification allows leeway in implementation.
|
| 913 |
|
| 914 |
This section gives details on a interface-by-interface level
|
| 915 |
about how certain implementation decisions may affect how you
|
| 916 |
use MySQL Connector/J.
|
| 917 |
* Blob
|
| 918 |
The Blob implementation does not allow in-place
|
| 919 |
modification (they are copies, as reported by the
|
| 920 |
DatabaseMetaData.locatorsUpdateCopies() method). Because
|
| 921 |
of this, you should use the corresponding
|
| 922 |
PreparedStatement.setBlob() or ResultSet.updateBlob() (in
|
| 923 |
the case of updatable result sets) methods to save
|
| 924 |
changes back to the database.
|
| 925 |
Starting with Connector/J version 3.1.0, you can emulate
|
| 926 |
Blobs with locators by adding the property
|
| 927 |
'emulateLocators=true' to your JDBC URL. You must then
|
| 928 |
use a column alias with the value of the column set to
|
| 929 |
the actual name of the Blob column in the SELECT that you
|
| 930 |
write to retrieve the Blob. The SELECT must also
|
| 931 |
reference only one table, the table must have a primary
|
| 932 |
key, and the SELECT must cover all columns that make up
|
| 933 |
the primary key. The driver will then delay loading the
|
| 934 |
actual Blob data until you retrieve the Blob and call
|
| 935 |
retrieval methods (getInputStream(), getBytes(), and so
|
| 936 |
forth) on it.
|
| 937 |
* CallableStatement
|
| 938 |
Starting with Connector/J 3.1.1, stored procedures are
|
| 939 |
supported when connecting to MySQL version 5.0 or newer
|
| 940 |
via the CallableStatement interface. Currently, the
|
| 941 |
getParameterMetaData() method of CallableStatement is not
|
| 942 |
supported.
|
| 943 |
* Clob
|
| 944 |
The Clob implementation does not allow in-place
|
| 945 |
modification (they are copies, as reported by the
|
| 946 |
DatabaseMetaData.locatorsUpdateCopies() method). Because
|
| 947 |
of this, you should use the PreparedStatement.setClob()
|
| 948 |
method to save changes back to the database. The JDBC API
|
| 949 |
does not have a ResultSet.updateClob() method.
|
| 950 |
* Connection
|
| 951 |
Unlike older versions of MM.MySQL the isClosed() method
|
| 952 |
does not ping the server to determine if it is alive. In
|
| 953 |
accordance with the JDBC specification, it only returns
|
| 954 |
true if closed() has been called on the connection. If
|
| 955 |
you need to determine if the connection is still valid,
|
| 956 |
you should issue a simple query, such as SELECT 1. The
|
| 957 |
driver will throw an exception if the connection is no
|
| 958 |
longer valid.
|
| 959 |
* DatabaseMetaData
|
| 960 |
Foreign Key information
|
| 961 |
(getImportedKeys()/getExportedKeys() and
|
| 962 |
getCrossReference()) is only available from InnoDB
|
| 963 |
tables. However, the driver uses SHOW CREATE TABLE to
|
| 964 |
retrieve this information, so when other storage engines
|
| 965 |
support foreign keys, the driver will transparently
|
| 966 |
support them as well.
|
| 967 |
* PreparedStatement
|
| 968 |
PreparedStatements are implemented by the driver, as
|
| 969 |
MySQL does not have a prepared statement feature. Because
|
| 970 |
of this, the driver does not implement
|
| 971 |
getParameterMetaData() or getMetaData() as it would
|
| 972 |
require the driver to have a complete SQL parser in the
|
| 973 |
client.
|
| 974 |
Starting with version 3.1.0 MySQL Connector/J,
|
| 975 |
server-side prepared statements and binary-encoded result
|
| 976 |
sets are used when the server supports them.
|
| 977 |
Take care when using a server-side prepared statement
|
| 978 |
with large parameters that are set via setBinaryStream(),
|
| 979 |
setAsciiStream(), setUnicodeStream(), setBlob(), or
|
| 980 |
setClob(). If you want to re-execute the statement with
|
| 981 |
any large parameter changed to a non-large parameter, it
|
| 982 |
is necessary to call clearParameters() and set all
|
| 983 |
parameters again. The reason for this is as follows:
|
| 984 |
+ The driver streams the large data out-of-band to the
|
| 985 |
prepared statement on the server side when the
|
| 986 |
parameter is set (before execution of the prepared
|
| 987 |
statement).
|
| 988 |
+ Once that has been done, the stream used to read the
|
| 989 |
data on the client side is closed (as per the JDBC
|
| 990 |
spec), and can't be read from again.
|
| 991 |
+ If a parameter changes from large to non-large, the
|
| 992 |
driver must reset the server-side state of the
|
| 993 |
prepared statement to allow the parameter that is
|
| 994 |
being changed to take the place of the prior large
|
| 995 |
value. This removes all of the large data that has
|
| 996 |
already been sent to the server, thus requiring the
|
| 997 |
data to be re-sent, via the setBinaryStream(),
|
| 998 |
setAsciiStream(), setUnicodeStream(), setBlob() or
|
| 999 |
setClob() methods.
|
| 1000 |
Consequently, if you want to change the type of a
|
| 1001 |
parameter to a non-large one, you must call
|
| 1002 |
clearParameters() and set all parameters of the prepared
|
| 1003 |
statement again before it can be re-executed.
|
| 1004 |
* ResultSet
|
| 1005 |
By default, ResultSets are completely retrieved and
|
| 1006 |
stored in memory. In most cases this is the most
|
| 1007 |
efficient way to operate, and due to the design of the
|
| 1008 |
MySQL network protocol is easier to implement. If you are
|
| 1009 |
working with ResultSets that have a large number of rows
|
| 1010 |
or large values, and can not allocate heap space in your
|
| 1011 |
JVM for the memory required, you can tell the driver to
|
| 1012 |
stream the results back one row at a time.
|
| 1013 |
To enable this functionality, you need to create a
|
| 1014 |
Statement instance in the following manner:
|
| 1015 |
stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
|
| 1016 |
java.sql.ResultSet.CONCUR_READ_ONLY);
|
| 1017 |
stmt.setFetchSize(Integer.MIN_VALUE);
|
| 1018 |
The combination of a forward-only, read-only result set,
|
| 1019 |
with a fetch size of Integer.MIN_VALUE serves as a signal
|
| 1020 |
to the driver to stream result sets row-by-row. After
|
| 1021 |
this any result sets created with the statement will be
|
| 1022 |
retrieved row-by-row.
|
| 1023 |
There are some caveats with this approach. You will have
|
| 1024 |
to read all of the rows in the result set (or close it)
|
| 1025 |
before you can issue any other queries on the connection,
|
| 1026 |
or an exception will be thrown.
|
| 1027 |
The earliest the locks these statements hold can be
|
| 1028 |
released (whether they be MyISAM table-level locks or
|
| 1029 |
row-level locks in some other storage engine such as
|
| 1030 |
InnoDB) is when the statement completes.
|
| 1031 |
If the statement is within scope of a transaction, then
|
| 1032 |
locks are released when the transaction completes (which
|
| 1033 |
implies that the statement needs to complete first). As
|
| 1034 |
with most other databases, statements are not complete
|
| 1035 |
until all the results pending on the statement are read
|
| 1036 |
or the active result set for the statement is closed.
|
| 1037 |
Therefore, if using streaming results, you should process
|
| 1038 |
them as quickly as possible if you want to maintain
|
| 1039 |
concurrent access to the tables referenced by the
|
| 1040 |
statement producing the result set.
|
| 1041 |
* ResultSetMetaData
|
| 1042 |
The isAutoIncrement() method only works when using MySQL
|
| 1043 |
servers 4.0 and newer.
|
| 1044 |
* Statement
|
| 1045 |
When using versions of the JDBC driver earlier than
|
| 1046 |
3.2.1, and connected to server versions earlier than
|
| 1047 |
5.0.3, the "setFetchSize()" method has no effect, other
|
| 1048 |
than to toggle result set streaming as described above.
|
| 1049 |
MySQL does not support SQL cursors, and the JDBC driver
|
| 1050 |
doesn't emulate them, so "setCursorName()" has no effect.
|
| 1051 |
|
| 1052 |
1.4.3. Java, JDBC and MySQL Types
|
| 1053 |
|
| 1054 |
MySQL Connector/J is flexible in the way it handles
|
| 1055 |
conversions between MySQL data types and Java data types.
|
| 1056 |
|
| 1057 |
In general, any MySQL data type can be converted to a
|
| 1058 |
java.lang.String, and any numerical type can be converted to
|
| 1059 |
any of the Java numerical types, although round-off,
|
| 1060 |
overflow, or loss of precision may occur.
|
| 1061 |
|
| 1062 |
Starting with Connector/J 3.1.0, the JDBC driver will issue
|
| 1063 |
warnings or throw DataTruncation exceptions as is required by
|
| 1064 |
the JDBC specification unless the connection was configured
|
| 1065 |
not to do so by using the property jdbcCompliantTruncation
|
| 1066 |
and setting it to false.
|
| 1067 |
|
| 1068 |
The conversions that are always guaranteed to work are listed
|
| 1069 |
in the following table:
|
| 1070 |
|
| 1071 |
Connection Properties - Miscellaneous.
|
| 1072 |
These MySQL Data Types Can always be converted to these Java
|
| 1073 |
types
|
| 1074 |
CHAR, VARCHAR, BLOB, TEXT, ENUM, and SET java.lang.String,
|
| 1075 |
java.io.InputStream, java.io.Reader, java.sql.Blob,
|
| 1076 |
java.sql.Clob
|
| 1077 |
FLOAT, REAL, DOUBLE PRECISION, NUMERIC, DECIMAL, TINYINT,
|
| 1078 |
SMALLINT, MEDIUMINT, INTEGER, BIGINT java.lang.String,
|
| 1079 |
java.lang.Short, java.lang.Integer, java.lang.Long,
|
| 1080 |
java.lang.Double, java.math.BigDecimal
|
| 1081 |
DATE, TIME, DATETIME, TIMESTAMP java.lang.String,
|
| 1082 |
java.sql.Date, java.sql.Timestamp
|
| 1083 |
|
| 1084 |
Note: round-off, overflow or loss of precision may occur if
|
| 1085 |
you choose a Java numeric data type that has less precision
|
| 1086 |
or capacity than the MySQL data type you are converting
|
| 1087 |
to/from.
|
| 1088 |
|
| 1089 |
The ResultSet.getObject() method uses the type conversions
|
| 1090 |
between MySQL and Java types, following the JDBC
|
| 1091 |
specification where appropriate. The value returned by
|
| 1092 |
ResultSetMetaData.GetColumnClassName() is also shown below.
|
| 1093 |
For more information on the java.sql.Types classes see Java 2
|
| 1094 |
Platform Types
|
| 1095 |
(http://java.sun.com/j2se/1.4.2/docs/api/java/sql/Types.html)
|
| 1096 |
.
|
| 1097 |
|
| 1098 |
MySQL Types to Java Types for ResultSet.getObject().
|
| 1099 |
MySQL Type Name Return value of GetColumnClassName Returned
|
| 1100 |
as Java Class
|
| 1101 |
BIT(1) (new in MySQL-5.0) BIT java.lang.Boolean
|
| 1102 |
BIT( > 1) (new in MySQL-5.0) BIT byte[]
|
| 1103 |
TINYINT TINYINT java.lang.Boolean if the configuration
|
| 1104 |
property tinyInt1isBit is set to true (the default) and the
|
| 1105 |
storage size is 1, or java.lang.Integer if not.
|
| 1106 |
BOOL, BOOLEAN TINYINT See TINYINT, above as these are aliases
|
| 1107 |
for TINYINT(1), currently.
|
| 1108 |
SMALLINT[(M)] [UNSIGNED] SMALLINT [UNSIGNED]
|
| 1109 |
java.lang.Integer (regardless if UNSIGNED or not)
|
| 1110 |
MEDIUMINT[(M)] [UNSIGNED] MEDIUMINT [UNSIGNED]
|
| 1111 |
java.lang.Integer, if UNSIGNED java.lang.Long
|
| 1112 |
INT,INTEGER[(M)] [UNSIGNED] INTEGER [UNSIGNED]
|
| 1113 |
java.lang.Integer, if UNSIGNED java.lang.Long
|
| 1114 |
BIGINT[(M)] [UNSIGNED] BIGINT [UNSIGNED] java.lang.Long, if
|
| 1115 |
UNSIGNED java.math.BigInteger
|
| 1116 |
FLOAT[(M,D)] FLOAT java.lang.Float
|
| 1117 |
DOUBLE[(M,B)] DOUBLE java.lang.Double
|
| 1118 |
DECIMAL[(M[,D])] DECIMAL java.math.BigDecimal
|
| 1119 |
DATE DATE java.sql.Date
|
| 1120 |
DATETIME DATETIME java.sql.Timestamp
|
| 1121 |
TIMESTAMP[(M)] TIMESTAMP java.sql.Timestamp
|
| 1122 |
TIME TIME java.sql.Time
|
| 1123 |
YEAR[(2|4)] YEAR If yearIsDateType configuration property is
|
| 1124 |
set to false, then the returned object type is
|
| 1125 |
java.sql.Short. If set to true (the default) then an object
|
| 1126 |
of type java.sql.Date (with the date set to January 1st, at
|
| 1127 |
midnight).
|
| 1128 |
CHAR(M) CHAR java.lang.String (unless the character set for
|
| 1129 |
the column is BINARY, then byte[] is returned.
|
| 1130 |
VARCHAR(M) [BINARY] VARCHAR java.lang.String (unless the
|
| 1131 |
character set for the column is BINARY, then byte[] is
|
| 1132 |
returned.
|
| 1133 |
BINARY(M) BINARY byte[]
|
| 1134 |
VARBINARY(M) VARBINARY byte[]
|
| 1135 |
TINYBLOB TINYBLOB byte[]
|
| 1136 |
TINYTEXT VARCHAR java.lang.String
|
| 1137 |
BLOB BLOB byte[]
|
| 1138 |
TEXT VARCHAR java.lang.String
|
| 1139 |
MEDIUMBLOB MEDIUMBLOB byte[]
|
| 1140 |
MEDIUMTEXT VARCHAR java.lang.String
|
| 1141 |
LONGBLOB LONGBLOB byte[]
|
| 1142 |
LONGTEXT VARCHAR java.lang.String
|
| 1143 |
ENUM('value1','value2',...) CHAR java.lang.String
|
| 1144 |
SET('value1','value2',...) CHAR java.lang.String
|
| 1145 |
|
| 1146 |
1.4.4. Using Character Sets and Unicode
|
| 1147 |
|
| 1148 |
All strings sent from the JDBC driver to the server are
|
| 1149 |
converted automatically from native Java Unicode form to the
|
| 1150 |
client character encoding, including all queries sent via
|
| 1151 |
Statement.execute(), Statement.executeUpdate(),
|
| 1152 |
Statement.executeQuery() as well as all PreparedStatement and
|
| 1153 |
CallableStatement parameters with the exclusion of parameters
|
| 1154 |
set using setBytes(), setBinaryStream(), setAsciiStream(),
|
| 1155 |
setUnicodeStream() and setBlob() .
|
| 1156 |
|
| 1157 |
Prior to MySQL Server 4.1, Connector/J supported a single
|
| 1158 |
character encoding per connection, which could either be
|
| 1159 |
automatically detected from the server configuration, or
|
| 1160 |
could be configured by the user through the useUnicode and
|
| 1161 |
"characterEncoding" properties.
|
| 1162 |
|
| 1163 |
Starting with MySQL Server 4.1, Connector/J supports a single
|
| 1164 |
character encoding between client and server, and any number
|
| 1165 |
of character encodings for data returned by the server to the
|
| 1166 |
client in ResultSets.
|
| 1167 |
|
| 1168 |
The character encoding between client and server is
|
| 1169 |
automatically detected upon connection. The encoding used by
|
| 1170 |
the driver is specified on the server via the character_set
|
| 1171 |
system variable for server versions older than 4.1.0 and
|
| 1172 |
character_set_server for server versions 4.1.0 and newer. For
|
| 1173 |
more information, see [WARNING: missing xref target
|
| 1174 |
(id=charset-server)]
|
| 1175 |
|
| 1176 |
To override the automatically-detected encoding on the client
|
| 1177 |
side, use the characterEncoding property in the URL used to
|
| 1178 |
connect to the server.
|
| 1179 |
|
| 1180 |
When specifying character encodings on the client side,
|
| 1181 |
Java-style names should be used. The following table lists
|
| 1182 |
Java-style names for MySQL character sets:
|
| 1183 |
|
| 1184 |
MySQL to Java Encoding Name Translations.
|
| 1185 |
MySQL Character Set Name Java-Style Character Encoding Name
|
| 1186 |
ascii US-ASCII
|
| 1187 |
big5 Big5
|
| 1188 |
gbk GBK
|
| 1189 |
sjis SJIS (or Cp932 or MS932 for MySQL Server < 4.1.11)
|
| 1190 |
cp932 Cp932 or MS932 (MySQL Server > 4.1.11)
|
| 1191 |
gb2312 EUC_CN
|
| 1192 |
ujis EUC_JP
|
| 1193 |
euckr EUC_KR
|
| 1194 |
latin1 ISO8859_1
|
| 1195 |
latin2 ISO8859_2
|
| 1196 |
greek ISO8859_7
|
| 1197 |
hebrew ISO8859_8
|
| 1198 |
cp866 Cp866
|
| 1199 |
tis620 TIS620
|
| 1200 |
cp1250 Cp1250
|
| 1201 |
cp1251 Cp1251
|
| 1202 |
cp1257 Cp1257
|
| 1203 |
macroman MacRoman
|
| 1204 |
macce MacCentralEurope
|
| 1205 |
utf8 UTF-8
|
| 1206 |
ucs2 UnicodeBig
|
| 1207 |
|
| 1208 |
Warning. Do not issue the query 'set names' with
|
| 1209 |
Connector/J, as the driver will not detect that the character
|
| 1210 |
set has changed, and will continue to use the character set
|
| 1211 |
detected during the initial connection setup.
|
| 1212 |
|
| 1213 |
To allow multiple character sets to be sent from the client,
|
| 1214 |
the UTF-8 encoding should be used, either by configuring utf8
|
| 1215 |
as the default server character set, or by configuring the
|
| 1216 |
JDBC driver to use UTF-8 through the characterEncoding
|
| 1217 |
property.
|
| 1218 |
|
| 1219 |
1.4.5. Connecting Securely Using SSL
|
| 1220 |
|
| 1221 |
SSL in MySQL Connector/J encrypts all data (other than the
|
| 1222 |
initial handshake) between the JDBC driver and the server.
|
| 1223 |
The performance penalty for enabling SSL is an increase in
|
| 1224 |
query processing time between 35% and 50%, depending on the
|
| 1225 |
size of the query, and the amount of data it returns.
|
| 1226 |
|
| 1227 |
For SSL Support to work, you must have the following:
|
| 1228 |
* A JDK that includes JSSE (Java Secure Sockets Extension),
|
| 1229 |
like JDK-1.4.1 or newer. SSL does not currently work with
|
| 1230 |
a JDK that you can add JSSE to, like JDK-1.2.x or
|
| 1231 |
JDK-1.3.x due to the following JSSE bug:
|
| 1232 |
http://developer.java.sun.com/developer/bugParade/bugs/42
|
| 1233 |
73544.html
|
| 1234 |
* A MySQL server that supports SSL and has been compiled
|
| 1235 |
and configured to do so, which is MySQL-4.0.4 or later,
|
| 1236 |
see [WARNING: missing xref target
|
| 1237 |
(id=secure-connections)] for more information.
|
| 1238 |
* A client certificate (covered later in this section)
|
| 1239 |
|
| 1240 |
You will first need to import the MySQL server CA Certificate
|
| 1241 |
into a Java truststore. A sample MySQL server CA Certificate
|
| 1242 |
is located in the SSL subdirectory of the MySQL source
|
| 1243 |
distribution. This is what SSL will use to determine if you
|
| 1244 |
are communicating with a secure MySQL server.
|
| 1245 |
|
| 1246 |
To use Java's keytool to create a truststore in the current
|
| 1247 |
directory , and import the server's CA certificate
|
| 1248 |
(cacert.pem), you can do the following (assuming that keytool
|
| 1249 |
is in your path. The keytool should be located in the bin
|
| 1250 |
subdirectory of your JDK or JRE):
|
| 1251 |
shell> keytool -import -alias mysqlServerCACert -file cacert.pem -keys
|
| 1252 |
tore truststore
|
| 1253 |
|
| 1254 |
Keytool will respond with the following information:
|
| 1255 |
Enter keystore password: *********
|
| 1256 |
Owner: EMAILADDRESS=walrus@example.com, CN=Walrus, O=MySQL AB, L=Orenb
|
| 1257 |
urg, ST=Some
|
| 1258 |
-State, C=RU
|
| 1259 |
Issuer: EMAILADDRESS=walrus@example.com, CN=Walrus, O=MySQL AB, L=Oren
|
| 1260 |
burg, ST=Som
|
| 1261 |
e-State, C=RU
|
| 1262 |
Serial number: 0
|
| 1263 |
Valid from: Fri Aug 02 16:55:53 CDT 2002 until: Sat Aug 02 16:55:53 CD
|
| 1264 |
T 2003
|
| 1265 |
Certificate fingerprints:
|
| 1266 |
MD5: 61:91:A0:F2:03:07:61:7A:81:38:66:DA:19:C4:8D:AB
|
| 1267 |
SHA1: 25:77:41:05:D5:AD:99:8C:14:8C:CA:68:9C:2F:B8:89:C3:34:4
|
| 1268 |
D:6C
|
| 1269 |
Trust this certificate? [no]: yes
|
| 1270 |
Certificate was added to keystore
|
| 1271 |
|
| 1272 |
You will then need to generate a client certificate, so that
|
| 1273 |
the MySQL server knows that it is talking to a secure client:
|
| 1274 |
shell> keytool -genkey -keyalg rsa -alias mysqlClientCertificate -key
|
| 1275 |
store keystore
|
| 1276 |
|
| 1277 |
Keytool will prompt you for the following information, and
|
| 1278 |
create a keystore named keystore in the current directory.
|
| 1279 |
|
| 1280 |
You should respond with information that is appropriate for
|
| 1281 |
your situation:
|
| 1282 |
Enter keystore password: *********
|
| 1283 |
What is your first and last name?
|
| 1284 |
[Unknown]: Matthews
|
| 1285 |
What is the name of your organizational unit?
|
| 1286 |
[Unknown]: Software Development
|
| 1287 |
What is the name of your organization?
|
| 1288 |
[Unknown]: MySQL AB
|
| 1289 |
What is the name of your City or Locality?
|
| 1290 |
[Unknown]: Flossmoor
|
| 1291 |
What is the name of your State or Province?
|
| 1292 |
[Unknown]: IL
|
| 1293 |
What is the two-letter country code for this unit?
|
| 1294 |
[Unknown]: US
|
| 1295 |
Is <CN=Matthews, OU=Software Development, O=MySQL AB,
|
| 1296 |
L=Flossmoor, ST=IL, C=US> correct?
|
| 1297 |
[no]: y
|
| 1298 |
|
| 1299 |
Enter key password for <mysqlClientCertificate>
|
| 1300 |
(RETURN if same as keystore password):
|
| 1301 |
|
| 1302 |
Finally, to get JSSE to use the keystore and truststore that
|
| 1303 |
you have generated, you need to set the following system
|
| 1304 |
properties when you start your JVM, replacing
|
| 1305 |
path_to_keystore_file with the full path to the keystore file
|
| 1306 |
you created, path_to_truststore_file with the path to the
|
| 1307 |
truststore file you created, and using the appropriate
|
| 1308 |
password values for each property.
|
| 1309 |
-Djavax.net.ssl.keyStore=path_to_keystore_file
|
| 1310 |
-Djavax.net.ssl.keyStorePassword=*********
|
| 1311 |
-Djavax.net.ssl.trustStore=path_to_truststore_file
|
| 1312 |
-Djavax.net.ssl.trustStorePassword=*********
|
| 1313 |
|
| 1314 |
You will also need to set useSSL to true in your connection
|
| 1315 |
parameters for MySQL Connector/J, either by adding
|
| 1316 |
useSSL=true to your URL, or by setting the property useSSL to
|
| 1317 |
true in the java.util.Properties instance you pass to
|
| 1318 |
DriverManager.getConnection().
|
| 1319 |
|
| 1320 |
You can test that SSL is working by turning on JSSE debugging
|
| 1321 |
(as detailed below), and look for the following key events:
|
| 1322 |
...
|
| 1323 |
*** ClientHello, v3.1
|
| 1324 |
RandomCookie: GMT: 1018531834 bytes = { 199, 148, 180, 215, 74, 12,
|
| 1325 |
54, 244, 0, 168, 55, 103, 215, 64, 16, 138, 225, 190, 132, 153, 2, 217
|
| 1326 |
, 219, 239, 202, 19, 121, 78 }
|
| 1327 |
Session ID: {}
|
| 1328 |
Cipher Suites: { 0, 5, 0, 4, 0, 9, 0, 10, 0, 18, 0, 19, 0, 3, 0, 17
|
| 1329 |
}
|
| 1330 |
Compression Methods: { 0 }
|
| 1331 |
***
|
| 1332 |
[write] MD5 and SHA1 hashes: len = 59
|
| 1333 |
0000: 01 00 00 37 03 01 3D B6 90 FA C7 94 B4 D7 4A 0C ...7..=.....
|
| 1334 |
..J.
|
| 1335 |
0010: 36 F4 00 A8 37 67 D7 40 10 8A E1 BE 84 99 02 D9 6...7g.@....
|
| 1336 |
....
|
| 1337 |
0020: DB EF CA 13 79 4E 00 00 10 00 05 00 04 00 09 00 ....yN......
|
| 1338 |
....
|
| 1339 |
0030: 0A 00 12 00 13 00 03 00 11 01 00 ...........
|
| 1340 |
main, WRITE: SSL v3.1 Handshake, length = 59
|
| 1341 |
main, READ: SSL v3.1 Handshake, length = 74
|
| 1342 |
*** ServerHello, v3.1
|
| 1343 |
RandomCookie: GMT: 1018577560 bytes = { 116, 50, 4, 103, 25, 100, 58
|
| 1344 |
, 202, 79, 185, 178, 100, 215, 66, 254, 21, 83, 187, 190, 42, 170, 3,
|
| 1345 |
132, 110, 82, 148, 160, 92 }
|
| 1346 |
Session ID: {163, 227, 84, 53, 81, 127, 252, 254, 178, 179, 68, 63,
|
| 1347 |
182, 158, 30, 11, 150, 79, 170, 76, 255, 92, 15, 226, 24, 17, 177, 219
|
| 1348 |
, 158, 177, 187, 143}
|
| 1349 |
Cipher Suite: { 0, 5 }
|
| 1350 |
Compression Method: 0
|
| 1351 |
***
|
| 1352 |
%% Created: [Session-1, SSL_RSA_WITH_RC4_128_SHA]
|
| 1353 |
** SSL_RSA_WITH_RC4_128_SHA
|
| 1354 |
[read] MD5 and SHA1 hashes: len = 74
|
| 1355 |
0000: 02 00 00 46 03 01 3D B6 43 98 74 32 04 67 19 64 ...F..=.C.t2
|
| 1356 |
.g.d
|
| 1357 |
0010: 3A CA 4F B9 B2 64 D7 42 FE 15 53 BB BE 2A AA 03 :.O..d.B..S.
|
| 1358 |
.*..
|
| 1359 |
0020: 84 6E 52 94 A0 5C 20 A3 E3 54 35 51 7F FC FE B2 .nR..\ ..T5Q
|
| 1360 |
....
|
| 1361 |
0030: B3 44 3F B6 9E 1E 0B 96 4F AA 4C FF 5C 0F E2 18 .D?.....O.L.
|
| 1362 |
\...
|
| 1363 |
0040: 11 B1 DB 9E B1 BB 8F 00 05 00 ..........
|
| 1364 |
main, READ: SSL v3.1 Handshake, length = 1712
|
| 1365 |
...
|
| 1366 |
|
| 1367 |
JSSE provides debugging (to STDOUT) when you set the
|
| 1368 |
following system property: -Djavax.net.debug=all This will
|
| 1369 |
tell you what keystores and truststores are being used, as
|
| 1370 |
well as what is going on during the SSL handshake and
|
| 1371 |
certificate exchange. It will be helpful when trying to
|
| 1372 |
determine what is not working when trying to get an SSL
|
| 1373 |
connection to happen.
|
| 1374 |
|
| 1375 |
1.4.6. Using Master/Slave Replication with ReplicationConnection
|
| 1376 |
|
| 1377 |
Starting with Connector/J 3.1.7, we've made available a
|
| 1378 |
variant of the driver that will automatically send queries to
|
| 1379 |
a read/write master, or a failover or round-robin
|
| 1380 |
loadbalanced set of slaves based on the state of
|
| 1381 |
Connection.getReadOnly() .
|
| 1382 |
|
| 1383 |
An application signals that it wants a transaction to be
|
| 1384 |
read-only by calling Connection.setReadOnly(true), this
|
| 1385 |
replication-aware connection will use one of the slave
|
| 1386 |
connections, which are load-balanced per-vm using a
|
| 1387 |
round-robin scheme (a given connection is sticky to a slave
|
| 1388 |
unless that slave is removed from service). If you have a
|
| 1389 |
write transaction, or if you have a read that is
|
| 1390 |
time-sensitive (remember, replication in MySQL is
|
| 1391 |
asynchronous), set the connection to be not read-only, by
|
| 1392 |
calling Connection.setReadOnly(false) and the driver will
|
| 1393 |
ensure that further calls are sent to the master MySQL
|
| 1394 |
server. The driver takes care of propagating the current
|
| 1395 |
state of autocommit, isolation level, and catalog between all
|
| 1396 |
of the connections that it uses to accomplish this load
|
| 1397 |
balancing functionality.
|
| 1398 |
|
| 1399 |
To enable this functionality, use the "
|
| 1400 |
com.mysql.jdbc.ReplicationDriver " class when configuring
|
| 1401 |
your application server's connection pool or when creating an
|
| 1402 |
instance of a JDBC driver for your standalone application.
|
| 1403 |
Because it accepts the same URL format as the standard MySQL
|
| 1404 |
JDBC driver, ReplicationDriver does not currently work with
|
| 1405 |
java.sql.DriverManager -based connection creation unless it
|
| 1406 |
is the only MySQL JDBC driver registered with the
|
| 1407 |
DriverManager .
|
| 1408 |
|
| 1409 |
Here is a short, simple example of how ReplicationDriver
|
| 1410 |
might be used in a standalone application.
|
| 1411 |
import java.sql.Connection;
|
| 1412 |
import java.sql.ResultSet;
|
| 1413 |
import java.util.Properties;
|
| 1414 |
|
| 1415 |
import com.mysql.jdbc.ReplicationDriver;
|
| 1416 |
|
| 1417 |
public class ReplicationDriverDemo {
|
| 1418 |
|
| 1419 |
public static void main(String[] args) throws Exception {
|
| 1420 |
ReplicationDriver driver = new ReplicationDriver();
|
| 1421 |
|
| 1422 |
Properties props = new Properties();
|
| 1423 |
|
| 1424 |
// We want this for failover on the slaves
|
| 1425 |
props.put("autoReconnect", "true");
|
| 1426 |
|
| 1427 |
// We want to load balance between the slaves
|
| 1428 |
props.put("roundRobinLoadBalance", "true");
|
| 1429 |
|
| 1430 |
props.put("user", "foo");
|
| 1431 |
props.put("password", "bar");
|
| 1432 |
|
| 1433 |
//
|
| 1434 |
// Looks like a normal MySQL JDBC url, with a comma-separated
|
| 1435 |
list
|
| 1436 |
// of hosts, the first being the 'master', the rest being any
|
| 1437 |
number
|
| 1438 |
// of slaves that the driver will load balance against
|
| 1439 |
//
|
| 1440 |
|
| 1441 |
Connection conn =
|
| 1442 |
driver.connect("jdbc:mysql://master,slave1,slave2,slave3/t
|
| 1443 |
est",
|
| 1444 |
props);
|
| 1445 |
|
| 1446 |
//
|
| 1447 |
// Perform read/write work on the master
|
| 1448 |
// by setting the read-only flag to "false"
|
| 1449 |
//
|
| 1450 |
|
| 1451 |
conn.setReadOnly(false);
|
| 1452 |
conn.setAutoCommit(false);
|
| 1453 |
conn.createStatement().executeUpdate("UPDATE some_table ....")
|
| 1454 |
;
|
| 1455 |
conn.commit();
|
| 1456 |
|
| 1457 |
//
|
| 1458 |
// Now, do a query from a slave, the driver automatically pick
|
| 1459 |
s one
|
| 1460 |
// from the list
|
| 1461 |
//
|
| 1462 |
|
| 1463 |
conn.setReadOnly(true);
|
| 1464 |
|
| 1465 |
ResultSet rs = conn.createStatement().executeQuery("SELECT a,b
|
| 1466 |
,c FROM some_other_table");
|
| 1467 |
|
| 1468 |
.......
|
| 1469 |
}
|
| 1470 |
}
|
| 1471 |
|
| 1472 |
1.5. Connector/J Notes and Tips
|
| 1473 |
|
| 1474 |
1.5.1. Basic JDBC Concepts
|
| 1475 |
|
| 1476 |
This section provides some general JDBC background.
|
| 1477 |
|
| 1478 |
1.5.1.1. Connecting to MySQL Using the DriverManager Interface
|
| 1479 |
|
| 1480 |
When you are using JDBC outside of an application server, the
|
| 1481 |
DriverManager class manages the establishment of Connections.
|
| 1482 |
|
| 1483 |
The DriverManager needs to be told which JDBC drivers it
|
| 1484 |
should try to make Connections with. The easiest way to do
|
| 1485 |
this is to use Class.forName() on the class that implements
|
| 1486 |
the java.sql.Driver interface. With MySQL Connector/J, the
|
| 1487 |
name of this class is com.mysql.jdbc.Driver. With this
|
| 1488 |
method, you could use an external configuration file to
|
| 1489 |
supply the driver class name and driver parameters to use
|
| 1490 |
when connecting to a database.
|
| 1491 |
|
| 1492 |
The following section of Java code shows how you might
|
| 1493 |
register MySQL Connector/J from the main() method of your
|
| 1494 |
application:
|
| 1495 |
import java.sql.Connection;
|
| 1496 |
import java.sql.DriverManager;
|
| 1497 |
import java.sql.SQLException;
|
| 1498 |
|
| 1499 |
// Notice, do not import com.mysql.jdbc.*
|
| 1500 |
// or you will have problems!
|
| 1501 |
|
| 1502 |
public class LoadDriver {
|
| 1503 |
public static void main(String[] args) {
|
| 1504 |
try {
|
| 1505 |
// The newInstance() call is a work around for some
|
| 1506 |
// broken Java implementations
|
| 1507 |
|
| 1508 |
Class.forName("com.mysql.jdbc.Driver").newInstance();
|
| 1509 |
} catch (Exception ex) {
|
| 1510 |
// handle the error
|
| 1511 |
}
|
| 1512 |
}
|
| 1513 |
|
| 1514 |
After the driver has been registered with the DriverManager,
|
| 1515 |
you can obtain a Connection instance that is connected to a
|
| 1516 |
particular database by calling DriverManager.getConnection():
|
| 1517 |
|
| 1518 |
Example 1. Obtaining a connection from the DriverManager
|
| 1519 |
|
| 1520 |
This example shows how you can obtain a Connection instance
|
| 1521 |
from the DriverManager. There are a few different signatures
|
| 1522 |
for the getConnection() method. You should see the API
|
| 1523 |
documentation that comes with your JDK for more specific
|
| 1524 |
information on how to use them.
|
| 1525 |
import java.sql.Connection;
|
| 1526 |
import java.sql.DriverManager;
|
| 1527 |
import java.sql.SQLException;
|
| 1528 |
|
| 1529 |
... try {
|
| 1530 |
Connection conn = DriverManager.getConnection("jdbc:mysql:
|
| 1531 |
//localhost/test?user=monty&password=greatsqldb");
|
| 1532 |
|
| 1533 |
// Do something with the Connection
|
| 1534 |
|
| 1535 |
....
|
| 1536 |
} catch (SQLException ex) {
|
| 1537 |
// handle any errors
|
| 1538 |
System.out.println("SQLException: " + ex.getMessage());
|
| 1539 |
System.out.println("SQLState: " + ex.getSQLState());
|
| 1540 |
System.out.println("VendorError: " + ex.getErrorCode());
|
| 1541 |
}
|
| 1542 |
|
| 1543 |
Once a Connection is established, it can be used to create
|
| 1544 |
Statement and PreparedStatement objects, as well as retrieve
|
| 1545 |
metadata about the database. This is explained in the
|
| 1546 |
following sections.
|
| 1547 |
|
| 1548 |
1.5.1.2. Using Statements to Execute SQL
|
| 1549 |
|
| 1550 |
Statement objects allow you to execute basic SQL queries and
|
| 1551 |
retrieve the results through the ResultSet class which is
|
| 1552 |
described later.
|
| 1553 |
|
| 1554 |
To create a Statement instance, you call the
|
| 1555 |
createStatement() method on the Connection object you have
|
| 1556 |
retrieved via one of the DriverManager.getConnection() or
|
| 1557 |
DataSource.getConnection() methods described earlier.
|
| 1558 |
|
| 1559 |
Once you have a Statement instance, you can execute a SELECT
|
| 1560 |
query by calling the executeQuery(String) method with the SQL
|
| 1561 |
you want to use.
|
| 1562 |
|
| 1563 |
To update data in the database, use the executeUpdate(String
|
| 1564 |
SQL) method. This method returns the number of rows affected
|
| 1565 |
by the update statement.
|
| 1566 |
|
| 1567 |
If you don't know ahead of time whether the SQL statement
|
| 1568 |
will be a SELECT or an UPDATE/INSERT, then you can use the
|
| 1569 |
execute(String SQL) method. This method will return true if
|
| 1570 |
the SQL query was a SELECT, or false if it was an UPDATE,
|
| 1571 |
INSERT, or DELETE statement. If the statement was a SELECT
|
| 1572 |
query, you can retrieve the results by calling the
|
| 1573 |
getResultSet() method. If the statement was an UPDATE,
|
| 1574 |
INSERT, or DELETE statement, you can retrieve the affected
|
| 1575 |
rows count by calling getUpdateCount() on the Statement
|
| 1576 |
instance.
|
| 1577 |
|
| 1578 |
Example 2. Using java.sql.Statement to execute a SELECT query
|
| 1579 |
// assume that conn is an already created JDBC connection
|
| 1580 |
Statement stmt = null;
|
| 1581 |
ResultSet rs = null;
|
| 1582 |
|
| 1583 |
try {
|
| 1584 |
stmt = conn.createStatement();
|
| 1585 |
rs = stmt.executeQuery("SELECT foo FROM bar");
|
| 1586 |
|
| 1587 |
// or alternatively, if you don't know ahead of time that
|
| 1588 |
// the query will be a SELECT...
|
| 1589 |
|
| 1590 |
if (stmt.execute("SELECT foo FROM bar")) {
|
| 1591 |
rs = stmt.getResultSet();
|
| 1592 |
}
|
| 1593 |
|
| 1594 |
// Now do something with the ResultSet ....
|
| 1595 |
} finally {
|
| 1596 |
// it is a good idea to release
|
| 1597 |
// resources in a finally{} block
|
| 1598 |
// in reverse-order of their creation
|
| 1599 |
// if they are no-longer needed
|
| 1600 |
|
| 1601 |
if (rs != null) {
|
| 1602 |
try {
|
| 1603 |
rs.close();
|
| 1604 |
} catch (SQLException sqlEx) { // ignore }
|
| 1605 |
|
| 1606 |
rs = null;
|
| 1607 |
}
|
| 1608 |
|
| 1609 |
if (stmt != null) {
|
| 1610 |
try {
|
| 1611 |
stmt.close();
|
| 1612 |
} catch (SQLException sqlEx) { // ignore }
|
| 1613 |
|
| 1614 |
stmt = null;
|
| 1615 |
}
|
| 1616 |
}
|
| 1617 |
|
| 1618 |
1.5.1.3. Using CallableStatements to Execute Stored Procedures
|
| 1619 |
|
| 1620 |
Starting with MySQL server version 5.0 when used with
|
| 1621 |
Connector/J 3.1.1 or newer, the java.sql.CallableStatement
|
| 1622 |
interface is fully implemented with the exception of the
|
| 1623 |
getParameterMetaData() method.
|
| 1624 |
|
| 1625 |
See [WARNING: missing xref target (id=stored-procedures)] for
|
| 1626 |
more information on MySQL stored procedures.
|
| 1627 |
|
| 1628 |
Connector/J exposes stored procedure functionality through
|
| 1629 |
JDBC's CallableStatement interface.
|
| 1630 |
|
| 1631 |
Note. Current versions of MySQL server do not return enough
|
| 1632 |
information for the JDBC driver to provide result set
|
| 1633 |
metadata for callable statements. This means that when using
|
| 1634 |
CallableStatement, ResultSetMetaData may return NULL.
|
| 1635 |
|
| 1636 |
The following example shows a stored procedure that returns
|
| 1637 |
the value of inOutParam incremented by 1, and the string
|
| 1638 |
passed in via inputParam as a ResultSet:
|
| 1639 |
|
| 1640 |
Example 3. Stored Procedures
|
| 1641 |
CREATE PROCEDURE demoSp(IN inputParam VARCHAR(255), INOUT inOutParam I
|
| 1642 |
NT)
|
| 1643 |
BEGIN
|
| 1644 |
DECLARE z INT;
|
| 1645 |
SET z = inOutParam + 1;
|
| 1646 |
SET inOutParam = z;
|
| 1647 |
|
| 1648 |
SELECT inputParam;
|
| 1649 |
|
| 1650 |
SELECT CONCAT('zyxw', inputParam);
|
| 1651 |
END
|
| 1652 |
|
| 1653 |
To use the demoSp procedure with Connector/J, follow these
|
| 1654 |
steps:
|
| 1655 |
1. Prepare the callable statement by using
|
| 1656 |
Connection.prepareCall() .
|
| 1657 |
Notice that you have to use JDBC escape syntax, and that
|
| 1658 |
the parentheses surrounding the parameter placeholders
|
| 1659 |
are not optional:
|
| 1660 |
Example 4. Using Connection.prepareCall()
|
| 1661 |
import java.sql.CallableStatement;
|
| 1662 |
|
| 1663 |
...
|
| 1664 |
|
| 1665 |
//
|
| 1666 |
// Prepare a call to the stored procedure 'demoSp'
|
| 1667 |
// with two parameters
|
| 1668 |
//
|
| 1669 |
// Notice the use of JDBC-escape syntax ({call ...})
|
| 1670 |
//
|
| 1671 |
|
| 1672 |
CallableStatement cStmt = conn.prepareCall("{call demoSp(?, ?)}");
|
| 1673 |
|
| 1674 |
|
| 1675 |
|
| 1676 |
cStmt.setString(1, "abcdefg");
|
| 1677 |
Note. Connection.prepareCall() is an expensive method,
|
| 1678 |
due to the metadata retrieval that the driver performs to
|
| 1679 |
support output parameters. For performance reasons, you
|
| 1680 |
should try to minimize unnecessary calls to
|
| 1681 |
Connection.prepareCall() by reusing CallableStatement
|
| 1682 |
instances in your code.
|
| 1683 |
2. Register the output parameters (if any exist)
|
| 1684 |
To retrieve the values of output parameters (parameters
|
| 1685 |
specified as OUT or INOUT when you created the stored
|
| 1686 |
procedure), JDBC requires that they be specified before
|
| 1687 |
statement execution using the various
|
| 1688 |
registerOutputParameter() methods in the
|
| 1689 |
CallableStatement interface:
|
| 1690 |
Example 5. Registering output parameters
|
| 1691 |
import java.sql.Types;
|
| 1692 |
...
|
| 1693 |
//
|
| 1694 |
// Connector/J supports both named and indexed
|
| 1695 |
// output parameters. You can register output
|
| 1696 |
// parameters using either method, as well
|
| 1697 |
// as retrieve output parameters using either
|
| 1698 |
// method, regardless of what method was
|
| 1699 |
// used to register them.
|
| 1700 |
//
|
| 1701 |
// The following examples show how to use
|
| 1702 |
// the various methods of registering
|
| 1703 |
// output parameters (you should of course
|
| 1704 |
// use only one registration per parameter).
|
| 1705 |
//
|
| 1706 |
|
| 1707 |
//
|
| 1708 |
// Registers the second parameter as output, and
|
| 1709 |
// uses the type 'INTEGER' for values returned from
|
| 1710 |
// getObject()
|
| 1711 |
//
|
| 1712 |
|
| 1713 |
cStmt.registerOutParameter(2, Types.INTEGER);
|
| 1714 |
|
| 1715 |
//
|
| 1716 |
// Registers the named parameter 'inOutParam', and
|
| 1717 |
// uses the type 'INTEGER' for values returned from
|
| 1718 |
// getObject()
|
| 1719 |
//
|
| 1720 |
|
| 1721 |
cStmt.registerOutParameter("inOutParam", Types.INTEGER);
|
| 1722 |
...
|
| 1723 |
|
| 1724 |
3. Set the input parameters (if any exist)
|
| 1725 |
Input and in/out parameters are set as for
|
| 1726 |
PreparedStatement objects. However, CallableStatement
|
| 1727 |
also supports setting parameters by name:
|
| 1728 |
Example 6. Setting CallableStatement input parameters
|
| 1729 |
...
|
| 1730 |
|
| 1731 |
//
|
| 1732 |
// Set a parameter by index
|
| 1733 |
//
|
| 1734 |
|
| 1735 |
cStmt.setString(1, "abcdefg");
|
| 1736 |
|
| 1737 |
//
|
| 1738 |
// Alternatively, set a parameter using
|
| 1739 |
// the parameter name
|
| 1740 |
//
|
| 1741 |
|
| 1742 |
cStmt.setString("inputParameter", "abcdefg");
|
| 1743 |
|
| 1744 |
//
|
| 1745 |
// Set the 'in/out' parameter using an index
|
| 1746 |
//
|
| 1747 |
|
| 1748 |
cStmt.setInt(2, 1);
|
| 1749 |
|
| 1750 |
//
|
| 1751 |
// Alternatively, set the 'in/out' parameter
|
| 1752 |
// by name
|
| 1753 |
//
|
| 1754 |
|
| 1755 |
cStmt.setInt("inOutParam", 1);
|
| 1756 |
|
| 1757 |
...
|
| 1758 |
4. Execute the CallableStatement, and retrieve any result
|
| 1759 |
sets or output parameters.
|
| 1760 |
Although CallableStatement supports calling any of the
|
| 1761 |
Statement execute methods (executeUpdate(),
|
| 1762 |
executeQuery() or execute()), the most flexible method to
|
| 1763 |
call is execute(), as you do not need to know ahead of
|
| 1764 |
time if the stored procedure returns result sets:
|
| 1765 |
Example 7. Retrieving results and output parameter values
|
| 1766 |
...
|
| 1767 |
|
| 1768 |
boolean hadResults = cStmt.execute();
|
| 1769 |
|
| 1770 |
//
|
| 1771 |
// Process all returned result sets
|
| 1772 |
//
|
| 1773 |
|
| 1774 |
while (hadResults) {
|
| 1775 |
ResultSet rs = cStmt.getResultSet();
|
| 1776 |
|
| 1777 |
// process result set
|
| 1778 |
...
|
| 1779 |
|
| 1780 |
hadResults = rs.getMoreResults();
|
| 1781 |
}
|
| 1782 |
|
| 1783 |
//
|
| 1784 |
// Retrieve output parameters
|
| 1785 |
//
|
| 1786 |
// Connector/J supports both index-based and
|
| 1787 |
// name-based retrieval
|
| 1788 |
//
|
| 1789 |
|
| 1790 |
int outputValue = cStmt.getInt(2); // index-based
|
| 1791 |
|
| 1792 |
outputValue = cStmt.getInt("inOutParam"); // name-based
|
| 1793 |
|
| 1794 |
...
|
| 1795 |
|
| 1796 |
1.5.1.4. Retrieving AUTO_INCREMENT Column Values
|
| 1797 |
|
| 1798 |
Before version 3.0 of the JDBC API, there was no standard way
|
| 1799 |
of retrieving key values from databases that supported auto
|
| 1800 |
increment or identity columns. With older JDBC drivers for
|
| 1801 |
MySQL, you could always use a MySQL-specific method on the
|
| 1802 |
Statement interface, or issue the query SELECT
|
| 1803 |
LAST_INSERT_ID() after issuing an INSERT to a table that had
|
| 1804 |
an AUTO_INCREMENT key. Using the MySQL-specific method call
|
| 1805 |
isn't portable, and issuing a SELECT to get the
|
| 1806 |
AUTO_INCREMENT key's value requires another round-trip to the
|
| 1807 |
database, which isn't as efficient as possible. The following
|
| 1808 |
code snippets demonstrate the three different ways to
|
| 1809 |
retrieve AUTO_INCREMENT values. First, we demonstrate the use
|
| 1810 |
of the new JDBC-3.0 method getGeneratedKeys() which is now
|
| 1811 |
the preferred method to use if you need to retrieve
|
| 1812 |
AUTO_INCREMENT keys and have access to JDBC-3.0. The second
|
| 1813 |
example shows how you can retrieve the same value using a
|
| 1814 |
standard SELECT LAST_INSERT_ID() query. The final example
|
| 1815 |
shows how updatable result sets can retrieve the
|
| 1816 |
AUTO_INCREMENT value when using the insertRow() method.
|
| 1817 |
|
| 1818 |
Example 8. Retrieving AUTO_INCREMENT column values using
|
| 1819 |
Statement.getGeneratedKeys()
|
| 1820 |
Statement stmt = null;
|
| 1821 |
ResultSet rs = null;
|
| 1822 |
|
| 1823 |
try {
|
| 1824 |
|
| 1825 |
//
|
| 1826 |
// Create a Statement instance that we can use for
|
| 1827 |
// 'normal' result sets assuming you have a
|
| 1828 |
// Connection 'conn' to a MySQL database already
|
| 1829 |
// available
|
| 1830 |
|
| 1831 |
stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
|
| 1832 |
java.sql.ResultSet.CONCUR_UPDATABLE);
|
| 1833 |
|
| 1834 |
//
|
| 1835 |
// Issue the DDL queries for the table for this example
|
| 1836 |
//
|
| 1837 |
|
| 1838 |
stmt.executeUpdate("DROP TABLE IF EXISTS autoIncTutorial");
|
| 1839 |
stmt.executeUpdate(
|
| 1840 |
"CREATE TABLE autoIncTutorial ("
|
| 1841 |
+ "priKey INT NOT NULL AUTO_INCREMENT, "
|
| 1842 |
+ "dataField VARCHAR(64), PRIMARY KEY (priKey))");
|
| 1843 |
|
| 1844 |
//
|
| 1845 |
// Insert one row that will generate an AUTO INCREMENT
|
| 1846 |
// key in the 'priKey' field
|
| 1847 |
//
|
| 1848 |
|
| 1849 |
stmt.executeUpdate(
|
| 1850 |
"INSERT INTO autoIncTutorial (dataField) "
|
| 1851 |
+ "values ('Can I Get the Auto Increment Field?')",
|
| 1852 |
Statement.RETURN_GENERATED_KEYS);
|
| 1853 |
|
| 1854 |
//
|
| 1855 |
// Example of using Statement.getGeneratedKeys()
|
| 1856 |
// to retrieve the value of an auto-increment
|
| 1857 |
// value
|
| 1858 |
//
|
| 1859 |
|
| 1860 |
int autoIncKeyFromApi = -1;
|
| 1861 |
|
| 1862 |
rs = stmt.getGeneratedKeys();
|
| 1863 |
|
| 1864 |
if (rs.next()) {
|
| 1865 |
autoIncKeyFromApi = rs.getInt(1);
|
| 1866 |
} else {
|
| 1867 |
|
| 1868 |
// throw an exception from here
|
| 1869 |
}
|
| 1870 |
|
| 1871 |
rs.close();
|
| 1872 |
|
| 1873 |
rs = null;
|
| 1874 |
|
| 1875 |
System.out.println("Key returned from getGeneratedKeys():"
|
| 1876 |
+ autoIncKeyFromApi);
|
| 1877 |
} finally {
|
| 1878 |
|
| 1879 |
if (rs != null) {
|
| 1880 |
try {
|
| 1881 |
rs.close();
|
| 1882 |
} catch (SQLException ex) {
|
| 1883 |
// ignore
|
| 1884 |
}
|
| 1885 |
}
|
| 1886 |
|
| 1887 |
if (stmt != null) {
|
| 1888 |
try {
|
| 1889 |
stmt.close();
|
| 1890 |
} catch (SQLException ex) {
|
| 1891 |
// ignore
|
| 1892 |
}
|
| 1893 |
}
|
| 1894 |
}
|
| 1895 |
|
| 1896 |
Example 9. Retrieving AUTO_INCREMENT column values using
|
| 1897 |
SELECT LAST_INSERT_ID()
|
| 1898 |
Statement stmt = null;
|
| 1899 |
ResultSet rs = null;
|
| 1900 |
|
| 1901 |
try {
|
| 1902 |
|
| 1903 |
//
|
| 1904 |
// Create a Statement instance that we can use for
|
| 1905 |
// 'normal' result sets.
|
| 1906 |
|
| 1907 |
stmt = conn.createStatement();
|
| 1908 |
|
| 1909 |
//
|
| 1910 |
// Issue the DDL queries for the table for this example
|
| 1911 |
//
|
| 1912 |
|
| 1913 |
stmt.executeUpdate("DROP TABLE IF EXISTS autoIncTutorial");
|
| 1914 |
stmt.executeUpdate(
|
| 1915 |
"CREATE TABLE autoIncTutorial ("
|
| 1916 |
+ "priKey INT NOT NULL AUTO_INCREMENT, "
|
| 1917 |
+ "dataField VARCHAR(64), PRIMARY KEY (priKey))");
|
| 1918 |
|
| 1919 |
//
|
| 1920 |
// Insert one row that will generate an AUTO INCREMENT
|
| 1921 |
// key in the 'priKey' field
|
| 1922 |
//
|
| 1923 |
|
| 1924 |
stmt.executeUpdate(
|
| 1925 |
"INSERT INTO autoIncTutorial (dataField) "
|
| 1926 |
+ "values ('Can I Get the Auto Increment Field?')");
|
| 1927 |
|
| 1928 |
//
|
| 1929 |
// Use the MySQL LAST_INSERT_ID()
|
| 1930 |
// function to do the same thing as getGeneratedKeys()
|
| 1931 |
//
|
| 1932 |
|
| 1933 |
int autoIncKeyFromFunc = -1;
|
| 1934 |
rs = stmt.executeQuery("SELECT LAST_INSERT_ID()");
|
| 1935 |
|
| 1936 |
if (rs.next()) {
|
| 1937 |
autoIncKeyFromFunc = rs.getInt(1);
|
| 1938 |
} else {
|
| 1939 |
// throw an exception from here
|
| 1940 |
}
|
| 1941 |
|
| 1942 |
rs.close();
|
| 1943 |
|
| 1944 |
System.out.println("Key returned from " + "'SELECT LAST_INSERT_ID(
|
| 1945 |
)': "
|
| 1946 |
+ autoIncKeyFromFunc);
|
| 1947 |
|
| 1948 |
} finally {
|
| 1949 |
|
| 1950 |
if (rs != null) {
|
| 1951 |
try {
|
| 1952 |
rs.close();
|
| 1953 |
} catch (SQLException ex) {
|
| 1954 |
// ignore
|
| 1955 |
}
|
| 1956 |
}
|
| 1957 |
|
| 1958 |
if (stmt != null) {
|
| 1959 |
try {
|
| 1960 |
stmt.close();
|
| 1961 |
} catch (SQLException ex) {
|
| 1962 |
// ignore
|
| 1963 |
}
|
| 1964 |
}
|
| 1965 |
}
|
| 1966 |
|
| 1967 |
Example 10. Retrieving AUTO_INCREMENT column values in
|
| 1968 |
Updatable ResultSets
|
| 1969 |
Statement stmt = null;
|
| 1970 |
ResultSet rs = null;
|
| 1971 |
|
| 1972 |
try {
|
| 1973 |
|
| 1974 |
//
|
| 1975 |
// Create a Statement instance that we can use for
|
| 1976 |
// 'normal' result sets as well as an 'updatable'
|
| 1977 |
// one, assuming you have a Connection 'conn' to
|
| 1978 |
// a MySQL database already available
|
| 1979 |
//
|
| 1980 |
|
| 1981 |
stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
|
| 1982 |
java.sql.ResultSet.CONCUR_UPDATABLE);
|
| 1983 |
|
| 1984 |
//
|
| 1985 |
// Issue the DDL queries for the table for this example
|
| 1986 |
//
|
| 1987 |
|
| 1988 |
stmt.executeUpdate("DROP TABLE IF EXISTS autoIncTutorial");
|
| 1989 |
stmt.executeUpdate(
|
| 1990 |
"CREATE TABLE autoIncTutorial ("
|
| 1991 |
+ "priKey INT NOT NULL AUTO_INCREMENT, "
|
| 1992 |
+ "dataField VARCHAR(64), PRIMARY KEY (priKey))");
|
| 1993 |
|
| 1994 |
//
|
| 1995 |
// Example of retrieving an AUTO INCREMENT key
|
| 1996 |
// from an updatable result set
|
| 1997 |
//
|
| 1998 |
|
| 1999 |
rs = stmt.executeQuery("SELECT priKey, dataField "
|
| 2000 |
+ "FROM autoIncTutorial");
|
| 2001 |
|
| 2002 |
rs.moveToInsertRow();
|
| 2003 |
|
| 2004 |
rs.updateString("dataField", "AUTO INCREMENT here?");
|
| 2005 |
rs.insertRow();
|
| 2006 |
|
| 2007 |
//
|
| 2008 |
// the driver adds rows at the end
|
| 2009 |
//
|
| 2010 |
|
| 2011 |
rs.last();
|
| 2012 |
|
| 2013 |
//
|
| 2014 |
// We should now be on the row we just inserted
|
| 2015 |
//
|
| 2016 |
|
| 2017 |
int autoIncKeyFromRS = rs.getInt("priKey");
|
| 2018 |
|
| 2019 |
rs.close();
|
| 2020 |
|
| 2021 |
rs = null;
|
| 2022 |
|
| 2023 |
System.out.println("Key returned for inserted row: "
|
| 2024 |
+ autoIncKeyFromRS);
|
| 2025 |
|
| 2026 |
} finally {
|
| 2027 |
|
| 2028 |
if (rs != null) {
|
| 2029 |
try {
|
| 2030 |
rs.close();
|
| 2031 |
} catch (SQLException ex) {
|
| 2032 |
// ignore
|
| 2033 |
}
|
| 2034 |
}
|
| 2035 |
|
| 2036 |
if (stmt != null) {
|
| 2037 |
try {
|
| 2038 |
stmt.close();
|
| 2039 |
} catch (SQLException ex) {
|
| 2040 |
// ignore
|
| 2041 |
}
|
| 2042 |
}
|
| 2043 |
}
|
| 2044 |
|
| 2045 |
|
| 2046 |
|
| 2047 |
When you run the preceding example code, you should get the
|
| 2048 |
following output: Key returned from getGeneratedKeys(): 1 Key
|
| 2049 |
returned from SELECT LAST_INSERT_ID(): 1 Key returned for
|
| 2050 |
inserted row: 2 You should be aware, that at times, it can be
|
| 2051 |
tricky to use the SELECT LAST_INSERT_ID() query, as that
|
| 2052 |
function's value is scoped to a connection. So, if some other
|
| 2053 |
query happens on the same connection, the value will be
|
| 2054 |
overwritten. On the other hand, the getGeneratedKeys() method
|
| 2055 |
is scoped by the Statement instance, so it can be used even
|
| 2056 |
if other queries happen on the same connection, but not on
|
| 2057 |
the same Statement instance.
|
| 2058 |
|
| 2059 |
1.5.2. Using Connector/J with J2EE and Other Java Frameworks
|
| 2060 |
|
| 2061 |
This section describes how to use Connector/J in several
|
| 2062 |
contexts.
|
| 2063 |
|
| 2064 |
1.5.2.1. General J2EE Concepts
|
| 2065 |
|
| 2066 |
This section provides general background on J2EE concepts
|
| 2067 |
that pertain to use of Connector/J.
|
| 2068 |
|
| 2069 |
1.5.2.1.1. Understanding Connection Pooling
|
| 2070 |
|
| 2071 |
Connection pooling is a technique of creating and managing a
|
| 2072 |
pool of connections that are ready for use by any thread that
|
| 2073 |
needs them.
|
| 2074 |
|
| 2075 |
This technique of pooling connections is based on the fact
|
| 2076 |
that most applications only need a thread to have access to a
|
| 2077 |
JDBC connection when they are actively processing a
|
| 2078 |
transaction, which usually take only milliseconds to
|
| 2079 |
complete. When not processing a transaction, the connection
|
| 2080 |
would otherwise sit idle. Instead, connection pooling allows
|
| 2081 |
the idle connection to be used by some other thread to do
|
| 2082 |
useful work.
|
| 2083 |
|
| 2084 |
In practice, when a thread needs to do work against a MySQL
|
| 2085 |
or other database with JDBC, it requests a connection from
|
| 2086 |
the pool. When the thread is finished using the connection,
|
| 2087 |
it returns it to the pool, so that it may be used by any
|
| 2088 |
other threads that want to use it.
|
| 2089 |
|
| 2090 |
When the connection is loaned out from the pool, it is used
|
| 2091 |
exclusively by the thread that requested it. From a
|
| 2092 |
programming point of view, it is the same as if your thread
|
| 2093 |
called DriverManager.getConnection() every time it needed a
|
| 2094 |
JDBC connection, however with connection pooling, your thread
|
| 2095 |
may end up using either a new, or already-existing
|
| 2096 |
connection.
|
| 2097 |
|
| 2098 |
Connection pooling can greatly increase the performance of
|
| 2099 |
your Java application, while reducing overall resource usage.
|
| 2100 |
The main benefits to connection pooling are:
|
| 2101 |
* Reduced connection creation time
|
| 2102 |
Although this is not usually an issue with the quick
|
| 2103 |
connection setup that MySQL offers compared to other
|
| 2104 |
databases, creating new JDBC connections still incurs
|
| 2105 |
networking and JDBC driver overhead that will be avoided
|
| 2106 |
if connections are recycled.
|
| 2107 |
* Simplified programming model
|
| 2108 |
When using connection pooling, each individual thread can
|
| 2109 |
act as though it has created its own JDBC connection,
|
| 2110 |
allowing you to use straight-forward JDBC programming
|
| 2111 |
techniques.
|
| 2112 |
* Controlled resource usage
|
| 2113 |
If you don't use connection pooling, and instead create a
|
| 2114 |
new connection every time a thread needs one, your
|
| 2115 |
application's resource usage can be quite wasteful and
|
| 2116 |
lead to unpredictable behavior under load.
|
| 2117 |
|
| 2118 |
Remember that each connection to MySQL has overhead (memory,
|
| 2119 |
CPU, context switches, and so forth) on both the client and
|
| 2120 |
server side. Every connection limits how many resources there
|
| 2121 |
are available to your application as well as the MySQL
|
| 2122 |
server. Many of these resources will be used whether or not
|
| 2123 |
the connection is actually doing any useful work!
|
| 2124 |
|
| 2125 |
Connection pools can be tuned to maximize performance, while
|
| 2126 |
keeping resource utilization below the point where your
|
| 2127 |
application will start to fail rather than just run slower.
|
| 2128 |
|
| 2129 |
Luckily, Sun has standardized the concept of connection
|
| 2130 |
pooling in JDBC through the JDBC-2.0 Optional interfaces, and
|
| 2131 |
all major application servers have implementations of these
|
| 2132 |
APIs that work fine with MySQL Connector/J.
|
| 2133 |
|
| 2134 |
Generally, you configure a connection pool in your
|
| 2135 |
application server configuration files, and access it via the
|
| 2136 |
Java Naming and Directory Interface (JNDI). The following
|
| 2137 |
code shows how you might use a connection pool from an
|
| 2138 |
application deployed in a J2EE application server:
|
| 2139 |
|
| 2140 |
Example 11. Using a connection pool with a J2EE application
|
| 2141 |
server
|
| 2142 |
import java.sql.Connection;
|
| 2143 |
import java.sql.SQLException;
|
| 2144 |
import java.sql.Statement;
|
| 2145 |
|
| 2146 |
import javax.naming.InitialContext;
|
| 2147 |
import javax.sql.DataSource;
|
| 2148 |
|
| 2149 |
|
| 2150 |
public class MyServletJspOrEjb {
|
| 2151 |
|
| 2152 |
public void doSomething() throws Exception {
|
| 2153 |
/*
|
| 2154 |
* Create a JNDI Initial context to be able to
|
| 2155 |
* lookup the DataSource
|
| 2156 |
*
|
| 2157 |
* In production-level code, this should be cached as
|
| 2158 |
* an instance or static variable, as it can
|
| 2159 |
* be quite expensive to create a JNDI context.
|
| 2160 |
*
|
| 2161 |
* Note: This code only works when you are using servlets
|
| 2162 |
* or EJBs in a J2EE application server. If you are
|
| 2163 |
* using connection pooling in standalone Java code, you
|
| 2164 |
* will have to create/configure datasources using whatever
|
| 2165 |
* mechanisms your particular connection pooling library
|
| 2166 |
* provides.
|
| 2167 |
*/
|
| 2168 |
|
| 2169 |
InitialContext ctx = new InitialContext();
|
| 2170 |
|
| 2171 |
/*
|
| 2172 |
* Lookup the DataSource, which will be backed by a pool
|
| 2173 |
* that the application server provides. DataSource instances
|
| 2174 |
* are also a good candidate for caching as an instance
|
| 2175 |
* variable, as JNDI lookups can be expensive as well.
|
| 2176 |
*/
|
| 2177 |
|
| 2178 |
DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/MyS
|
| 2179 |
QLDB");
|
| 2180 |
|
| 2181 |
/*
|
| 2182 |
* The following code is what would actually be in your
|
| 2183 |
* Servlet, JSP or EJB 'service' method...where you need
|
| 2184 |
* to work with a JDBC connection.
|
| 2185 |
*/
|
| 2186 |
|
| 2187 |
Connection conn = null;
|
| 2188 |
Statement stmt = null;
|
| 2189 |
|
| 2190 |
try {
|
| 2191 |
conn = ds.getConnection();
|
| 2192 |
|
| 2193 |
/*
|
| 2194 |
* Now, use normal JDBC programming to work with
|
| 2195 |
* MySQL, making sure to close each resource when you're
|
| 2196 |
* finished with it, which allows the connection pool
|
| 2197 |
* resources to be recovered as quickly as possible
|
| 2198 |
*/
|
| 2199 |
|
| 2200 |
stmt = conn.createStatement();
|
| 2201 |
stmt.execute("SOME SQL QUERY");
|
| 2202 |
|
| 2203 |
stmt.close();
|
| 2204 |
stmt = null;
|
| 2205 |
|
| 2206 |
conn.close();
|
| 2207 |
conn = null;
|
| 2208 |
} finally {
|
| 2209 |
/*
|
| 2210 |
* close any jdbc instances here that weren't
|
| 2211 |
* explicitly closed during normal code path, so
|
| 2212 |
* that we don't 'leak' resources...
|
| 2213 |
*/
|
| 2214 |
|
| 2215 |
if (stmt != null) {
|
| 2216 |
try {
|
| 2217 |
stmt.close();
|
| 2218 |
} catch (sqlexception sqlex) {
|
| 2219 |
// ignore -- as we can't do anything about it here
|
| 2220 |
}
|
| 2221 |
|
| 2222 |
stmt = null;
|
| 2223 |
}
|
| 2224 |
|
| 2225 |
if (conn != null) {
|
| 2226 |
try {
|
| 2227 |
conn.close();
|
| 2228 |
} catch (sqlexception sqlex) {
|
| 2229 |
// ignore -- as we can't do anything about it here
|
| 2230 |
}
|
| 2231 |
|
| 2232 |
conn = null;
|
| 2233 |
}
|
| 2234 |
}
|
| 2235 |
}
|
| 2236 |
}
|
| 2237 |
|
| 2238 |
As shown in the example above, after obtaining the JNDI
|
| 2239 |
InitialContext, and looking up the DataSource, the rest of
|
| 2240 |
the code should look familiar to anyone who has done JDBC
|
| 2241 |
programming in the past.
|
| 2242 |
|
| 2243 |
The most important thing to remember when using connection
|
| 2244 |
pooling is to make sure that no matter what happens in your
|
| 2245 |
code (exceptions, flow-of-control, and so forth),
|
| 2246 |
connections, and anything created by them (such as statements
|
| 2247 |
or result sets) are closed, so that they may be re-used,
|
| 2248 |
otherwise they will be stranded, which in the best case means
|
| 2249 |
that the MySQL server resources they represent (such as
|
| 2250 |
buffers, locks, or sockets) may be tied up for some time, or
|
| 2251 |
worst case, may be tied up forever.
|
| 2252 |
|
| 2253 |
What's the Best Size for my Connection Pool?
|
| 2254 |
|
| 2255 |
As with all other configuration rules-of-thumb, the answer
|
| 2256 |
is: it depends. Although the optimal size depends on
|
| 2257 |
anticipated load and average database transaction time, the
|
| 2258 |
optimum connection pool size is smaller than you might
|
| 2259 |
expect. If you take Sun's Java Petstore blueprint application
|
| 2260 |
for example, a connection pool of 15-20 connections can serve
|
| 2261 |
a relatively moderate load (600 concurrent users) using MySQL
|
| 2262 |
and Tomcat with response times that are acceptable.
|
| 2263 |
|
| 2264 |
To correctly size a connection pool for your application, you
|
| 2265 |
should create load test scripts with tools such as Apache
|
| 2266 |
JMeter or The Grinder, and load test your application.
|
| 2267 |
|
| 2268 |
An easy way to determine a starting point is to configure
|
| 2269 |
your connection pool's maximum number of connections to be
|
| 2270 |
unbounded, run a load test, and measure the largest amount of
|
| 2271 |
concurrently used connections. You can then work backward
|
| 2272 |
from there to determine what values of minimum and maximum
|
| 2273 |
pooled connections give the best performance for your
|
| 2274 |
particular application.
|
| 2275 |
|
| 2276 |
1.5.2.2. Using Connector/J with Tomcat
|
| 2277 |
|
| 2278 |
The following instructions are based on the instructions for
|
| 2279 |
Tomcat-5.x, available at
|
| 2280 |
http://jakarta.apache.org/tomcat/tomcat-5.0-doc/jndi-datasour
|
| 2281 |
ce-examples-howto.html which is current at the time this
|
| 2282 |
document was written.
|
| 2283 |
|
| 2284 |
First, install the .jar file that comes with Connector/J in
|
| 2285 |
$CATALINA_HOME/common/lib so that it is available to all
|
| 2286 |
applications installed in the container.
|
| 2287 |
|
| 2288 |
Next, Configure the JNDI DataSource by adding a declaration
|
| 2289 |
resource to $CATALINA_HOME/conf/server.xml in the context
|
| 2290 |
that defines your web application:
|
| 2291 |
<Context ....>
|
| 2292 |
|
| 2293 |
...
|
| 2294 |
|
| 2295 |
<Resource name="jdbc/MySQLDB"
|
| 2296 |
auth="Container"
|
| 2297 |
type="javax.sql.DataSource"/>
|
| 2298 |
|
| 2299 |
<!-- The name you used above, must match _exactly_ here!
|
| 2300 |
|
| 2301 |
The connection pool will be bound into JNDI with the name
|
| 2302 |
"java:/comp/env/jdbc/MySQLDB"
|
| 2303 |
-->
|
| 2304 |
|
| 2305 |
<ResourceParams name="jdbc/MySQLDB">
|
| 2306 |
<parameter>
|
| 2307 |
<name>factory</name>
|
| 2308 |
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
|
| 2309 |
</parameter>
|
| 2310 |
|
| 2311 |
<!-- Don't set this any higher than max_connections on your
|
| 2312 |
MySQL server, usually this should be a 10 or a few 10's
|
| 2313 |
of connections, not hundreds or thousands -->
|
| 2314 |
|
| 2315 |
<parameter>
|
| 2316 |
<name>maxActive</name>
|
| 2317 |
<value>10</value>
|
| 2318 |
</parameter>
|
| 2319 |
|
| 2320 |
<!-- You don't want to many idle connections hanging around
|
| 2321 |
if you can avoid it, only enough to soak up a spike in
|
| 2322 |
the load -->
|
| 2323 |
|
| 2324 |
<parameter>
|
| 2325 |
<name>maxIdle</name>
|
| 2326 |
<value>5</value>
|
| 2327 |
</parameter>
|
| 2328 |
|
| 2329 |
<!-- Don't use autoReconnect=true, it's going away eventually
|
| 2330 |
and it's a crutch for older connection pools that couldn't
|
| 2331 |
test connections. You need to decide whether your application
|
| 2332 |
is
|
| 2333 |
supposed to deal with SQLExceptions (hint, it should), and
|
| 2334 |
how much of a performance penalty you're willing to pay
|
| 2335 |
to ensure 'freshness' of the connection -->
|
| 2336 |
|
| 2337 |
<parameter>
|
| 2338 |
<name>validationQuery</name>
|
| 2339 |
<value>SELECT 1</value>
|
| 2340 |
</parameter>
|
| 2341 |
|
| 2342 |
<!-- The most conservative approach is to test connections
|
| 2343 |
before they're given to your application. For most application
|
| 2344 |
s
|
| 2345 |
this is okay, the query used above is very small and takes
|
| 2346 |
no real server resources to process, other than the time used
|
| 2347 |
to traverse the network.
|
| 2348 |
|
| 2349 |
If you have a high-load application you'll need to rely on
|
| 2350 |
something else. -->
|
| 2351 |
|
| 2352 |
<parameter>
|
| 2353 |
<name>testOnBorrow</name>
|
| 2354 |
<value>true</value>
|
| 2355 |
</parameter>
|
| 2356 |
|
| 2357 |
<!-- Otherwise, or in addition to testOnBorrow, you can test
|
| 2358 |
while connections are sitting idle -->
|
| 2359 |
|
| 2360 |
<parameter>
|
| 2361 |
<name>testWhileIdle</name>
|
| 2362 |
<value>true</value>
|
| 2363 |
</parameter>
|
| 2364 |
|
| 2365 |
<!-- You have to set this value, otherwise even though
|
| 2366 |
you've asked connections to be tested while idle,
|
| 2367 |
the idle evicter thread will never run -->
|
| 2368 |
|
| 2369 |
<parameter>
|
| 2370 |
<name>timeBetweenEvictionRunsMillis</name>
|
| 2371 |
<value>10000</value>
|
| 2372 |
</parameter>
|
| 2373 |
|
| 2374 |
<!-- Don't allow connections to hang out idle too long,
|
| 2375 |
never longer than what wait_timeout is set to on the
|
| 2376 |
server...A few minutes or even fraction of a minute
|
| 2377 |
is sometimes okay here, it depends on your application
|
| 2378 |
and how much spikey load it will see -->
|
| 2379 |
|
| 2380 |
<parameter>
|
| 2381 |
<name>minEvictableIdleTimeMillis</name>
|
| 2382 |
<value>60000</value>
|
| 2383 |
</parameter>
|
| 2384 |
|
| 2385 |
<!-- Username and password used when connecting to MySQL -->
|
| 2386 |
|
| 2387 |
<parameter>
|
| 2388 |
<name>username</name>
|
| 2389 |
<value>someuser</value>
|
| 2390 |
</parameter>
|
| 2391 |
|
| 2392 |
<parameter>
|
| 2393 |
<name>password</name>
|
| 2394 |
<value>somepass</value>
|
| 2395 |
</parameter>
|
| 2396 |
|
| 2397 |
<!-- Class name for the Connector/J driver -->
|
| 2398 |
|
| 2399 |
<parameter>
|
| 2400 |
<name>driverClassName</name>
|
| 2401 |
<value>com.mysql.jdbc.Driver</value>
|
| 2402 |
</parameter>
|
| 2403 |
|
| 2404 |
<!-- The JDBC connection url for connecting to MySQL, notice
|
| 2405 |
that if you want to pass any other MySQL-specific parameters
|
| 2406 |
you should pass them here in the URL, setting them using the
|
| 2407 |
parameter tags above will have no effect, you will also
|
| 2408 |
need to use & to separate parameter values as the
|
| 2409 |
ampersand is a reserved character in XML -->
|
| 2410 |
|
| 2411 |
<parameter>
|
| 2412 |
<name>url</name>
|
| 2413 |
<value>jdbc:mysql://localhost:3306/test</value>
|
| 2414 |
</parameter>
|
| 2415 |
|
| 2416 |
</ResourceParams>
|
| 2417 |
</Context>
|
| 2418 |
|
| 2419 |
In general, you should follow the installation instructions
|
| 2420 |
that come with your version of Tomcat, as the way you
|
| 2421 |
configure datasources in Tomcat changes from time-to-time,
|
| 2422 |
and unfortunately if you use the wrong syntax in your XML
|
| 2423 |
file, you will most likely end up with an exception similar
|
| 2424 |
to the following:
|
| 2425 |
Error: java.sql.SQLException: Cannot load JDBC driver class 'null ' SQ
|
| 2426 |
L
|
| 2427 |
state: null
|
| 2428 |
|
| 2429 |
1.5.2.3. Using Connector/J with JBoss
|
| 2430 |
|
| 2431 |
These instructions cover JBoss-4.x. To make the JDBC driver
|
| 2432 |
classes available to the application server, copy the .jar
|
| 2433 |
file that comes with Connector/J to the lib directory for
|
| 2434 |
your server configuration (which is usually called default).
|
| 2435 |
Then, in the same configuration directory, in the
|
| 2436 |
subdirectory named deploy, create a datasource configuration
|
| 2437 |
file that ends with "-ds.xml", which tells JBoss to deploy
|
| 2438 |
this file as a JDBC Datasource. The file should have the
|
| 2439 |
following contents:
|
| 2440 |
<datasources>
|
| 2441 |
<local-tx-datasource>
|
| 2442 |
<!-- This connection pool will be bound into JNDI with the nam
|
| 2443 |
e
|
| 2444 |
"java:/MySQLDB" -->
|
| 2445 |
|
| 2446 |
<jndi-name>MySQLDB</jndi-name>
|
| 2447 |
<connection-url>jdbc:mysql://localhost:3306/dbname</connection
|
| 2448 |
-url>
|
| 2449 |
<driver-class>com.mysql.jdbc.Driver</driver-class>
|
| 2450 |
<user-name>user</user-name>
|
| 2451 |
<password>pass</password>
|
| 2452 |
|
| 2453 |
<min-pool-size>5</min-pool-size>
|
| 2454 |
|
| 2455 |
<!-- Don't set this any higher than max_connections on your
|
| 2456 |
MySQL server, usually this should be a 10 or a few 10's
|
| 2457 |
of connections, not hundreds or thousands -->
|
| 2458 |
|
| 2459 |
<max-pool-size>20</max-pool-size>
|
| 2460 |
|
| 2461 |
<!-- Don't allow connections to hang out idle too long,
|
| 2462 |
never longer than what wait_timeout is set to on the
|
| 2463 |
server...A few minutes is usually okay here,
|
| 2464 |
it depends on your application
|
| 2465 |
and how much spikey load it will see -->
|
| 2466 |
|
| 2467 |
<idle-timeout-minutes>5</idle-timeout-minutes>
|
| 2468 |
|
| 2469 |
<!-- If you're using Connector/J 3.1.8 or newer, you can use
|
| 2470 |
our implementation of these to increase the robustness
|
| 2471 |
of the connection pool. -->
|
| 2472 |
|
| 2473 |
<exception-sorter-class-name>com.mysql.jdbc.integration.jboss.
|
| 2474 |
ExtendedMysqlExceptionSorter</exception-sorter-class-name>
|
| 2475 |
<valid-connection-checker-class-name>com.mysql.jdbc.integratio
|
| 2476 |
n.jboss.MysqlValidConnectionChecker</valid-connection-checker-class-na
|
| 2477 |
me>
|
| 2478 |
|
| 2479 |
</local-tx-datasource>
|
| 2480 |
</datasources>
|
| 2481 |
|
| 2482 |
1.5.3. Common Problems and Solutions
|
| 2483 |
|
| 2484 |
There are a few issues that seem to be commonly encountered
|
| 2485 |
often by users of MySQL Connector/J. This section deals with
|
| 2486 |
their symptoms, and their resolutions.
|
| 2487 |
|
| 2488 |
Questions
|
| 2489 |
* [1]1.5.3.1: When I try to connect to the database with
|
| 2490 |
MySQL Connector/J, I get the following exception:
|
| 2491 |
SQLException: Server configuration denies access to data source
|
| 2492 |
SQLState: 08001
|
| 2493 |
VendorError: 0
|
| 2494 |
What's going on? I can connect just fine with the MySQL
|
| 2495 |
command-line client.
|
| 2496 |
* [2]1.5.3.2: My application throws an SQLException 'No
|
| 2497 |
Suitable Driver'. Why is this happening?
|
| 2498 |
* [3]1.5.3.3: I'm trying to use MySQL Connector/J in an
|
| 2499 |
applet or application and I get an exception similar to:
|
| 2500 |
SQLException: Cannot connect to MySQL server on host:3306.
|
| 2501 |
Is there a MySQL server running on the machine/port you
|
| 2502 |
are trying to connect to?
|
| 2503 |
|
| 2504 |
(java.security.AccessControlException)
|
| 2505 |
SQLState: 08S01
|
| 2506 |
VendorError: 0
|
| 2507 |
* [4]1.5.3.4: I have a servlet/application that works fine
|
| 2508 |
for a day, and then stops working overnight
|
| 2509 |
* [5]1.5.3.5: I'm trying to use JDBC-2.0 updatable result
|
| 2510 |
sets, and I get an exception saying my result set is not
|
| 2511 |
updatable.
|
| 2512 |
|
| 2513 |
Questions and Answers
|
| 2514 |
|
| 2515 |
1.5.3.1: When I try to connect to the database with MySQL
|
| 2516 |
Connector/J, I get the following exception:
|
| 2517 |
SQLException: Server configuration denies access to data source
|
| 2518 |
SQLState: 08001
|
| 2519 |
VendorError: 0
|
| 2520 |
|
| 2521 |
What's going on? I can connect just fine with the MySQL
|
| 2522 |
command-line client.
|
| 2523 |
|
| 2524 |
MySQL Connector/J must use TCP/IP sockets to connect to
|
| 2525 |
MySQL, as Java does not support Unix Domain Sockets.
|
| 2526 |
Therefore, when MySQL Connector/J connects to MySQL, the
|
| 2527 |
security manager in MySQL server will use its grant tables to
|
| 2528 |
determine whether the connection should be allowed.
|
| 2529 |
|
| 2530 |
You must add the necessary security credentials to the MySQL
|
| 2531 |
server for this to happen, using the GRANT statement to your
|
| 2532 |
MySQL Server. See [WARNING: missing xref target (id=grant)]
|
| 2533 |
for more information.
|
| 2534 |
|
| 2535 |
Note. Testing your connectivity with the mysql command-line
|
| 2536 |
client will not work unless you add the --host flag, and use
|
| 2537 |
something other than localhost for the host. The mysql
|
| 2538 |
command-line client will use Unix domain sockets if you use
|
| 2539 |
the special hostname localhost. If you are testing
|
| 2540 |
connectivity to localhost, use 127.0.0.1 as the hostname
|
| 2541 |
instead.
|
| 2542 |
|
| 2543 |
Warning. Changing privileges and permissions improperly in
|
| 2544 |
MySQL can potentially cause your server installation to not
|
| 2545 |
have optimal security properties.
|
| 2546 |
|
| 2547 |
1.5.3.2: My application throws an SQLException 'No Suitable
|
| 2548 |
Driver'. Why is this happening?
|
| 2549 |
|
| 2550 |
There are three possible causes for this error:
|
| 2551 |
* The Connector/J driver is not in your CLASSPATH, see
|
| 2552 |
Section A.2, "Installing Connector/J."
|
| 2553 |
* The format of your connection URL is incorrect, or you
|
| 2554 |
are referencing the wrong JDBC driver.
|
| 2555 |
* When using DriverManager, the jdbc.drivers system
|
| 2556 |
property has not been populated with the location of the
|
| 2557 |
Connector/J driver.
|
| 2558 |
|
| 2559 |
1.5.3.3: I'm trying to use MySQL Connector/J in an applet or
|
| 2560 |
application and I get an exception similar to:
|
| 2561 |
SQLException: Cannot connect to MySQL server on host:3306.
|
| 2562 |
Is there a MySQL server running on the machine/port you
|
| 2563 |
are trying to connect to?
|
| 2564 |
|
| 2565 |
(java.security.AccessControlException)
|
| 2566 |
SQLState: 08S01
|
| 2567 |
VendorError: 0
|
| 2568 |
|
| 2569 |
Either you're running an Applet, your MySQL server has been
|
| 2570 |
installed with the "--skip-networking" option set, or your
|
| 2571 |
MySQL server has a firewall sitting in front of it.
|
| 2572 |
|
| 2573 |
Applets can only make network connections back to the machine
|
| 2574 |
that runs the web server that served the .class files for the
|
| 2575 |
applet. This means that MySQL must run on the same machine
|
| 2576 |
(or you must have some sort of port re-direction) for this to
|
| 2577 |
work. This also means that you will not be able to test
|
| 2578 |
applets from your local file system, you must always deploy
|
| 2579 |
them to a web server.
|
| 2580 |
|
| 2581 |
MySQL Connector/J can only communicate with MySQL using
|
| 2582 |
TCP/IP, as Java does not support Unix domain sockets. TCP/IP
|
| 2583 |
communication with MySQL might be affected if MySQL was
|
| 2584 |
started with the "--skip-networking" flag, or if it is
|
| 2585 |
firewalled.
|
| 2586 |
|
| 2587 |
If MySQL has been started with the "--skip-networking" option
|
| 2588 |
set (the Debian Linux package of MySQL server does this for
|
| 2589 |
example), you need to comment it out in the file
|
| 2590 |
/etc/mysql/my.cnf or /etc/my.cnf. Of course your my.cnf file
|
| 2591 |
might also exist in the data directory of your MySQL server,
|
| 2592 |
or anywhere else (depending on how MySQL was compiled for
|
| 2593 |
your system). Binaries created by MySQL AB always look in
|
| 2594 |
/etc/my.cnf and [datadir]/my.cnf. If your MySQL server has
|
| 2595 |
been firewalled, you will need to have the firewall
|
| 2596 |
configured to allow TCP/IP connections from the host where
|
| 2597 |
your Java code is running to the MySQL server on the port
|
| 2598 |
that MySQL is listening to (by default, 3306).
|
| 2599 |
|
| 2600 |
1.5.3.4: I have a servlet/application that works fine for a
|
| 2601 |
day, and then stops working overnight
|
| 2602 |
|
| 2603 |
MySQL closes connections after 8 hours of inactivity. You
|
| 2604 |
either need to use a connection pool that handles stale
|
| 2605 |
connections or use the "autoReconnect" parameter (see Section
|
| 2606 |
A.4.1, "Driver/Datasource Class Names, URL Syntax and
|
| 2607 |
Configuration Properties for Connector/J").
|
| 2608 |
|
| 2609 |
Also, you should be catching SQLExceptions in your
|
| 2610 |
application and dealing with them, rather than propagating
|
| 2611 |
them all the way until your application exits, this is just
|
| 2612 |
good programming practice. MySQL Connector/J will set the
|
| 2613 |
SQLState (see java.sql.SQLException.getSQLState() in your
|
| 2614 |
APIDOCS) to "08S01" when it encounters network-connectivity
|
| 2615 |
issues during the processing of a query. Your application
|
| 2616 |
code should then attempt to re-connect to MySQL at this
|
| 2617 |
point.
|
| 2618 |
|
| 2619 |
The following (simplistic) example shows what code that can
|
| 2620 |
handle these exceptions might look like:
|
| 2621 |
|
| 2622 |
Example 12. Example of transaction with retry logic
|
| 2623 |
public void doBusinessOp() throws SQLException {
|
| 2624 |
Connection conn = null;
|
| 2625 |
Statement stmt = null;
|
| 2626 |
ResultSet rs = null;
|
| 2627 |
|
| 2628 |
//
|
| 2629 |
// How many times do you want to retry the transaction
|
| 2630 |
// (or at least _getting_ a connection)?
|
| 2631 |
//
|
| 2632 |
int retryCount = 5;
|
| 2633 |
|
| 2634 |
boolean transactionCompleted = false;
|
| 2635 |
|
| 2636 |
do {
|
| 2637 |
try {
|
| 2638 |
conn = getConnection(); // assume getting this from a
|
| 2639 |
// javax.sql.DataSource, or th
|
| 2640 |
e
|
| 2641 |
// java.sql.DriverManager
|
| 2642 |
|
| 2643 |
conn.setAutoCommit(false);
|
| 2644 |
|
| 2645 |
//
|
| 2646 |
// Okay, at this point, the 'retry-ability' of the
|
| 2647 |
// transaction really depends on your application logi
|
| 2648 |
c,
|
| 2649 |
// whether or not you're using autocommit (in this cas
|
| 2650 |
e
|
| 2651 |
// not), and whether you're using transacational stora
|
| 2652 |
ge
|
| 2653 |
// engines
|
| 2654 |
//
|
| 2655 |
// For this example, we'll assume that it's _not_ safe
|
| 2656 |
// to retry the entire transaction, so we set retry co
|
| 2657 |
unt
|
| 2658 |
// to 0 at this point
|
| 2659 |
//
|
| 2660 |
// If you were using exclusively transaction-safe tabl
|
| 2661 |
es,
|
| 2662 |
// or your application could recover from a connection
|
| 2663 |
going
|
| 2664 |
// bad in the middle of an operation, then you would n
|
| 2665 |
ot
|
| 2666 |
// touch 'retryCount' here, and just let the loop repe
|
| 2667 |
at
|
| 2668 |
// until retryCount == 0.
|
| 2669 |
//
|
| 2670 |
retryCount = 0;
|
| 2671 |
|
| 2672 |
stmt = conn.createStatement();
|
| 2673 |
|
| 2674 |
String query = "SELECT foo FROM bar ORDER BY baz";
|
| 2675 |
|
| 2676 |
rs = stmt.executeQuery(query);
|
| 2677 |
|
| 2678 |
while (rs.next()) {
|
| 2679 |
}
|
| 2680 |
|
| 2681 |
rs.close();
|
| 2682 |
rs = null;
|
| 2683 |
|
| 2684 |
stmt.close();
|
| 2685 |
stmt = null;
|
| 2686 |
|
| 2687 |
conn.commit();
|
| 2688 |
conn.close();
|
| 2689 |
conn = null;
|
| 2690 |
|
| 2691 |
transactionCompleted = true;
|
| 2692 |
} catch (SQLException sqlEx) {
|
| 2693 |
|
| 2694 |
//
|
| 2695 |
// The two SQL states that are 'retry-able' are 08S01
|
| 2696 |
// for a communications error, and 40001 for deadlock.
|
| 2697 |
//
|
| 2698 |
// Only retry if the error was due to a stale connecti
|
| 2699 |
on,
|
| 2700 |
// communications problem or deadlock
|
| 2701 |
//
|
| 2702 |
|
| 2703 |
String sqlState = sqlEx.getSQLState();
|
| 2704 |
|
| 2705 |
if ("08S01".equals(sqlState) || "40001".equals(sqlStat
|
| 2706 |
e)) {
|
| 2707 |
retryCount--;
|
| 2708 |
} else {
|
| 2709 |
retryCount = 0;
|
| 2710 |
}
|
| 2711 |
} finally {
|
| 2712 |
if (rs != null) {
|
| 2713 |
try {
|
| 2714 |
rs.close();
|
| 2715 |
} catch (SQLException sqlEx) {
|
| 2716 |
// You'd probably want to log this . . .
|
| 2717 |
}
|
| 2718 |
}
|
| 2719 |
|
| 2720 |
if (stmt != null) {
|
| 2721 |
try {
|
| 2722 |
stmt.close();
|
| 2723 |
} catch (SQLException sqlEx) {
|
| 2724 |
// You'd probably want to log this as well . .
|
| 2725 |
.
|
| 2726 |
}
|
| 2727 |
}
|
| 2728 |
|
| 2729 |
if (conn != null) {
|
| 2730 |
try {
|
| 2731 |
//
|
| 2732 |
// If we got here, and conn is not null, the
|
| 2733 |
// transaction should be rolled back, as not
|
| 2734 |
// all work has been done
|
| 2735 |
|
| 2736 |
try {
|
| 2737 |
conn.rollback();
|
| 2738 |
} finally {
|
| 2739 |
conn.close();
|
| 2740 |
}
|
| 2741 |
} catch (SQLException sqlEx) {
|
| 2742 |
//
|
| 2743 |
// If we got an exception here, something
|
| 2744 |
// pretty serious is going on, so we better
|
| 2745 |
// pass it up the stack, rather than just
|
| 2746 |
// logging it. . .
|
| 2747 |
|
| 2748 |
throw sqlEx;
|
| 2749 |
}
|
| 2750 |
}
|
| 2751 |
}
|
| 2752 |
} while (!transactionCompleted && (retryCount > 0));
|
| 2753 |
}
|
| 2754 |
|
| 2755 |
Note. Use of the autoReconnect option is not recommended
|
| 2756 |
because there is no safe method of reconnecting to the MySQL
|
| 2757 |
server without risking some corruption of the connection
|
| 2758 |
state or database state information. Instead, you should use
|
| 2759 |
a connection pool which will enable your application to
|
| 2760 |
connect to the MySQL server using an available connection
|
| 2761 |
from the pool. The autoReconnect facility is deprecated, and
|
| 2762 |
may be removed in a future release.
|
| 2763 |
|
| 2764 |
1.5.3.5: I'm trying to use JDBC-2.0 updatable result sets,
|
| 2765 |
and I get an exception saying my result set is not updatable.
|
| 2766 |
|
| 2767 |
Because MySQL does not have row identifiers, MySQL
|
| 2768 |
Connector/J can only update result sets that have come from
|
| 2769 |
queries on tables that have at least one primary key, the
|
| 2770 |
query must select every primary key and the query can only
|
| 2771 |
span one table (that is, no joins). This is outlined in the
|
| 2772 |
JDBC specification.
|
| 2773 |
|
| 2774 |
Note that this issue only occurs when using updatable result
|
| 2775 |
sets, and is caused because Connector/J is unable to
|
| 2776 |
guarantee that it can identify the correct rows within the
|
| 2777 |
result set to be updated without having a unique reference to
|
| 2778 |
each row. There is no requirement to have a unique field on a
|
| 2779 |
table if you are using UPDATE or DELETE statements on a table
|
| 2780 |
where you can individually specify the criteria to be matched
|
| 2781 |
using a WHERE clause.
|
| 2782 |
|
| 2783 |
1.6. Connector/J Support
|
| 2784 |
|
| 2785 |
1.6.1. Connector/J Community Support
|
| 2786 |
|
| 2787 |
MySQL AB provides assistance to the user community by means
|
| 2788 |
of its mailing lists. For Connector/J related issues, you can
|
| 2789 |
get help from experienced users by using the MySQL and Java
|
| 2790 |
mailing list. Archives and subscription information is
|
| 2791 |
available online at http://lists.mysql.com/java.
|
| 2792 |
|
| 2793 |
For information about subscribing to MySQL mailing lists or
|
| 2794 |
to browse list archives, visit http://lists.mysql.com/. See
|
| 2795 |
MySQL Mailing Lists
|
| 2796 |
(http://dev.mysql.com/doc/refman/5.1/en/mailing-lists.html).
|
| 2797 |
|
| 2798 |
Community support from experienced users is also available
|
| 2799 |
through the JDBC Forum (http://forums.mysql.com/list.php?39).
|
| 2800 |
You may also find help from other users in the other MySQL
|
| 2801 |
Forums, located at http://forums.mysql.com. See MySQL
|
| 2802 |
Community Support at the MySQL Forums
|
| 2803 |
(http://dev.mysql.com/doc/refman/5.1/en/forums.html).
|
| 2804 |
|
| 2805 |
1.6.2. How to Report Connector/J Bugs or Problems
|
| 2806 |
|
| 2807 |
The normal place to report bugs is http://bugs.mysql.com/,
|
| 2808 |
which is the address for our bugs database. This database is
|
| 2809 |
public, and can be browsed and searched by anyone. If you log
|
| 2810 |
in to the system, you will also be able to enter new reports.
|
| 2811 |
|
| 2812 |
If you have found a sensitive security bug in MySQL, you can
|
| 2813 |
send email to security_at_mysql.com
|
| 2814 |
(mailto:security_at_mysql.com).
|
| 2815 |
|
| 2816 |
Writing a good bug report takes patience, but doing it right
|
| 2817 |
the first time saves time both for us and for yourself. A
|
| 2818 |
good bug report, containing a full test case for the bug,
|
| 2819 |
makes it very likely that we will fix the bug in the next
|
| 2820 |
release.
|
| 2821 |
|
| 2822 |
This section will help you write your report correctly so
|
| 2823 |
that you don't waste your time doing things that may not help
|
| 2824 |
us much or at all.
|
| 2825 |
|
| 2826 |
If you have a repeatable bug report, please report it to the
|
| 2827 |
bugs database at http://bugs.mysql.com/. Any bug that we are
|
| 2828 |
able to repeat has a high chance of being fixed in the next
|
| 2829 |
MySQL release.
|
| 2830 |
|
| 2831 |
To report other problems, you can use one of the MySQL
|
| 2832 |
mailing lists.
|
| 2833 |
|
| 2834 |
Remember that it is possible for us to respond to a message
|
| 2835 |
containing too much information, but not to one containing
|
| 2836 |
too little. People often omit facts because they think they
|
| 2837 |
know the cause of a problem and assume that some details
|
| 2838 |
don't matter.
|
| 2839 |
|
| 2840 |
A good principle is this: If you are in doubt about stating
|
| 2841 |
something, state it. It is faster and less troublesome to
|
| 2842 |
write a couple more lines in your report than to wait longer
|
| 2843 |
for the answer if we must ask you to provide information that
|
| 2844 |
was missing from the initial report.
|
| 2845 |
|
| 2846 |
The most common errors made in bug reports are (a) not
|
| 2847 |
including the version number of Connector/J or MySQL used,
|
| 2848 |
and (b) not fully describing the platform on which
|
| 2849 |
Connector/J is installed (including the JVM version, and the
|
| 2850 |
platform type and version number that MySQL itself is
|
| 2851 |
installed on).
|
| 2852 |
|
| 2853 |
This is highly relevant information, and in 99 cases out of
|
| 2854 |
100, the bug report is useless without it. Very often we get
|
| 2855 |
questions like, "Why doesn't this work for me?" Then we find
|
| 2856 |
that the feature requested wasn't implemented in that MySQL
|
| 2857 |
version, or that a bug described in a report has already been
|
| 2858 |
fixed in newer MySQL versions.
|
| 2859 |
|
| 2860 |
Sometimes the error is platform-dependent; in such cases, it
|
| 2861 |
is next to impossible for us to fix anything without knowing
|
| 2862 |
the operating system and the version number of the platform.
|
| 2863 |
|
| 2864 |
If at all possible, you should create a repeatable, stanalone
|
| 2865 |
testcase that doesn't involve any third-party classes.
|
| 2866 |
|
| 2867 |
To streamline this process, we ship a base class for
|
| 2868 |
testcases with Connector/J, named
|
| 2869 |
'com.mysql.jdbc.util.BaseBugReport'. To create a testcase for
|
| 2870 |
Connector/J using this class, create your own class that
|
| 2871 |
inherits from com.mysql.jdbc.util.BaseBugReport and override
|
| 2872 |
the methods setUp(), tearDown() and runTest().
|
| 2873 |
|
| 2874 |
In the setUp() method, create code that creates your tables,
|
| 2875 |
and populates them with any data needed to demonstrate the
|
| 2876 |
bug.
|
| 2877 |
|
| 2878 |
In the runTest() method, create code that demonstrates the
|
| 2879 |
bug using the tables and data you created in the setUp
|
| 2880 |
method.
|
| 2881 |
|
| 2882 |
In the tearDown() method, drop any tables you created in the
|
| 2883 |
setUp() method.
|
| 2884 |
|
| 2885 |
In any of the above three methods, you should use one of the
|
| 2886 |
variants of the getConnection() method to create a JDBC
|
| 2887 |
connection to MySQL:
|
| 2888 |
* getConnection() - Provides a connection to the JDBC URL
|
| 2889 |
specified in getUrl(). If a connection already exists,
|
| 2890 |
that connection is returned, otherwise a new connection
|
| 2891 |
is created.
|
| 2892 |
* getNewConnection() - Use this if you need to get a new
|
| 2893 |
connection for your bug report (i.e. there's more than
|
| 2894 |
one connection involved).
|
| 2895 |
* getConnection(String url) - Returns a connection using
|
| 2896 |
the given URL.
|
| 2897 |
* getConnection(String url, Properties props) - Returns a
|
| 2898 |
connection using the given URL and properties.
|
| 2899 |
|
| 2900 |
If you need to use a JDBC URL that is different from
|
| 2901 |
'jdbc:mysql:///test', override the method getUrl() as well.
|
| 2902 |
|
| 2903 |
Use the assertTrue(boolean expression) and assertTrue(String
|
| 2904 |
failureMessage, boolean expression) methods to create
|
| 2905 |
conditions that must be met in your testcase demonstrating
|
| 2906 |
the behavior you are expecting (vs. the behavior you are
|
| 2907 |
observing, which is why you are most likely filing a bug
|
| 2908 |
report).
|
| 2909 |
|
| 2910 |
Finally, create a main() method that creates a new instance
|
| 2911 |
of your testcase, and calls the run method:
|
| 2912 |
public static void main(String[] args) throws Exception {
|
| 2913 |
new MyBugReport().run();
|
| 2914 |
}
|
| 2915 |
|
| 2916 |
Once you have finished your testcase, and have verified that
|
| 2917 |
it demonstrates the bug you are reporting, upload it with
|
| 2918 |
your bug report to http://bugs.mysql.com/.
|
| 2919 |
|
| 2920 |
1.6.3. Connector/J Change History
|
| 2921 |
|
| 2922 |
The Connector/J Change History (Changelog) is located with
|
| 2923 |
the main Changelog for MySQL. See MySQL Connector/J Change
|
| 2924 |
History
|
| 2925 |
(http://dev.mysql.com/doc/refman/5.1/en/cj-news.html).
|
| 2926 |
|
| 2927 |
References
|
| 2928 |
|
| 2929 |
1. file://localhost/src/extern/MySQL/bk/mysqldoc/refman-5.0/connector-j-nolink.html#qandaitem-1-5-3-1
|
| 2930 |
2. file://localhost/src/extern/MySQL/bk/mysqldoc/refman-5.0/connector-j-nolink.html#qandaitem-1-5-3-2
|
| 2931 |
3. file://localhost/src/extern/MySQL/bk/mysqldoc/refman-5.0/connector-j-nolink.html#qandaitem-1-5-3-3
|
| 2932 |
4. file://localhost/src/extern/MySQL/bk/mysqldoc/refman-5.0/connector-j-nolink.html#qandaitem-1-5-3-4
|
| 2933 |
5. file://localhost/src/extern/MySQL/bk/mysqldoc/refman-5.0/connector-j-nolink.html#qandaitem-1-5-3-5
|