JDBC跟踪是一种为Java应用程序开发人员提供有价值的信息,以帮助他们进行数据库应用程序开发工作的方法。 以下是一些需要了解如何执行JDBC跟踪的实例示例:
DB2 Legacy JDBC驱动程序是旧的Type 2驱动程序,已在较旧的DB2版本中提供。 它建立在DB2 CLI(DB2本地C调用级别接口)之上,该接口本身也建立在其他几层之上。 作为2类驱动程序,它需要安装DB2客户机。 DB2旧版JDBC驱动程序包含在文件db2java.zip中。
在DB2版本8中,提供了一个新的JDBC驱动程序,即所谓的DB2通用JDBC驱动程序 。 它是从头开始编写的,并被构造为允许类型2和类型4连接的抽象JDBC处理器。 进行连接时,应用程序通过使用不同的URL语法选择所需的连接类型。 DB2通用驱动程序使用分布式关系数据库体系结构(DRDA)协议与DB2服务器进行通信,该驱动程序建立在Java客户机层之上,该客户机层替代了CLI和其下的许多层。 仅对于2类连接,才需要安装DB2客户机; 类型4不需要DB2客户机。 DB2通用JDBC驱动程序包含在文件db2jcc.jar中(JCC表示Java Common Connectivity)。 尽管仍支持DB2 Legacy Driver,但将来它将被DB2 Universal JDBC Driver完全替代。
基于CLI的DB2传统JDBC驱动程序类型2为应用程序开发人员提供了两种不同的跟踪可能性:
这两个跟踪变量都通过CLI初始化文件db2cli.ini进行控制。 在Windows系统上,文件db2cli.ini可以在目录%DB2PATH%中找到(缺省情况下为C:\ Program Files \ IBM \ SQLLIB)。 在UNIX / Linux系统上,可以在实例所有者的$ HOME目录中的sqllib / cfg下找到它。
要在JDBC层激活跟踪,请在文件db2cli.ini的[COMMON]
部分下进行以下输入:
[COMMON]
JDBCTrace=1
JDBCTracePathName=
(可选)可以指定关键字JDBCTraceFlush=1
。 在这种情况下,每个跟踪条目都将分别写入跟踪文件。 之后,跟踪文件将关闭并再次打开。 这样可确保即使Java程序崩溃也不会丢失任何跟踪条目。 另一方面,此选项会极大地降低性能。
由于仅在首次建立数据库连接时才读取文件db2cli.ini中的条目,因此对db2cli.ini文件的更改不会影响现有的数据库连接。
当使用DB2传统JDBC驱动程序类型2时,可以使用以下样本程序来测试JDBC跟踪。 在本文的其余部分中,该示例程序还用于演示DB2通用JDBC驱动程序的跟踪功能。
public class LegacyTraceExample
{
public static void main(String[] args) {
try {
// load driver
Class.forName("COM.ibm.db2.jdbc.app.DB2Driver").newInstance();
// set connection properties
String databaseUrl = "jdbc:db2:sample";
// get connection
java.sql.Connection con =
java.sql.DriverManager.getConnection(databaseUrl, "user", "password");
// execute a query
java.sql.Statement stmt = con.createStatement();
String query = "SELECT COUNT(*) FROM SYSCAT.TABLES";
java.sql.ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
System.out.println("\n" + query + " = " + rs.getInt(1));
}
rs.close();
stmt.close();
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
因为该示例程序仅用于演示跟踪工具,所以异常处理减少到最低限度。 首先,动态加载DB2 Legacy JDBC Driver Type 2。 然后,通过JDBC驱动程序管理器建立与数据库的连接,并对系统目录表执行简单查询。
db2cli.ini文件中的以下条目在目录C:\ temp中创建示例程序的JDBC跟踪。
[COMMON]
JDBCTrace=1
JDBCTraceFlush=1
JDBCTracePathName=c:\temp
DB2通用JDBC驱动程序不再基于DB2 CLI层。 对于类型4驱动程序的初始化以及类型2驱动程序的初始化都是如此。 因此,不再可能通过CLI配置更改(文件db2cli.ini)进行JDBC跟踪。 相反,DB2通用JDBC驱动程序允许通过设置某些驱动程序属性进行跟踪。
当使用DataSource
接口进行数据库访问时,可以通过此接口的方法设置跟踪属性。 DB2通用JDBC驱动程序的所有DataSource
类都从基类DB2BaseDataSource
继承,该基类还定义了跟踪的属性。
com.ibm.db2.jcc.DB2BaseDataSource
com.ibm.db2.jcc.DB2SimpleDataSource
com.ibm.db2.jcc.DB2DataSource
com.ibm.db2.jcc.DB2ConnectionPoolDataSource
com.ibm.db2.jcc.DB2XADataSource
在以下示例中, DB2SimpleDataSource
用于数据库访问。 JDBC跟踪的配置对所有DataSource
类均相同,并且独立于DB2通用JDBC驱动程序的类型2或类型4初始化。
下面的示例程序演示了如何通过调用类DB2BaseDataSource
中定义的方法来激活JDBC跟踪。
public class JccTraceExample1
{
public static void main(String[] args) {
try {
// create data source
com.ibm.db2.jcc.DB2SimpleDataSource ds =
new com.ibm.db2.jcc.DB2SimpleDataSource();
// set connection properties
ds.setServerName("localhost");
ds.setPortNumber(50000);
ds.setDatabaseName("sample");
ds.setDriverType(4);
// set trace properties
ds.setTraceDirectory("c:\\temp");
ds.setTraceFile("trace");
ds.setTraceFileAppend(false);
ds.setTraceLevel(com.ibm.db2.jcc.DB2BaseDataSource.TRACE_ALL);
// get connection
java.sql.Connection con = ds.getConnection("user", "password");
// execute a query
java.sql.Statement stmt = con.createStatement();
String query = "SELECT COUNT(*) FROM SYSCAT.TABLES";
java.sql.ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
System.out.println("\n" + query + " = " + rs.getInt(1));
}
rs.close();
stmt.close();
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
首先,初始化用于数据库访问的DB2SimpleDataSource
,在这种情况下,其类型为DB2SimpleDataSource
跟踪的配置通过调用以下方法来完成:
setTraceDirectory
定义写入跟踪文件的目录。 如果定义了跟踪目录,则会为每个数据库连接创建一个单独的跟踪文件。 建议这样做,因为否则所有数据库连接的跟踪数据都将写入单个跟踪文件中,这会使跟踪文件分析变得更加困难。 setTraceFile
定义将跟踪输出写入的文件。 如果将跟踪文件名与跟踪目录一起指定(例如在示例中),则为每个数据库连接创建根据以下模式的跟踪文件:<跟踪目录> \ <跟踪文件> _ <数据源类型> _ <序列号>。 对于示例程序,将创建跟踪文件c:\ temp \ trace_sds_0。 如果未指定跟踪目录,那么所有数据库连接的所有跟踪输出都将写入指定的跟踪文件。 在这种情况下,也可以使用完整路径指定跟踪文件。 setTraceFileAppend
控制跟踪文件是否已覆盖(如果它们已经存在)。 setTraceLevel
定义应跟踪的信息类型。 为此,使用在基类DB2BaseDataSource
中定义的常量。 跟踪常数 | 整数值 |
---|---|
com.ibm.db2.jcc.DB2BaseDataSource.TRACE_NONE |
0 |
com.ibm.db2.jcc.DB2BaseDataSource.TRACE_CONNECTION_CALLS |
1个 |
com.ibm.db2.jcc.DB2BaseDataSource.TRACE_STATEMENT_CALLS |
2 |
com.ibm.db2.jcc.DB2BaseDataSource.TRACE_RESULT_SET_CALLS |
4 |
com.ibm.db2.jcc.DB2BaseDataSource.TRACE_DRIVER_CONFIGURATION |
16 |
com.ibm.db2.jcc.DB2BaseDataSource.TRACE_CONNECTS |
32 |
com.ibm.db2.jcc.DB2BaseDataSource.TRACE_DRDA_FLOWS |
64 |
com.ibm.db2.jcc.DB2BaseDataSource.TRACE_RESULT_SET_META_DATA |
128 |
com.ibm.db2.jcc.DB2BaseDataSource.TRACE_PARAMETER_META_DATA |
256 |
com.ibm.db2.jcc.DB2BaseDataSource.TRACE_DIAGNOSTICS |
512 |
com.ibm.db2.jcc.DB2BaseDataSource.TRACE_SQLJ |
1024 |
com.ibm.db2.jcc.DB2BaseDataSource.TRACE_XA_CALLS |
2048 |
com.ibm.db2.jcc.DB2BaseDataSource.TRACE_ALL |
-1 |
在样本程序中,将收集所有跟踪信息( com.ibm.db2.jcc.DB2BaseDataSource.TRACE_ALL
)。 如果仅希望跟踪某些信息,则可以使用OR运算符组合跟踪常量(例如com.ibm.db2.jcc.DB2BaseDataSource.TRACE_STATEMENT_CALLS | com.ibm.db2.jcc.DB2BaseDataSource.TRACE_RESULT_SET_CALLS
)。
这种跟踪可能会有些问题,因为它需要更改源代码,这并非在所有情况下都是理想的。 当数据源与源代码分开定义时(如果使用类似WebSphere的应用程序服务器,则为true),可以将跟踪属性与数据源的定义一起指定。 这允许在不更改源代码的情况下激活/停用跟踪。
但是,即使在源代码中定义了数据源(例如在示例程序中),也可以在不更改源代码的情况下控制跟踪。 清单6显示了未设置跟踪属性的示例程序。
public class JccTraceExample2
{
public static void main(String[] args) {
try {
// create data source
com.ibm.db2.jcc.DB2SimpleDataSource ds =
new com.ibm.db2.jcc.DB2SimpleDataSource();
// set connection properties
ds.setServerName("localhost");
ds.setPortNumber(50000);
ds.setDatabaseName("sample");
ds.setDriverType(4);
// get connection
java.sql.Connection con = ds.getConnection("user", "password");
// execute a query
java.sql.Statement stmt = con.createStatement();
String query = "SELECT COUNT(*) FROM SYSCAT.TABLES";
java.sql.ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
System.out.println("\n" + query + " = " + rs.getInt(1));
}
rs.close();
stmt.close();
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
要在不更改源代码的情况下控制跟踪,请创建一个包含跟踪属性的单独配置文件。
db2.jcc.traceDirectory=c:\\temp
db2.jcc.traceFile=trace
db2.jcc.traceFileAppend=false
db2.jcc.traceLevel=-1
此配置文件没有命名约定。 执行Java程序时,通过选项-D指定文件名。 例如,如果配置文件名为jcc.properties,则程序调用如下所示。
java -Ddb2.jcc.propertiesFile=jcc.properties JccTraceExample2
在这种情况下,配置文件与Java类文件放置在同一目录中。 否则,也可以指定配置文件的完整路径。
如果使用配置文件,则不能将跟踪级别指定为常量,而必须使用相应的整数值,例如对于TRACE_ALL
为-1,对于TRACE_STATEMENT_CALLS | TRACE_RESULT_SET_CALLS
为TRACE_STATEMENT_CALLS | TRACE_RESULT_SET_CALLS
TRACE_STATEMENT_CALLS | TRACE_RESULT_SET_CALLS
(在这种情况下,只需将值相加= 2 + 4)。
因为配置文件中的属性不限于某个数据源,所以它们会自动引用所有数据源。 因此,生成的跟踪文件名与上一个示例中的文件名不同。 如果指定了跟踪目录以及跟踪文件,则将为每个数据库连接创建根据以下模式的跟踪文件:<跟踪目录> \ <跟踪文件> _global_ <序列号>。 对于示例程序,将创建跟踪文件c:\ temp \ trace_global_0。
如果在源代码和配置文件中也指定了跟踪属性,那么将使用在源代码中定义的属性。 要强制使用配置文件中的跟踪属性,必须使用附加替代指定配置文件中的跟踪属性。
db2.jcc.override.traceDirectory=c:\\temp
db2.jcc.override.traceFile=trace
db2.jcc.override.traceFileAppend=false
db2.jcc.override.traceLevel=-1
除了数据源, DriverManager
接口还可以用于建立数据库连接。 在这种情况下,可以将跟踪属性指定为数据库URL的补充。
public class JccTraceExample3
{
public static void main(String[] args) {
try {
// load driver
Class.forName("com.ibm.db2.jcc.DB2Driver").newInstance();
// set connection properties
String databaseUrl = "jdbc:db2://localhost:50000/sample"
+ ":traceDirectory=c:\\temp"
+ ";traceFile=trace"
+ ";traceFileAppend=false"
+ ";traceLevel="
+ com.ibm.db2.jcc.DB2BaseDataSource.TRACE_ALL
+ ";";
// get connection
java.sql.Connection con =
java.sql.DriverManager.getConnection(databaseUrl, "user", "password");
// execute a query
java.sql.Statement stmt = con.createStatement();
String query = "SELECT COUNT(*) FROM SYSCAT.TABLES";
java.sql.ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
System.out.println("\n" + query + " = " + rs.getInt(1));
}
rs.close();
stmt.close();
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
如果指定了跟踪目录以及跟踪文件,则会为每个数据库连接创建以下模式的跟踪文件:<跟踪目录> \ <跟踪文件> _driver_ <顺序号>。 对于示例程序,将创建跟踪文件c:\ temp \ trace_driver_0。
另外,跟踪输出可以重定向到PrintWriter
。 在这种情况下,通过调用com.ibm.db2.jcc.DB2Connection
类的setJccLogWriter
方法来激活跟踪。 作为参数,该方法期望使用PrintWriter
以及跟踪级别。
public class JccTraceExample4
{
public static void main(String[] args) {
try {
// create print writer
java.io.PrintWriter printWriter = new java.io.PrintWriter(
new java.io.BufferedOutputStream(
new java.io.FileOutputStream("c:\\temp\\trace.txt"), 4096), true);
// create data source
com.ibm.db2.jcc.DB2SimpleDataSource ds =
new com.ibm.db2.jcc.DB2SimpleDataSource();
// set connection properties
ds.setServerName("localhost");
ds.setPortNumber(50000);
ds.setDatabaseName("sample");
ds.setDriverType(4);
// get connection
java.sql.Connection con = ds.getConnection("user", "password");
// activate trace
((com.ibm.db2.jcc.DB2Connection) con).setJccLogWriter(printWriter,
com.ibm.db2.jcc.DB2BaseDataSource.TRACE_ALL);
// execute a query
java.sql.Statement stmt = con.createStatement();
String query = "SELECT COUNT(*) FROM SYSCAT.TABLES";
java.sql.ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
System.out.println("\n" + query + " = " + rs.getInt(1));
}
rs.close();
stmt.close();
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
我要感谢Peter Schurr审阅本文。
翻译自: https://www.ibm.com/developerworks/data/library/techarticle/dm-0506fechner/index.html