Programming WebLogic JDBC
Programming WebLogic JDBC
Programming WebLogic JDBC
Server and ™
WebLogic
Express ®
Programming WebLogic
JDBC
Release 7.0
Document Revised: December 4, 2002
Copyright
Copyright © 2002 BEA Systems, Inc. All Rights Reserved.
Adobe Acrobat Reader is available at no charge from the Adobe Web site at
http://www.adobe.com.
Contact Us!
Your feedback on BEA documentation is important to us. Send us e-mail at
[email protected] if you have questions or comments. Your comments will be
reviewed directly by the BEA professionals who create and update the documentation.
In your e-mail message, please indicate the software name and version your are using,
as well as the title and document date of your documentation. If you have any questions
about this version of BEA WebLogic Server, or if you have problems installing and
running BEA WebLogic Server, contact BEA Customer Support through BEA
WebSupport at http://www.bea.com. You can also contact Customer Support by using
the contact information provided on the Customer Support Card, which is included in
the product package.
Convention Usage
monospace Code samples, commands and their options, Java classes, data types,
text directories, and filenames and their extensions. Monospace text also
indicates text that you enter from the keyboard.
Examples:
import java.util.Enumeration;
chmod u+w *
config/examples/applications
.java
config.xml
float
. Indicates the omission of items from a code example or from a syntax line.
.
.
1 Introduction to
WebLogic JDBC
The following sections provide an overview of the JDBC components and JDBC API:
Overview of JDBC
Java Database Connectivity (JDBC) is a standard Java API that consists of a set of
classes and interfaces written in the Java programming language. Application, tool,
and database developers use JDBC to write database applications and execute SQL
statements.
JDBC is a low-level interface, which means that you use it to invoke (or call) SQL
commands directly. In addition, JDBC is a base upon which to build higher-level
interfaces and tools, such as Java Message Service (JMS) and Enterprise Java Beans
(EJBs).
! Two-tier drivers that provide database access directly between a connection pool
and the database. WebLogic Server uses a DBMS vendor-specific JDBC driver,
such as the WebLogic jDrivers for Oracle and Microsoft SQL Server, to connect
to a back-end database.
The middle tier architecture of WebLogic Server, including data sources and
connection pools, allows you to manage database resources centrally in WebLogic
Server. The vendor-neutral multitier JDBC drivers makes it easier to adapt purchased
components to your DBMS environment and to write more portable code.
Two-tier Type 2 (requires native libraries): Between WebLogic Programming WebLogic JDBC
without ! WebLogic jDriver for Oracle Server and DBMS in (this document)
support for local transactions. Administration Guide, “Managing
! Third-party drivers
distributed JDBC Connectivity”
transactions Type 4 (pure Java)
Using WebLogic jDriver for
(non-XA) ! WebLogic jDrivers for
Oracle
Microsoft SQL Server
Using WebLogic jDriver for
! Third-party drivers,
Microsoft SQL Server
including:
Oracle Thin
Sybase jConnect
Two-tier Type 2 (requires native libraries) Between WebLogic Programming WebLogic JTA
with ! WebLogic jDriver for Oracle Server and DBMS in Administration Guide, “Managing
support for XA distributed transactions. JDBC Connectivity”
distributed
Using WebLogic jDriver for
transactions
Oracle
(XA)
For more details about using these drivers, see Chapter 4, “Using WebLogic Multitier
JDBC Drivers.”
You can use the WebLogic RMI driver with server-side or client applications.
For more details about using the WebLogic RMI driver, see “Using the WebLogic
RMI Driver” on page 4-1.
For more details about using the WebLogic JTS driver, see “Using the WebLogic JTS
Driver” on page 4-7.
Third-Party Drivers
WebLogic Server works with third-party JDBC drivers that meet the following
requirements:
! Are thread-safe.
! Support the JDBC API. Drivers can support extensions to the API, but they must
support the JDBC API as a minimum.
You typically use these drivers when configuring WebLogic Server to create physical
database connections in a connection pool.
When the connection pool starts up, it creates a specified number of physical database
connections. By establishing connections at start-up, the connection pool eliminates
the overhead of creating a database connection for each application.
Connection pools require a two-tier JDBC driver to make the physical database
connections from WebLogic Server to the DBMS. The two-tier driver can be one of
the WebLogic jDrivers or a third-party JDBC driver, such as the Sybase jConnect
driver or the Oracle Thin Driver. The following table summarizes the advantages to
using connection pools.
Save time, low overhead Making a DBMS connection is very slow. With
connection pools, connections are already
established and available to users. The alternative is
for applications to make their own JDBC
connections as needed. A DBMS runs faster with
dedicated connections than if it has to handle
incoming connection attempts at run time.
Allow use of the DBMS If you use the DBMS persistence option with some
persistence option APIs, such as EJBs, pools are mandatory so that
WebLogic Server can control the JDBC connection.
This ensures your EJB transactions are committed or
rolled back correctly and completely.
This section is an overview of connection pools. For more detailed information, see
“Configuring and Using Connection Pools” on page 2-2.
instance, use a TxDataSource from the JNDI tree or use the JTS driver. BEA
recommends that you access connection pools using the JNDI tree and a DataSource
object rather than using WebLogic multitier drivers.
The WebLogic RMI driver is a Type 3, multitier JDBC driver that uses RMI and a
DataSource object to create database connections. This driver also provides for
clustered JDBC, leveraging the load balancing and failover features of WebLogic
Server clusters. You can define DataSource objects to enable transactional support or
not.
Overview of MultiPools
JDBC MultiPools are “pools of connection pools” that you can set up according to
either a high availability or load balancing algorithm. You use a MultiPool in the same
manner that you use a connection pool. When an application requests a connection, the
MultiPool determines which connection pool will provide a connection, according to
the selected algorithm. MultiPools are not supported multiple-server configurations or
with distributed transactions.
You can choose one of the following algorithm options for each MultiPool in your
WebLogic Server configuration:
! High availability, in which the connection pools are set up as an ordered list and
used sequentially.
! Load balancing, in which all listed pools are accessed using a round-robin
scheme.
For more information, see “Configuring and Using MultiPools” on page 2-15.
Overview of DataSources
Client and server-side JDBC applications can obtain a DBMS connection using a
DataSource. A DataSource is an interface between an application and the connection
pool. Each data source (such as a DBMS instance) requires a separate DataSource
object, which may be implemented as a DataSource class that supports distributed
transactions. For more information, see “Configuring and Using DataSources” on page
2-17.
JDBC API
To create a JDBC application, use the java.sql API to create the class objects necessary
to establish a connection with a data source, to send queries and update statements to
the data source, and to process the results. For a complete description of all JDBC
interfaces, see the standard JDBC interfaces at java.sql Javadoc. Also see the
following WebLogic Javadocs:
! weblogic.jdbc.pool
JDBC 2.0
WebLogic Server uses JDK 1.3.1, which supports JDBC 2.0.
Platforms
Supported platforms vary by vendor-specific DBMSs and drivers. For current
information, see BEA WebLogic Server Platform Support at
http://e-docs.bea.com/wls/certifications/certifications/index.htm
l.
2 Configuring and
Administering
WebLogic JDBC
You use WebLogic Server Administration Console to enable, configure, and monitor
features of the WebLogic Server, including JDBC.
The following sections describe how to program the JDBC connectivity components:
! Using connection pools is far more efficient than creating a new connection for
each client each time they need to access the database.
! You do not need to hard-code details such as the DBMS password in your
application.
! You can limit the number of connections to your DBMS. This can be useful for
managing licensing restrictions on the number of connections to your DBMS.
! You can change the DBMS you are using without changing your application
code.
The attributes for a configuring a connection pool are defined in the Administration
Console Online Help. There is also an API that you can use to programmatically create
connection pools in a running WebLogic Server; see “Creating a Connection Pool
Dynamically” on page 2-5. You can also use the command line; see the Web Logic
Server Command-Line Interface Reference in the Administration Guide at
http://e-docs.bea.com/wls/docs70/adminguide/cli.html.
For step-by-step instructions and a description of connection pool attributes, see the
Administration Console Online Help, available when you click the question mark in
the upper-right corner of the Administration Console or at
http://e-docs.bea.com/wls/docs70/ConsoleHelp/jdbc.html. For more
information about creating and configuring connection pools with the Administration
Console, see “Managing JDBC Connectivity” in the Administration Guide at
http://e-docs.bea.com/wls/docs70/adminguide/jdbc.html.
! Password. Use this field to set the database password. This value overrides any
password value defined in the Properties passed to the tier-2 JDBC Driver
when creating physical database connections. The value is encrypted in the
config.xml file (stored as the Password attribute in the JDBCConnectionPool
tag) and is hidden on the administration console.
! Open String Password. Use this field to set the password in the open string
that the transaction manager in WebLogic Server uses to open a database
connection. This value overrides any password defined as part of the open string
in the Properties field. The value is encrypted in the config.xml file (stored
as the XAPassword attribute in the JDBCConnectionPool tag) and is hidden on
the Administration Console. At runtime, WebLogic Server reconstructs the open
string with the password you specify in this field. The open string in the
Properties field should follow this format:
openString=Oracle_XA+Acc=P/userName/+SesTm=177+DB=demoPool+Thre
ads=true=Sqlnet=dvi0+logDir=.
Note that after the userName there is no password.
If you specify a password in the Properties field when you first configure the
connection pool, WebLogic Server removes the password from the Properties string
and sets the value as the Password value in an ecrypted form the next time you start
WebLogic Server. If there is already a value for the Password attribute for the
connection pool, WebLogic Server does not change any values. However, the value for
the Password attribute overrides the password value in the Properties string. The
same behavior applies to any password that you define as part of an open string. For
example, if you include the following properties when you first configure a connection
pool:
user=scott;
password=tiger;
openString=Oracle_XA+Acc=p/scott/tiger+SesTm=177+db=jtaXaPool+Thr
eads=true+Sqlnet=lcs817+logDir=.+dbgFl=0x15;server=lcs817
The next time you start WebLogic Server, it moves the database password and the
password included in the open string to the Password and Open String Password
attributes, respectively, and the following value remains for the Properties field:
user=scott;
openString=Oracle_XA+Acc=p/scott/+SesTm=177+db=jtaXaPool+Threads=
true+Sqlnet=lcs817+logDir=.+dbgFl=0x15;server=lcs817
After a value is established for the Password or Open String Password attributes,
the values in these attributes override the respective values in the Properties
attribute. That is, continuing with the previous example, if you specify tiger2 as the
database password in the Properties attribute, WebLogic Server ignores the value
and continues to use tiger as the database password, which is the current encrypted
value of the Password attribute. To change the database password, you must change
the Password attribute.
Note: The value for Password and Open String Password do not need to be the
same.
You can also use the CREATE_POOL command in the WebLogic Server command line
interface to dynamically create a connection pool. See CREATE_POOL in the
Administration Guide at
http://e-docs.bea.com/wls/docs70/adminguide/cli.html#cli_create_p
ool.
When you create a connection pool using the JDBCConnectionPool MBean, the
connection pool is added to the server configuration and will be available even if you
stop and restart the server. If you do not want the connection pool to be persistent, you
must remove it programmatically.
Also, you can temporarily disable dynamically created connection pools, which
suspends communication with the database server through any connection in the pool.
When a disabled pool is re-enabled, each connection returns to the same state as when
the pool was disabled; clients can continue their database operations exactly where
they left off.
For more information about using MBeans to manage WebLogic Server, see
Programming WebLogic Management Services with JMX at
http://e-docs.bea.com/wls/docs70/jmx/index.html. For more information
about the JDBCConnectionPool MBean, see the Javadoc at
http://e-docs.bea.com/wls/docs70/javadocs/weblogic/management/con
figuration/JDBCConnectionPoolMBean.html.
Import Packages
import java.sql.*;
import java.util.*;
import javax.naming.Context;
import javax.sql.DataSource;
import weblogic.jndi.Environment;
import weblogic.management.configuration.JDBCConnectionPoolMBean;
import weblogic.management.runtime.JDBCConnectionPoolRuntimeMBean;
import weblogic.management.configuration.JDBCDataSourceMBean;
import weblogic.management.configuration.ServerMBean;
import weblogic.management.MBeanHome;
import weblogic.management.WebLogicObjectName;
cpMBean.setRefreshMinutes(10);
cpMBean.setTestTableName("dual");
Create a DataSource
public void createDataSource() throws SQLException {
try {
// Get context
Environment env = new Environment();
env.setProviderUrl(url);
env.setSecurityPrincipal(userName);
env.setSecurityCredentials(password);
ctx = env.getInitialContext();
// Startup datasource
dsMBeans.addTarget(serverMBean);
try {
dsMBeans.removeTarget(serverMBean);
mbeanHome.deleteMBean(dsMBeans);
! Shrinking a pool, which releases unused connections until the pool has reached
the minimum specified pool size
props = JDBCConnectionPoolRuntimeMBean.getProperties();
The poolExists() method tests whether a connection pool with a specified name
exists in the WebLogic Server. You can use this method to determine whether a
dynamic connection pool has already been created or to ensure that you select a unique
name for a dynamic connection pool you want to create.
You can temporarily disable a connection pool, preventing any clients from obtaining
a connection from the pool. Only the “system” user or users granted “admin”
permission by an ACL associated with a connection pool can disable or enable the
pool.
You can also use the disable_pool and enable_pool commands of the
weblogic.Admin class to disable and enable a pool.
A connection pool has a set of properties that define the initial and maximum number
of connections in the pool (initialCapacity and maxCapacity), and the number of
connections added to the pool when all connections are in use (capacityIncrement).
When the pool reaches its maximum capacity, the maximum number of connections
are opened, and they remain opened unless you shrink the pool.
You may want to drop some connections from the connection pool when a peak usage
period has ended, freeing up WebLogic Server and DBMS resources.
These methods destroy a connection pool. Connections are closed and removed from
the pool and the pool dies when it has no remaining connections. Only the “system”
user or users granted “admin” permission by an ACL associated with a connection pool
can destroy the pool.
The shutdownSoft() method waits for connections to be returned to the pool before
closing them.
You can also use the destroy_pool command of the weblogic.Admin class to
destroy a pool.
Resetting a Pool
JDBCConnectionPoolRuntimeMBean.reset()
You can configure a connection pool to test its connections either periodically, or
every time a connection is reserved or released. Allowing the WebLogic Server to
automatically maintain the integrity of pool connections should prevent most DBMS
connection problems. In addition, WebLogic provides methods you can call from an
application to refresh all connections in the pool or a single connection you have
reserved from the pool.
a. In a try block, test a connection from the connection pool with a SQL
statement that is guaranteed to succeed under any circumstances so long as
there is a working connection to the DBMS. An example is the SQL statement
select 1 from dual which is guaranteed to succeed for an Oracle DBMS.
! disable
After any of these actions, applications on managed servers that use the affected
connection pool may fail.
An instance of the connection pool is created with each instance of your application.
This means an instance of the pool is created with the application on each node that the
application is targeted to. It is important to keep this in mind when considering pool
sizing.
For more information about application scoping and application scoped resources, see:
You create a MultiPool by first creating connection pools, then creating the MultiPool
using the Administration Console or WebLogic Management API and assigning the
connection pools to the MultiPool.
For instructions to create a MultiPool using the Administration Console, see the
Administration Console Online Help at
http://e-docs.bea.com/wls/docs70/ConsoleHelp/jdbc.html#jdbc_metap
ool_create. For information about the JDBCMultiPoolMBean, see the WebLogic
Server Javadocs at
http://e-docs.bea.com/wls/docs70/javadocs/weblogic/management/con
figuration/JDBCMultiPoolMBean.html.
MultiPool Features
A MultiPools is a pool of connection pools in a single server. All the connections in a
particular connection pool are created identically with a single database, single user,
and the same connection attributes; that is, they are attached to a single database.
However, the connection pools within a MultiPool may be associated with different
users or DBMSs.
MultiPools are used in local transactions and are not supported by WebLogic Server
for distributed transactions.
Note: Capacity is not a failover reason, because users have the right to set capacity.
MultiPools take effect only if loss of database connectivity has occurred.
High Availability
The High Availability algorithm provides an ordered list of connection pools.
Normally, every connection request to this kind of MultiPool is served by the first pool
in the list. If a database connection via that pool fails, then a connection is sought
sequentially from the next pool on the list.
Load Balancing
Connection requests to a load balancing MultiPool are served from any connection
pool in the list. Pools are added without any attached ordering and are accessed using
a round-robin scheme. When switching connections, the connection pool just after the
last pool accessed is selected.
Exceptions
Entries are posted to the JDBC log under these circumstances:
Capacity Issues
In a high availability scenario, the fact that the first pool in the list is busy does not
trigger an attempt to get a connection from the next pool in the list.
DataSource objects, along with the JNDI, provide access to connection pools for
database connectivity. Each DataSource can refer to one connection pool or MultiPool.
However, you can define multiple DataSources that use a single connection pool. This
allows you to define both transaction and non-transaction-enabled DataSource objects
that share the same database.
If your application meets any of the following criteria, you should use a TxDataSource
in WebLogic Server:
For more information about when to use a TxDataSource and how to configure a
TxDataSource, see JDBC Configuration Guidelines for Connection Pools, MultiPools,
and DataSources in the Administration Guide at
http://e-docs.bea.com/wls/docs70/adminguide/jdbc.html#jdbc002.
try {
ctx = new InitialContext(ht);
javax.sql.DataSource ds
= (javax.sql.DataSource) ctx.lookup ("myJtsDataSource");
java.sql.Connection conn = ds.getConnection();
// Close the statement and connection objects when you are finished:
stmt.close();
conn.close();
}
catch (NamingException e) {
// a failure occurred
}
finally {
try {ctx.close();}
catch (Exception e) {
// a failure occurred
}
}
(Substitute the correct hostname and port number for your WebLogic Server.)
Note: The code above uses one of several available procedures for obtaining a JNDI
context. For more information on JNDI, see Programming WebLogic JNDI
at http://e-docs.bea.com/wls/docs70/jndi/index.html.
Code Examples
See the DataSource code example in the samples/examples/jdbc/datasource
directory of your WebLogic Server installation.
For details about creating and using a JDBC Data Source factory, see Resource
Factories in Programming WebLogic Enterprise JavaBeans at
http://e-docs.bea.com/wls/docs70/ejb/EJB_environment.html#resourc
efact.
3 Performance Tuning
Your JDBC Application
The following sections explain how to get the most out of your applications:
When WebLogic Server starts, connections from the connection pools are opened and
are available to all clients. When a client closes a connection from a connection pool,
the connection is returned to the pool and becomes available for other clients; the
connection itself is not closed. There is little cost to opening and closing pool
connections.
How many connections should you create in the pool? A connection pool can grow and
shrink according to configured parameters, between a minimum and a maximum
number of connections. The best performance will always be when the connection pool
has as many connections as there are concurrent users.
The following are general hints that apply to all DBMSs. It is also important to be
familiar with the performance documentation of the specific DBMS that you use in
your application.
Most DBMSs provide stored procedures, an ideal tool for putting your logic where
your data is. There is a significant difference in performance between a client that calls
a stored procedure to update 10 rows, and another client that fetches those rows, alters
them, and sends update statements to save the changes to the DBMS.
Also review the DBMS documentation on managing cache memory in the DBMS.
Some DBMSs (Sybase, for example) provide the means to partition the virtual
memory allotted to the DBMS, and to guarantee certain objects exclusive use of some
fixed areas of cache. This means that an important table or index can be read once from
disk and remain available to all clients without having to access the disk again.
Many complicated processes that were originally thought too complex to do any other
way but row-at-a-time have been rewritten using set-based processing, resulting in
improved performance. For example, a major payroll application was converted from
a huge slow COBOL application to four stored procedures running in series, and what
took hours on a multi-CPU machine now takes fifteen minutes with many fewer
resources used.
This returns the number of rows the original query would have returned, assuming no
change in relevant data. The actual count may change when the query is issued if other
DBMS activity has occurred that alters the relevant data.
Make your application queries as specific as possible about what data it actually wants.
For example, tailor your application to select into temporary tables, returning only the
count, and then sending a refined second query to return only a subset of the rows in
the temporary table.
Learning to select only the data you really want at the client is crucial. Some
applications ported from ISAM (a pre-relational database architecture) will
unnecessarily send a query selecting all the rows in a table when only the first few rows
are required. Some applications use a 'sort by' clause to get the rows they want to come
back first. Database queries like this cause unnecessary degradation of performance.
Proper use of SQL can avoid these performance problems. For example, if you only
want data about the top three earners on the payroll, the proper way to make this query
is with a correlated subquery. Table 3-1 shows the entire table returned by the SQL
statement
select * from payroll
Joe 10
Mikes 20
Sam 30
Tom 40
Jan 50
Ann 60
Sue 70
Hal 80
May 80
A correlated subquery
select p.name, p.salary from payroll p
where 3 >= (select count(*) from payroll pp
where pp.salary >= p.salary);
Sue 70
Hal 80
May 80
This query returns only three rows, with the name and salary of the top three earners.
It scans through the payroll table, and for every row, it goes through the whole payroll
table again in an inner loop to see how many salaries are higher than the current row
of the outer scan. This may look complicated, but DBMSs are designed to use SQL
efficiently for this type of operation.
This approach results in better performance than using separate statements and
commits. Even with conditional logic and temporary tables in the batch, it is preferable
because the DBMS obtains all the locks necessary on the various rows and tables, and
uses and releases them in one step. Using separate statements and commits results in
many more client-to-DBMS transmissions and holds the locks in the DBMS for much
longer. These locks will block out other clients from accessing this data, and,
depending on whether different updates can alter tables in different orders, may cause
deadlocks.
Warning: If any individual statement in the preceding transaction fails, due, for
instance, to violating a unique key constraint, you should put in conditional SQL logic
to detect statement failure and to roll back the transaction rather than commit. If, in the
preceding example, the insert failed, most DBMSs return an error message about the
failed insert, but behave as if you got the message between the second and third
statement, and decided to commit anyway! Microsoft SQL Server offers a connection
option enabled by executing the SQL set xact_abort on, which automatically rolls
back the transaction if any statement fails.
If you require user input to form or complete a transaction, use optimistic locking.
Briefly, optimistic locking employs timestamps and triggers in queries and updates.
Queries select data with timestamp values and prepare a transaction based on that data,
without locking the data in a transaction.
When an update transaction is finally defined by the user input, it is sent as a single
submission that includes timestamped safeguards to make sure the data is the same as
originally fetched. A successful transaction automatically updates the relevant
timestamps for changed data. If an interceding update from another client has altered
data on which the current transaction is based, the timestamps change, and the current
transaction is rejected. Most of the time, no relevant data has been changed so
transactions usually succeed. When a transaction fails, the application can refetch the
updated data to present to the user to reform the transaction if desired.
4 Using WebLogic
Multitier JDBC Drivers
BEA recommends that you use DataSource objects to get database connections in new
applications. DataSource objects, along with the JNDI, provide access to connection
pools for database connectivity. For existing or legacy applications that use the JDBC
1.x API, you can use the WebLogic multitier drivers to get database connectivity.
The following sections describe how to use multitier JDBC drivers with WebLogic
Server:
RMI driver clients make their connection to the DBMS by looking up the DataSource
object. This lookup is accomplished by using a Java Naming and Directory Service
(JNDI) lookup, or by directly calling WebLogic Server which performs the JNDI
lookup on behalf of the client.
The RMI driver replaces the functionality of both the WebLogic t3 driver (deprecated)
and the Pool driver, and uses the Java standard Remote Method Invocation (RMI) to
connect to WebLogic Server rather than the proprietary t3 protocol.
Because the details of the RMI implementation are taken care of automatically by the
driver, a knowledge of RMI is not required to use the WebLogic JDBC/RMI driver.
java.util.*
javax.naming.*
! Using a JNDI lookup. This is the preferred and most direct procedure.
! Passing the DataSource name to the RMI driver with the
Driver.connect()method. In this case, WebLogic Server performs the JNDI
look up on behalf of the client.
try {
ctx = new InitialContext(ht);
javax.sql.DataSource ds
= (javax.sql.DataSource) ctx.lookup ("myDataSource");
java.sql.Connection conn = ds.getConnection();
stmt.close();
conn.close();
}
catch (NamingException e) {
// a failure occurred
}
finally {
try {ctx.close();}
catch (Exception e) {
// a failure occurred
}
}
(Where hostname is the name of the machine running your WebLogic Server and
port is the port number where that machine is listening for connection requests.)
In this example a Hashtable object is used to pass the parameters required for the JNDI
lookup. There are other ways to perform a JNDI lookup. For more information, see
Programming WebLogic JNDI at
http://e-docs.bea.com/wls/docs70/jndi/index.html.
Notice that the JNDI lookup is wrapped in a try/catch block in order to catch a failed
look up and also that the context is closed in a finally block.
(Where hostname is the name of the machine running your WebLogic Server and
port is the port number where that machine is listening for connection requests.)
You can also define the following properties which will be used to set the JNDI user
information:
! weblogic.user—specifies a username
Note: WebLogic Server will not perform row caching when the client and WebLogic
Server are in the same JVM.
You can enable and disable row caching and set the number of rows fetched per
ResultSet.next() call with the Data Source attributes Row Prefetch Enabled and
Row Prefetch Size, respectively. You set Data Source attributes via the Administration
Console. To enable row caching and to set the row prefetch size attribute for a
DataSource or TxDataSource, follow these steps:
2. In the right pane of the Administration Console, select the Configuration tab if it
is not already selected.
4. In Row Prefetch Size, type the number of rows you want to cache for each
ResultSet.next() call.
Important Limitations for Row Caching with the WebLogic RMI Driver
Keep the following limitations in mind if you intend to implement row caching with
the RMI driver:
! WebLogic Server only performs row caching if the result set type is both
TYPE_FORWARD_ONLY and CONCUR_READ_ONLY.
! Certain data types in a result set may disable caching for that result set. These
include the following:
" LONGVARCHAR/LONGVARBINARY
" NULL
" BLOB/CLOB
" ARRAY
" REF
" STRUCT
" JAVA_OBJECT
! Certain ResultSet methods are not supported if row caching is enabled and
active for that result set. Most pertain to streaming data, scrollable result sets or
data types not supported for row caching. These include the following:
" getAsciiStream()
" getUnicodeStream()
" getBinaryStream()
" getCharacterStream()
" isBeforeLast()
" isAfterLast()
" isFirst()
" isLast()
" getRow()
" getObject (Map)
" getRef()
" getBlob()/getClob()
" getArray()
" getDate()
" getTime()
" getTimestamp()
Once a transaction begins, all database operations in an execute thread that get their
connection from the same connection pool share the same connection from that pool.
These operations can be made through services such as Enterprise JavaBeans (EJB),
or Java Messaging Service (JMS), or by directly sending SQL statements using
standard JDBC calls. All of these operations will, by default, share the same
connection and participate in the same transaction.When the transaction is committed
or rolled back, the connection is returned to the pool.
Although Java clients may not register the JTS driver themselves, they may participate
in transactions via Remote Method Invocation (RMI). You can begin a transaction in
a thread on a client and then have the client call a remote RMI object. The database
operations executed by the remote object become part of the transaction that was begun
on the client. When the remote object is returned back to the calling client, you can then
commit or roll back the transaction. The database operations executed by the remote
objects must all use the same connection pool to be part of the same transaction.
This explanation demonstrates creating and using a JTS transaction from a server-side
application and uses a connection pool named “myConnectionPool.”
2. Establish the transaction by using the UserTransaction class. You can look up
this class on the JNDI tree. The UserTransaction class controls the transaction
on the current execute thread. Note that this class does not represent the
transaction itself. The actual context for the transaction is associated with the
current execute thread.
Context ctx = null;
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
UserTransaction tx = (UserTransaction)
ctx.lookup("javax.transaction.UserTransaction");
6. Execute your database operations. These operations may be made by any service
that uses a database connection, including EJB, JMS, and standard JDBC
statements. These operations must use the JTS driver to access the same
connection pool as the transaction begun in step 3 in order to participate in that
transaction.
If the additional database operations using the JTS driver use a different
connection pool than the one specified in step 5, an exception will be thrown
when you try to commit or roll back the transaction.
7. Close your connection objects. Note that closing the connections does not
commit the transaction nor return the connection to the pool:
conn.close();
// or:
tx.rollback();
5 Using Third-Party
Drivers with WebLogic
Server
The following sections describe how to set up and use third-party JDBC drivers:
! “Setting the Environment for Your Third-Party JDBC Driver” on page 5-3
! “Getting a Connection with Your Third-Party Driver” on page 5-11
! “Using Oracle Extensions with the Oracle Thin Driver” on page 5-13
! Are thread-safe
This section describes how to set up and use the following third-party JDBC drivers
with WebLogic Server:
! Sybase jConnect Driver 4.5 and 5.5 (included in WebLogic Server installation)
In WebLogic Server version 6.1, a version of the Oracle Thin Driver and the Sybase
jConnect Driver were bundled within weblogic.jar. In version 7.x, third-party
JDBC drivers are no longer bundled within weblogic.jar. Instead, the 8.1.7 version
of the Oracle Thin driver (classes12.zip) and the 4.5 (jConnect.jar) and 5.5
(jconn2.jar) versions of the Sybase jConnect driver are installed in the
WL_HOME\server\lib folder (where WL_HOME is the folder where WebLogic
Platform is installed) with weblogic.jar. The manifest in weblogic.jar lists these
files so that they are loaded when weblogic.jar is loaded (when the server starts).
Figure 5-1 Directory Structure for JDBC Drivers Installed with WebLogic
Server
The oracle folder includes versions of the Oracle Thin driver, including the 8.1.7
version, which is also included in the WL_HOME\server\lib folder, as previously
mentioned. You can copy one of these files to the WL_HOME\server\lib folder to
change the version of the Oracle Thin driver or revert to the default version. See
“Changing or Updating the Oracle Thin Driver” on page 5-4 for more details.
The sybase folder contains the 4.5 version of the Sybase jConnect driver and a
subfolder with the 5.5 version of the Sybase jConnect driver and other supporting files.
These drivers—jConnect.jar and jconn2.jar, without the directory structure and
additional supporting files—are also included in the WL_HOME\server\lib folder, as
previously mentioned. WebLogic Server uses the files in the WL_HOME\server\lib
folder during runtime. You can use the additional copies in the
WL_HOME\server\ext\jdbc\sybase folder as a backup in the event that you update
the drivers with a defective or unsupported version of the driver.
If you plan to use the default version of these drivers, you do not need to make any
changes. If you plan to use a different version of these drivers, you must replace the
files in WL_HOME\server\lib with a file from
WL_HOME\server\ext\jdbc\oracle\version, where version is the version of
the JDBC driver you want to use, or with a file from the DBMS vendor—Oracle or
Sybase.
Because the manifest in weblogic.jar lists the class files for the Oracle Thin driver
and Sybase jConnect driver in WL_HOME\server\lib, the drivers are loaded when
weblogic.jar is loaded (when the server starts). Therefore, you do not need to add
the JDBC driver to your CLASSPATH. If you plan to use a third-party JDBC driver that
is not installed with WebLogic Server, you must add the path to the driver files to your
CLASSPATH.
Where DRIVER_CLASSES is the path to the JDBC driver classes and WL_HOME is the
directory where you installed WebLogic Platform.
Where DRIVER_CLASSES is the path to the JDBC driver classes and WL_HOME is the
directory where you installed WebLogic Platform.
Follow these instructions to use Oracle Thin Driver version 9.0.1 or 9.2.0:
1. In Windows Explorer or a command shell, go to the folder for the version of the
driver you want to use:
" WL_HOME\server\ext\jdbc\oracle\901 or
" WL_HOME\server\ext\jdbc\oracle\920
2. Copy classes12.zip.
To revert to version 8.1.7 (the default), follow the instructions above, but copy from
the following folder: WL_HOME\server\ext\jdbc\oracle\817.
To update a version of the Oracle Thin driver with a new version from Oracle, replace
classes12.zip in WL_HOME\server\lib with the new file from Oracle. You can
download driver updates from the Oracle Web site at
http://otn.oracle.com/software/content.html.
Note: You cannot include the 9.0.1 and 8.1.7 versions of the Oracle Thin driver in
your CLASSPATH. Including both in the CLASSPATH will cause clashes for
various methods.
To revert to versions installed with WebLogic Server, copy the following files and
place them in the WL_HOME\server\lib folder:
! WL_HOME\server\ext\jdbc\sybase\jConnect.jar
! WL_HOME\server\ext\jdbc\sybase\jConnect-5_5\classes\jconn2.jar
download the product. Download the driver from the JDBC/EMBEDDED SQLJ
section, and follow the instructions in the install.txt file included in the
downloaded zip file to install the driver.
After you download and install the driver, follow these steps to prepare to use the
driver with WebLogic Server:
Connection Pool Attributes when using the IBM Informix JDBC Driver
Use the attributes as described in Table 5-1 and Table 5-2 when creating a connection
pool that uses the IBM Informix JDBC driver.
Table 5-1 Non-XA Connection Pool Attributes Using the Informix JDBC Driver
Attribute Value
URL jdbc:informix-sqli:dbserver_name_or_ip:port/
dbname:informixserver=ifx_server_name
Table 5-1 Non-XA Connection Pool Attributes Using the Informix JDBC Driver
Attribute Value
Properties user=username
url=jdbc:informix-sqli:dbserver_name_or_ip:po
rt/dbname:informixserver=ifx_server_name
portNumber=1543
databaseName=dbname
ifxIFXHOST=ifx_server_name
serverName=dbserver_name_or_ip
Password password
Target serverName
Table 5-2 XA Connection Pool Attributes Using the Informix JDBC Driver
Attribute Value
Table 5-2 XA Connection Pool Attributes Using the Informix JDBC Driver
Attribute Value
Properties user=username
url=jdbc:informix-sqli://dbserver_name_or_ip:
port_num/dbname:informixserver=dbserver_name_
or_ip
password=password
portNumber =port_num;
databaseName=dbname
serverName=dbserver_name
ifxIFXHOST=dbserver_name_or_ip
Password leave blank
Target serverName
Note: If you create the connection pool using the Administration Console, you may
need to stop and restart the server before the connection pool will deploy
properly on the target server. This is a known issue.
! Batch updates fail if you attempt to insert rows with TEXT or BYTE columns
unless the IFX_USEPUT environment variable is set to 1.
! If the Java program sets autocommit mode to true during a transaction, IBM
Informix JDBC Driver commits the current transaction if the JDK is version 1.4
and later, otherwise the driver rolls back the current transaction before enabling
autocommit.
Installing and Using the SQL Server 2000 Driver for JDBC
from Microsoft
The Microsoft SQL Server 2000 Driver for JDBC is available for download to all
licensed SQL Server 2000 customers at no charge. The driver is a Type 4 JDBC driver
that supports a subset of the JDBC 2.0 Optional Package. When you install the
Microsoft SQL Server 2000 Driver for JDBC, the supporting documentation is
optionally installed with it. You should refer to that documentation for the most
comprehensive information about the driver. Also, see the release manifest at
http://msdn.microsoft.com/MSDN-FILES/027/001/779/JDBCRTMReleaseMa
nifest.htm for known issues.
1. Download the Microsoft SQL Server 2000 Driver for JDBC (setup.exe file) from
the Microsoft MSDN Web site at
http://msdn.microsoft.com/downloads/default.asp?URL=/downloads/
sample.asp?url=/MSDN-FILES/027/001/779/msdncompositedoc.xml.
Save the file in a temporary directory on your local computer.
2. Run setup.exe from the temporary directory and follow the instructions on the
screen.
" install_dir/lib/msbase.jar
" install_dir/lib/msutil.jar
" install_dir/lib/mssqlserver.jar
Where install_dir is the folder in which you installed the driver. For
example:
set CLASSPATH=install_dir\lib\msbase.jar;
install_dir\lib\msutil.jar;install_dir\lib\mssqlserver.jar;
%CLASSPATH%
1. Download the Microsoft SQL Server 2000 Driver for JDBC (mssqlserver.tar
file) from the Microsoft MSDN Web site at
http://msdn.microsoft.com/downloads/default.asp?URL=/downloads/
sample.asp?url=/MSDN-FILES/027/001/779/msdncompositedoc.xml.
Save the file in a temporary directory on your local computer.
2. Change to the temporary directory and untar the contents of the file using the
following command:
tar -xvf mssqlserver.tar
Where install_dir is the folder in which you installed the driver. For
example:
export CLASSPATH=install_dir/lib/msbase.jar:
install_dir/lib/msutil.jar:install_dir/lib/mssqlserver.jar:
$CLASSPATH
Connection Pool Attributes when using the Microsoft SQL Server Driver for
JDBC
Use the following attributes when creating a connection pool that uses the Microsoft
SQL Server Driver for JDBC:
! Properties:
user=<myuserid>
databaseName=<dbname>
! Password: mypassword
try {
ctx = new InitialContext(ht);
javax.sql.DataSource ds
= (javax.sql.DataSource) ctx.lookup ("myDataSource");
java.sql.Connection conn = ds.getConnection();
stmt.close();
conn.close();
}
catch (NamingException e) {
// a failure occurred
}
finally {
try {ctx.close();}
catch (Exception e) {
// a failure occurred
}
}
(Where hostname is the name of the machine running your WebLogic Server and
port is the port number where that machine is listening for connection requests.)
In this example a Hashtable object is used to pass the parameters required for the JNDI
lookup. There are other ways to perform a JNDI lookup. For more information, see
Programming WebLogic JNDI at http://e-docs.bea.com/wls/docs70/jndi/index.html.
Notice that the JNDI lookup is wrapped in a try/catch block in order to catch a failed
look up and also that the context is closed in a finally block.
! OracleRef
! OracleBlob
! OracleClob
The following sections provide code samples for Oracle extensions and tables of
supported methods. For more information, please refer to the Oracle documentation.
! You can use Oracle extensions for ARRAYs, REFs, and STRUCTs in server-side
applications that use the same JVM as the server only. You cannot use Oracle
extensions for ARRAYs, REFs, and STRUCTs in client applications.
! You cannot create ARRAYs, REFs, and STRUCTs in your applications. You can
only retrieve existing ARRAY, REF, and STRUCT objects from a database. To
create these objects in your applications, you must use a non-standard Oracle
descriptor object, which is not supported in WebLogic Server.
For examples showing how to access other Oracle extension methods, see the
following sections:
If you selected the option to install server examples with WebLogic Server, see the
JDBC examples, typically at WL_HOME\samples\server\src\examples\jdbc,
where WL_HOME is the folder where you installed WebLogic Platform.
int default_prefetch =
((OracleConnection)conn).getDefaultRowPrefetch();
while(rs.next()) {
java.math.BigDecimal empno = rs.getBigDecimal(1);
String ename = rs.getString(2);
System.out.println(empno + "\t" + ename);
}
rs.close();
stmt.close();
conn.close();
conn = null;
}
2. Get a connection (see “Establish the Connection” on page 5-15) and then create a
statement for the connection.
Note: You can use ARRAYs in server-side applications only. You cannot use
ARRAYs in client applications.
Getting an ARRAY
You can use the getArray() methods for a callable statement or a result set to get a
Java array. You can then use the array as a java.sql.array to use standard
java.sql.array methods, or you can cast the array as a
weblogic.jdbc.vendor.oracle.OracleArray to use the Oracle extension
methods for an array.
The following example shows how to get a java.sql.array from a result set that
contains an ARRAY. In the example, the query returns a result set that contains an
object column—an ARRAY of test scores for a student.
try {
conn = getConnection(url);
stmt = conn.createStatement();
String sql = "select * from students";
//Get the result set
rs = stmt.executeQuery(sql);
while(rs.next()) {
BigDecimal id = rs.getBigDecimal("student_id");
String name = rs.getString("name");
log("ArraysDAO.getStudents() -- Id = "+id.toString()+", Student
= "+name);
//Get the array from the result set
Array scoreArray = rs.getArray("test_scores");
String[] scores = (String[])scoreArray.getArray();
for (int i = 0; i < scores.length; i++) {
log(" Test"+(i+1)+" = "+scores[i]);
}
}
! STRUCTs are supported for use with Oracle only. To use STRUCTs in
your applications, you must use the Oracle Thin Driver to communicate
with the database, typically through a connection pool. The WebLogic
jDriver for Oracle does not support the STRUCT data type.
! You can use STRUCTs in server-side applications only. You cannot use
STRUCTs in client applications.
5. Use the standard or Oracle extension methods to work with the data.
The following sections provide more details for steps 3 through 5.
Getting a STRUCT
To get a database object as a STRUCT, you can use a query to create a result set and
then use the getObject method to get the STRUCT from the result set. You then cast
the STRUCT as a java.sql.Struct so you can use the standard Java methods. For
example:
conn = ds.getConnection();
stmt = conn.createStatement();
struct = (java.sql.Struct)(rs.getObject(2));
WebLogic Server supports all of the JDBC API methods for STRUCTs:
! getAttributes()
! getAttributes(java.util.Dictionary map)
! getSQLTypeName()
Oracle supports the standard methods as well as the Oracle extensions. Therefore,
when you cast a STRUCT as a weblogic.jdbc.vendor.oracle.OracleStruct,
you can use both the standard and extension methods.
java.sql.Struct struct =
(weblogic.jdbc.vendor.oracle.OracleStruct)(rs.getObject(2));
! getAutoBuffering()
! setAutoBuffering(boolean)
To use the standard method, you can create a result set, get a STRUCT from the result
set, and then use the getAttributes() method. The method returns an array of
ordered attributes. You can assign the attributes from the STRUCT (object in the
database) to an object in the application, including Java language types. You can then
manipulate the attributes individually. For example:
conn = ds.getConnection();
stmt = conn.createStatement();
struct = (java.sql.Struct)(rs.getObject(2));
In the preceding example, the third column in the people table uses an object data
type. The example shows how to assign the results from the getObject method to a
Java object that contains an array of values, and then use individual values in the array
as necessary.
map.put("NUMBER", Class.forName("java.lang.Integer"));
map.put("VARCHAR", Class.forName("java.lang.String"));
You can also use the Oracle extension method getOracleAttributes() to get the
attributes for a STRUCT. You must first cast the STRUCT as a
weblogic.jdbc.vendor.oracle.OracleStruct. This method returns a datum
array of oracle.sql.Datum objects. For example:
oracle.sql.Datum[] attrs =
((weblogic.jdbc.vendor.oracle.OracleStruct)struct).getOracleAttributes();
The preceding example includes a nested STRUCT. That is, the second attribute in the
datum array returned is another STRUCT.
stmt = conn.createStatement();
ps.executeUpdate();
stmt = conn.createStatement();
stmt.execute(cmd);
stmt.execute(cmd);
stmt.execute(cmd);
Note: You cannot create STRUCTs in your applications. You can only retrieve
existing objects from a database and cast them as STRUCTs. To create
STRUCT objects in your applications, you must use a non-standard Oracle
STRUCT descriptor object, which is not supported in WebLogic Server.
the attributes in the STRUCT in their converted form (materialized from SQL to Java
language objects). When your application accesses the STRUCT again, the system
does not have to convert the data again.
You can also use the getAutoBuffering() method to determine the automatic
buffering mode.
! REFs are supported for use with Oracle only. To use REFs in your
applications, you must use the Oracle Thin Driver to communicate with
the database, typically through a connection pool. The WebLogic jDriver
for Oracle does not support the REF data type.
! You can use REFs in server-side applications only.
4. Cast the result as a STRUCT or as a Java object. You can then manipulate data
using STRUCT methods or methods for the Java object.
Getting a REF
To get a REF in an application, you can use a query to create a result set and then use
the getRef method to get the REF from the result set. You then cast the REF as a
java.sql.Ref so you can use the built-in Java method. For example:
conn = ds.getConnection();
stmt = conn.createStatement();
rs.next();
Note that the WHERE clause in the preceding example uses dot notation to specify the
attribute in the referenced object.
After you cast the REF as a java.sql.Ref, you can use the Java API method
getBaseTypeName, the only JDBC 2.0 standard method for REFs.
When you get a REF, you actually get a pointer to a value in an object table. To get or
manipulate REF values, you must use the Oracle extensions, which are only available
when you cast the sql.java.Ref as a
weblogic.jdbc.vendor.oracle.OracleRef.
! getDescriptor()
! getSTRUCT()
! getValue()
! getValue(dictionary)
! setValue(object)
Getting a Value
Oracle provides two versions of the getValue() method—one that takes no
parameters and one that requires a hash table for mapping return types. When you use
either version of the getValue() method to get the value of an attribute in a REF, the
method returns a either a STRUCT or a Java object.
The example below shows how to use the getValue() method without parameters. In
this example, the REF is cast as an oracle.sql.STRUCT. You can then use the STRUCT
methods to manipulate the value, as illustrated with the getAttributes() method.
oracle.sql.STRUCT student1 =
(oracle.sql.STRUCT)((weblogic.jdbc.vendor.oracle.OracleRef)ref).getValue ();
You can also use the getValue(dictionary) method to get the value for a REF. You
must provide a hash table to map data types in each attribute of the REF to Java
language data types. For example:
java.util.Hashtable map = new java.util.Hashtable();
map.put("VARCHAR", Class.forName("java.lang.String"));
map.put("NUMBER", Class.forName("java.lang.Integer"));
! Change the location to which the REF points with a prepared statement or a
callable statement.
To use the setValue(object) method to update a REF value, you create an object
with the new values for the REF, and then pass the object as a parameter of the
setValue method. For example:
s1.setName("Terry Green");
s1.setAge(20);
((weblogic.jdbc.vendor.oracle.OracleRef)ref).setValue(s1);
When you update the value for a REF with the setValue(object) method, you
actually update the value in the table to which the REF points.
To update the location to which a REF points using a prepared statement, you can
follow these basic steps:
1. Get a REF that points to the new location. You use this REF to replace the value of
another REF.
2. Create a string for the SQL command to replace the location of an existing REF
with the value of the new REF.
conn = ds.getConnection();
stmt = conn.createStatement();
rs.next();
pstmt = conn.prepareStatement(sqlUpdate);
pstmt.setRef(1, ref);
pstmt.executeUpdate();
To use a callable statement to update the location to which a REF points, you prepare
the stored procedure, set any IN parameters and register any OUT parameters, and then
execute the statement. The stored procedure updates the REF value, which is actually
a location. For example:
conn = ds.getConnection();
stmt = conn.createStatement();
rs = stmt.executeQuery("SELECT ref (s) FROM t1 s where s.ob1=5");
rs.next();
cstmt = conn.prepareCall(sql);
cstmt.setRef(1, ref1);
// Execute
cstmt.execute();
The preceding example creates an object type (ob), a table (t1) of that object type, a
table (t2) with a REF column that can point to instances of ob objects, and inserts a
REF into the REF column. The REF points to a row in t1 where the value in the first
column is 5.
Note: When working with BLOBs and CLOBs (referred to as “LOBs”), you must
take transaction boundaries into account; for example, direct all read/writes to
a particular LOB within a transaction. For additional information, refer to
Oracle documentation about “LOB Locators and Transaction Boundaries” at
the Oracle Web site at http://www.oracle.com.
myStatement = myConnect.createStatement();
rs = myStatement.executeQuery(selectBlob);
while (rs.next()) {
myRegularBlob = rs.getBlob("blobCol");
os = ((OracleThinBlob)myRegularBlob).getBinaryOutputStream();
.....
........
Once you cast to the Oracle.ThinBlob interface, you can access the BEA supported
methods.
String getDatabaseProductVersion()
throws java.sql.SQLException;
String getUserName()
throws java.sql.SQLException;
boolean getBigEndian()
throws java.sql.SQLException;
boolean getIncludeSynonyms()
throws java.sql.SQLException;
boolean getRemarksReporting()
throws java.sql.SQLException;
boolean getReportRemarks()
throws java.sql.SQLException;
boolean getRestrictGetTables()
throws java.sql.SQLException;
boolean getUsingXAFlag()
throws java.sql.SQLException;
boolean getXAErrorFlag()
throws java.sql.SQLException;
int getDefaultRowPrefetch()
throws java.sql.SQLException;
int getStmtCacheSize()
throws java.sql.SQLException;
java.util.Properties getDBAccessProperties()
throws java.sql.SQLException;
short getStructAttrCsId()
throws java.sql.SQLException;
short getVersionNumber()
throws java.sql.SQLException;
void close_statements()
throws java.sql.SQLException;
void setDefaultAutoRefetch(boolean b)
throws java.sql.SQLException;
void setDefaultExecuteBatch(int i)
throws java.sql.SQLException;
void setDefaultRowPrefetch(int i)
throws java.sql.SQLException;
void setFDO(byte[] b)
throws java.sql.SQLException;
void setIncludeSynonyms(boolean b)
throws java.sql.SQLException;
void setPhysicalStatus(boolean b)
throws java.sql.SQLException;
void setRemarksReporting(boolean b)
throws java.sql.SQLException;
void setRestrictGetTables(boolean b)
throws java.sql.SQLException;
void setStmtCacheSize(int i)
throws java.sql.SQLException;
void setUsingXAFlag(boolean b)
throws java.sql.SQLException;
void setXAErrorFlag(boolean b)
throws java.sql.SQLException;
void shutdown(int i)
throws java.sql.SQLException;
boolean getAutoRefetch()
throws java.sql.SQLException;
byte getSqlKind()
throws java.sql.SQLException;
int creationState()
throws java.sql.SQLException;
int getAutoRollback()
throws java.sql.SQLException;
(Deprecated)
int getRowPrefetch()
throws java.sql.SQLException;
int getWaitOption()
throws java.sql.SQLException;
(Deprecated)
int sendBatch()
throws java.sql.SQLException;
void clearDefines()
throws java.sql.SQLException;
void notify_close_rset()
throws java.sql.SQLException;
void setAutoRefetch(boolean b)
throws java.sql.SQLException;
void setAutoRollback(int i)
throws java.sql.SQLException;
(Deprecated)
void setRowPrefetch(int i)
throws java.sql.SQLException;
void setWaitOption(int i)
throws java.sql.SQLException;
(Deprecated)
void closeStatementOnClose()
throws java.sql.SQLException;
void setAutoRefetch(boolean b)
throws java.sql.SQLException;
java.sql.ResultSet getCursor(int n)
throws java.sql.SQLException;
java.sql.ResultSet getCURSOR(String s)
throws java.sql.SQLException;
void registerOutParameter
(int i, int j, int k, int l)
throws java.sql.SQLException;
java.sql.ResultSet getCursor(int i)
throws java.sql.SQLException;
java.io.InputStream getAsciiStream(int i)
throws java.sql.SQLException;
java.io.InputStream getBinaryStream(int i)
throws java.sql.SQLException;
java.io.InputStream getUnicodeStream(int i)
throws java.sql.SQLException;
void setExecuteBatch(int i)
throws java.sql.SQLException;
6 Using dbKona
(Deprecated)
The dbKona classes provide a set of high-level database connectivity objects that give
Java applications and applets access to databases. dbKona sits on top of the JDBC API
and works with the WebLogic JDBC drivers, or with any other JDBC-compliant
driver.
Overview of dbKona
The dbKona classes provide a higher level of abstraction than JDBC, which deals with
low-level details of managing data. The dbKona classes offer objects that allow the
programmer to view and modify database data in a high-level, vendor-independent
way. A Java application that uses dbKona objects does not need vendor-specific
knowledge about DBMS table structure or field types to retrieve, insert, modify,
delete, or otherwise use data from a database.
For more information on WebLogic and the WebLogic JDBC Server, see
Programming WebLogic JDBC at
http://e-docs.bea.com/wls/docs70/jdbc/index.html.
! If you are using the WebLogic jDriver for Oracle native JDBC driver, you
should install the appropriate WebLogic-supplied .dll, .sl, or .so for your
operating system, as described in Installing and Using WebLogic jDriver for
Oracle at
http://e-docs.bea.com/wls/docs70/oracle/install_jdbc.html.
! If you are using a non-WebLogic JDBC driver, you should refer to the
documentation for that JDBC driver.
JavaSoft’s JDBC is a set of interfaces that BEA has implemented to create its jDriver
JDBC drivers. BEA’s JDBC drivers are JDBC implementations of database-specific
drivers for Oracle and Microsoft SQL Server. Using database-specific drivers with
dbKona offers the programmer access to all of the functionality of each specific
database, as well as improved performance.
Although the underlying foundation of dbKona uses JDBC for database transactions,
dbKona provides the programmer with higher-level, more convenient access to the
database.
A DataSet contains Records, and each Record contains one or more Value objects.
A Record is comparable to a database row, and a Value can be compared to a database
cell. Value objects “know” their internal data type as stored in the DBMS, but the
programmer can treat Value objects in a consistent way without having to worry about
vendor-specific internal data types.
Methods from the DataSet class (and its subclasses TableDataSet and
QueryDataSet) provide a high-level, flexible way to navigate through and manipulate
the results of a query. Changes made to a TableDataSet can be saved to the DBMS;
dbKona maintains knowledge of which records have changed and makes a selective
save, which reduces network traffic and DBMS overhead.
dbKona also uses other objects, such as SelectStmt and KeyDef, to shield the
programmer from vendor-specific SQL. By using methods in these classes, the
programmer can have dbKona construct the appropriate SQL, which reduces syntax
errors and does not require a knowledge of vendor-specific SQL. On the other hand,
dbKona also allows the programmer to pass SQL to the DBMS if desired.
Class weblogic.db.jdbc.Value
! Data container objects hold data retrieved from or bound for a database, or they
contain other objects that hold data. Data container objects are always associated
with a set of data description objects and a set of session objects. TableDataSet
and Record objects are examples of data container objects.
! Data description objects contain the metadata about data objects, that is, a
description of how the data is structured and typed, and parameters for its
retrieval from the remote DBMS. Every data object or its container is associated
with a set of data description objects. Schema and SelectStmt objects are
examples data description objects.
These broad categories of objects depend upon each other in application building. In a
general way, every data object has a set of descriptive objects associated with it.
DataSet
The dbKona package uses the concept of a DataSet to cache records retrieved from a
DBMS server. It is roughly equivalent to a table in SQL. The DataSet class has two
subclasses, QueryDataSet and TableDataSet.
In the multitier model using the WebLogic Server, DataSets can be saved (cached) on
the WebLogic Server.
! A Dataset is populated with Records, which contain Values. Records that are
accessible by index position (0-origined).
The DataSet class (see weblogic.db.jdbc.DataSet) is the abstract parent class for
QueryDataSet and TableDataSet.
QueryDataSet
A QueryDataSet makes the results of an SQL query available as a collection of
Records that are accessible by index position (0-origined). Unlike the case with a
TableDataSet, changes and additions to a QueryDataSet cannot be saved into the
database.
TableDataSet
The functional difference between a TableDataSet and a QueryDataSet is that
changes made to a TableDataSet can be saved to a database. With a TableDataSet,
you can update values in Records, add new Records, and mark Records for deletion;
finally, you can save changes to a database, using the save() methods in either the
TableDataSet class to save an entire TableDataSet, or in the Record class to save
a single record. Additionally, the data retrieved into a TableDataSet is, by definition,
from a single database table; you cannot perform joins on database tables to retrieve
data for a TableDataSet.
If you intend to save updates or deletes to a database, you must construct the
TableDataSet with a KeyDef object that specifies a unique key for forming the
WHERE clauses in an UPDATE or DELETE statement. A KeyDef is not necessary if only
inserts take place, because an insert operation does not require a WHERE clause. The
KeyDef key must not contain columns that are filled or altered by the DBMS, because
dbKona must have a known value for the key column to construct a correct WHERE
clause.
You can also qualify a TableDataSet with an arbitrary string that is used to construct
the tail of the SQL statement. When you are using dbKona with an Oracle database,
for example, you can qualify the TableDataSet with the string “for UPDATE” to place
a lock on the records that are retrieved by the query.
A TableDataSet can be constructed with a KeyDef, a dbKona object used for setting
a unique key for saving updates and deletes to the DBMS. If you are working with an
Oracle database, you can set the TableDataSet KeyDef to “ROWID,” which is a unique
key inherent in each table. Then construct the TableDataSet with a set of attributes that
includes “ROWID.”
EventfulTableDataSet (Deprecated)
An EventfulTableDataSet, for use within WebLogic Server, is a TableDataSet
that sends and receives events when its data is updated locally or in the DBMS.
EventfulTableDataSet implements weblogic.event.actions.ActionDef,
which is the interface implemented by all Action classes in WebLogic Events. The
action() method of an EventfulTableDataSet updates the DBMS and notifies all
other EventfulTableDataSets for the same DBMS table of the change. (You can
read more about WebLogic Events in the White Paper and the Developer’s Guide for
WebLogic Events, also deprecated.)
When a user changes a record, the DBMS is updated with the new record. At the same
time, an EventMessage (embedded with the changed Record itself) is automatically
sent to the WebLogic Server. Each client using an EventfulTableDataSet of the
“stock” table receives an event notification that has embedded in it the changed
Record. The EventfulTableDataSet for each client accepts the changed record and
updates the GUI.
Record
Records are created as part of a DataSet. You can also construct records manually in
the context of a DataSet and its schema, or the schema of an SQL table known to an
active Database session.
! Records are constructed when a DataSet is created and its query is executed. A
record may also be added to an existing DataSet with the
DataSet.addRecord() method or with a Record constructor (after the
DataSet’s fetchRecords() method has been called to get its schema).
! Determining the SQL string used to save or update a Record to the database
! Getting and setting its values
Value
A Value object has an internal type, which is defined by the schema of its parent
DataSet. A Value object can be assigned a value with a data type other than its
internal type, if the assignment is legal. A Value object can also return the value of a
data type other than its internal data type, if the request is legal.
The Value object acts to shield the application from the details of manipulating
vendor-specific data types. The Value object “knows” its data type, but all Value
objects can be manipulated within a Java application with the same methods, no matter
the internal data type.
! The internal data type of a Value object may be among the following:
" Boolean
" Byte
" Byte[]
" Date
" Double-precision
" Floating-point
" Integer
" Long
" Numeric
" Short
" String
" Time
" Timestamp
" NULL
! Values are described by the schema associated with its parent DataSet.
The Value class (see weblogic.db.jdbc.Value) has methods for getting and setting
the data and data type of a Value object.
Schema
When you instantiate a DataSet, you implicitly create the schema that describes it,
and when you fetch its records, the DataSet schema is updated.
Column
Schema is created.
KeyDef
“WHERE attribute1 = value1 and attribute2 = value2,” and so on, to uniquely
identify and manipulate a particular database record. The attributes in a KeyDef should
correspond to unique key in the database table.
The KeyDef object with no attributes is constructed in the KeyDef class. Use the
addAttrib() method to build the attributes of the KeyDef, and then use the KeyDef
as an argument in the constructor for a TableDataSet. Once the KeyDef is associated
with a DataSet, you cannot add anymore attributes to it.
When you are working with an Oracle database, you can add the attribute “ROWID,”
which is an inherently unique key associated with each table, to be used for inserts and
deletes with a TableDataSet.
! Adding attributes
SelectStmt
You can construct a SelectStmt object in the SelectStmt class. Then add clauses to
the SelectStmt with methods in the SelectStmt class, and use the resulting
SelectStmt object as an argument when you create a QueryDataSet. A
TableDataSet also has a default SelectStmt associated with it that can be used to
further refine data retrieval after the TableDataSet has been created.
There is also full support for setting and adding Query-by-example clauses. Note that
with the from() method, you can specify a string that includes an alias, in the format
“<i>tableName alias</i>”. With the field() method, you can use a string after
the format “<i>tableAlias.attribute</i>” as an argument. You are not limited
to a single table name when constructing a SelectStmt object, although its usage may
dictate whether or not a join is useful. A SelectStmt object associated with a
QueryDataSet can join one or more tables, whereas a TableDataSet cannot, since it
is by definition limited to the data in a single table.
Exceptions
! DataSetException
! LicenseException
! java.sql.SQLException
Constants
The Enums class contains constants for the following:
! Trigger states
Entity Relationships
Inheritance Relationships
The following describes important descendancy relationships between dbKona
classes. One class is subclassed:
DataSet
DataSet is the abstract base class for QueryDataSet and TableDataSet.
Possession Relationships
Each dbKona object may have other objects associated with it that further define its
structure.
DataSet
A DataSet has records, each of which has values. A DataSet has a schema that
defines its structure, which is made up of one or more columns. A DataSet may have
a SelectStmt that sets parameters for data retrieval.
TableDataSet
A TableDataSet has a KeyDef for updates and deletes by key.
Schema
A schema has columns that define its structure.
Implementing dbKona
The following sections describe a set of working examples that illustrate several steps
to building a simple Java application that retrieves and displays data from a remote
DBMS.
Note that you do not import the package for your JDBC driver. The JDBC driver is
established during the connection phase. For version 2.0 and later, you do not import
weblogic.db.common, weblogic.db.server, or weblogic.db.t3client.
You can see how to create the Properties object, props, in step 2.
Driver myDriver = (Driver)
Class.forName("weblogic.jdbc.oci.Driver").newInstance();
conn =
myDriver.connect("jdbc:weblogic:oracle", props);
conn.setAutoCommit(false);
The Connection conn becomes an argument for other actions that involve the DBMS,
for instance creating DataSets to hold query results. For details about connecting to
a DBMS, see the developers guide for your driver.
You can use the results of a query executed with a Statement object to instantiate a
QueryDataSet. This QueryDataSet is constructed with a JDBC ResultSet:
Using the results from the execution of a JDBC Statement is only one way to create
a DataSet. It requires knowledge of SQL, and it doesn’t give you much control over
the results of your query: basically, you can iterate through the records with the JDBC
next() method. With dbKona, you do not have to know much about SQL to retrieve
records; you can use methods in dbKona to set up your query, and once you have
created a DataSet with your records, you have a much finer control over manipulating
the records.
For example, the simplest data retrieval in dbKona is into a TableDataSet. Creating
a TableDataSet requires just a Connection object and the name of the DBMS table
that you want to retrieve, as in this example that retrieves the Employee table (alias
“empdemo"):
TableDataSet tds = new TableDataSet(conn, "empdemo");
Use a TableDataSet if you want to be able to save changes to the DBMS, or if you
do not plan to do a join of one or more tables to retrieve data; otherwise, use a
QueryDataSet. In this example, we use the QueryDataSet constructor that takes two
arguments: a Connection object and a string that is the SQL:
QueryDataSet qds = new QueryDataSet(conn, "select * from
empdemo");
You do not actually begin receiving data until you call the fetchRecords() method
in the DataSet class. After you create a DataSet, you can continue to refine its data
parameters. For instance, we could refine the selection of records to be retrieved in the
TableDataSet with the where() method, which adds a WHERE clause to the SQL that
dbKona composes. The following retrieves just one record from the Employee table
by using the where() method to create a WHERE clause:
TableDataSet tds = new TableDataSet(conn, "empdemo");
tds.where("empno = 8000");
When dealing with very large query results, you may prefer to fetch a few records at a
time, process them, and then clear the DataSet before the next fetch. Use the
clearRecords() method from the DataSet class to clear the TableDataSet
between fetches, as illustrated here:
TableDataSet tds = new TableDataSet(conn, "empdemo", "empno,
dept");
tds.where("empno > 2000");
while (!tds.allRecordsRetrieved()) {
tds.fetchRecords(100);
// Process the hundred records . . .
tds.clearRecords();
}
You can also reuse a DataSet with a method that was added in release 2.5.3. This
method, DataSet.releaseRecords(), closes the DataSet and releases all the
Records but does not nullify them. You can reuse the DataSet to generate new
records, yet any records from the first use still held by the application remain readable.
If you use a Statement object to create a query, you should close the Statement after
you have completed the query and fetched its results:
stmt.close();
sal = tmp;
name = rec.getValue("Emp Name").asString();
id = rec.getValue("Emp ID").asString();
salstr = rec.getValue("Emp Salary").asString();
}
hp.output();
It is also important to close the Connection to the DBMS. This code should appear at
the end of all of your database operations in a finally block, as in this example:
try {
// Do your work
}
catch (Exception mye) {
// Catch and handle exceptions
}
finally {
try {conn.close();}
catch (Exception e) {
// Deal with any exceptions
}
}
Code summary
import java.sql.*;
import weblogic.db.jdbc.*;
import weblogic.html.*;
import java.util.Properties;
.addElement("Name: ")
.addElement(new BoldElement(name))
.addElement(MarkupElement.Break)
.addElement("ID: ")
.addElement(new BoldElement(id))
.addElement(MarkupElement.Break)
.addElement("Salary: ")
.addElement(new BoldElement(salstr))
.addElement(MarkupElement.HorizontalLine);
hp.output();
// Close QueryDataSet
qds.close();
}
catch (Exception e) {
// Deal with any exceptions
}
finally {
// Close the connection
try {conn.close();}
catch (Exception mye) {
// Deal with any exceptions
}
}
}
}
Note that we closed each Statement and DataSet after use, and that we closed the
Connection in a finally block.
Now set the parameters for the SelectStmt object. In the example, the first argument
for each field is the attribute name and the second is the alias. This query will retrieve
information about all employees who make less than $2000:
sql.field("empno", "Emp ID")
.field("ename", "Emp Name")
.field("sal", "Emp Salary")
.from("empdemo")
.where("sal < 2000")
.order("empno");
We can further define the parameters for data selection by using the setQbe() and
addQbe() methods in the SelectStmt class, as is shown here. These methods allow
you to use vendor-specific QBE syntax in constructing a select statement:
sql.setQbe("ename", "MURPHY")
.addUnquotedQbe("empno", "8000");
When you have finished, use the fetchRecords() method to populate the DataSet,
as we did in the second tutorial.
As with most dbKona operations, you should begin by creating the Properties and
Driver objects, and then instantiating a Connection.
The second statement changes Murphy’s name to Smith, and changes his job status
from Salesman to Manager:
String update = "update empdemo set ename = 'SMITH', " +
"job = 'MANAGER' " +
"where empno = 8000";
The methods associated with TableDataSet allow you to specify a SQL WHERE clause
and a SQL ORDER BY clause and to set and add to a QBE statement. We use the
TableDataSet in this example to requery the database table “emp” after each
statement is executed to see the results of the execute() method. With the “where”
clause, we narrow down the records in the table to just employee number 8000.
Repeat the execute() method for the update and delete statements and capture the
results into two more TableDataSets, ds2 and ds3.
.addElement(MarkupElement.HorizontalLine)
.addElement(new TableElement(tds))
.addElement(MarkupElement.HorizontalLine)
.addElement(new HeadingElement("Query results afer INSERT", 2))
.addElement(new HeadingElement("SQL: ", 3))
.addElement(new LiteralElement(insert))
.addElement(new HeadingElement("Result: ", 3))
.addElement(new LiteralElement(ds1))
.addElement(MarkupElement.HorizontalLine)
.addElement(new HeadingElement("Query results after UPDATE", 2))
.addElement(new HeadingElement("SQL: ", 3))
.addElement(new LiteralElement(update))
.addElement(new HeadingElement("Result: ", 3))
.addElement(new LiteralElement(ds2))
.addElement(MarkupElement.HorizontalLine)
.addElement(new HeadingElement("Query results after DELETE", 2))
.addElement(new HeadingElement("SQL: ", 3))
.addElement(new LiteralElement(delete))
.addElement(new HeadingElement("Result: ", 3))
.addElement(new LiteralElement(ds3))
.addElement(MarkupElement.HorizontalLine);
hp.output();
Code summary
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.sql.*;
import java.util.*;
import weblogic.db.jdbc.*;
import weblogic.html.*;
// Verify results
TableDataSet ds1 = new TableDataSet(conn, "empdemo");
ds1.where("empno = 8000");
ds1.fetchRecords();
// Verify results
TableDataSet ds2 = new TableDataSet(conn, "empdemo");
ds2.where("empno = 8000");
ds2.fetchRecords();
// Verify results
TableDataSet ds3 = new TableDataSet(conn, "empdemo");
ds3.where("empno = 8000");
ds3.fetchRecords();
hp.output();
tds.close();
ds1.close();
ds2.close();
ds3.close();
}
catch (Exception e) {
// Handle the exception
}
// Always close the connection in a finally block
finally {
conn.close();
}
}
}
The first step is to create a connection to the DBMS. In this example, we use the
Connection object conn created in the first tutorial. The database table we use in this
example is the Employee table ("empdemo"), with fields empno, ename, job, and
deptno. The query we execute retrieves the full contents of the table empdemo.
A KeyDef is created and built in the KeyDef class, as shown in this example:
KeyDef key = new KeyDef().addAttrib("empno");
If you are working with an Oracle database, you can construct the KeyDef with the
attribute “ROWID,” to do inserts and deletes on this Oracle key, as in this example:
KeyDef key = new KeyDef().addAttrib("ROWID");
The KeyDef becomes the reference for all changes that we will make to the data. Each
time we save the TableDataSet, we change data in the database (according to the
limits set on SQL UPDATE, INSERT, and DELETE operations) based on the value of the
KeyDef attribute, which in this example is the employee number ("empno").
If you are working with an Oracle database and have added the attribute ROWID to the
KeyDef, you can construct a TableDataSet for inserts and deletes like this:
The getSaveString() method in the Record class returns the SQL string (a SQL
UPDATE, DELETE, or INSERT statement) used to save a Record to the database. We
saved this string into an object that we can display later to examine exactly how the
insert operation was carried out.
Records marked for deletion are not removed from a TableDataSet until you save()
it, or until you execute the removeDeletedRecords() method in the TableDataSet
class.
Records that have been removed from the TableDataSet but not yet deleted from the
database (by the removeDeletedRecords() method) fall into a zombie state. You can
determine whether a record is a zombie by testing it with the isAZombie() method in
the Record class, as shown here:
if (!newrec.isAZombie()) {
. . .
}
toBeSavedWith...()
You can check how a Record will be saved with a particular SQL action with
the methods toBeSavedWithDelete(), toBeSavedWithInsert(), and
toBeSavedWithUpdate() methods. The semantics of these methods equate to
the answer to the question, “If this row is or becomes dirty, what action will be
taken when the TableDataSet is saved?”
If you want to know whether a row will participate in a save to the DBMS, use the
isClean() and the needsToBeSaved() methods.
When you make modifications to a Record or TableDataSet, use the save() method
from either class to save the changes to the database. In the previous steps, we saved
the TableDataSet after each transaction as shown below:
tds.save();
As a final step, we can display the query results after each step and the strings
“insert”, “update”, and “delete” that we created after each save(). Refer to the
code summary in the previous tutorial to use htmlKona for displaying the results.
When you have finished with the DataSets, close each one with the close() method:
tds.close();
tds2.close();
Code Summary
Here is a code example that uses some of the concepts covered in this section:
package tutorial.dbkona;
import weblogic.db.jdbc.*;
import java.sql.*;
import java.util.Properties;
pstmt.close();
You should always close a Statement or PreparedStatement object when you have
finished working with it.
You can accomplish the same task with dbKona without worrying about the SQL. Use
a KeyDef to set fields for update or delete. Check the tutorial “Modifying DBMS Data
with a KeyDef” on page 6-31 for details.
The first step, as in any dbKona application, is to connect to the DBMS. The example
code uses the same Connection object, conn, that we created in the first tutorial topic.
In this example, we use the setInt() method to set the first parameter to the integer
“3”. Then we register the second parameter as an OUT parameter of type
java.sql.Types.INTEGER. Finally, we execute the stored procedure:
CallableStatement cstmt =
conn.prepareCall("BEGIN proc_squareInt(?, ?): END;");
cstmt.setInt(1, 3);
cstmt.registerOutParameter(2, java.sql.Types.INTEGER);
cstmt.execute();
Note that Oracle does not natively support binding to “?” values in a SQL statement.
Instead it uses “:1”, “:2”, etc. We allow you to use either in your SQL.
You will probably also find htmlKona useful, which will make it easy to integrate
database data retrieved with dbKona into an HTML environment. The example code
that we use in this tutorial depends on htmlKona.
After we retrieve the image record, we set the HTML page type to the image type and
then retrieve the image data as an array of bytes (byte[]) into an htmlKona
ImagePage, which will display the image in a browser:
if (iname != null) {
// Retrieve the image from the database
TableDataSet tds = new TableDataSet(conn, "imagetable");
tds.selectStmt().setQbe("name", iname);
tds.fetchRecords();
this.returnNormalResponse("image/" +
rec.getValue("type").asString());
rec = tds.addRecord();
rec.setValue("name", "excepts")
.setValue("type", "jpeg")
.setValue("data", "c:/html/api/images/exception-index.jpg");
tds.save();
tds.close();
You can drop an Oracle sequence from dbKona, also, as in this example:
Sequence.drop(conn, "mysequence");
Using a Sequence
Once you have created a Sequence object, you can use it to generate autoincrementing
ints, for example, to set an autoincrementing key as you add records to a table. Use
the nextValue() method to return an int that is the next increment in the Sequence.
For example:
TableDataSet tds = new TableDataSet(conn, "empdemo");
for (int i = 1; i <= 10; i++) {
Record rec = tds.addRecord();
rec.setValue("empno", seq.nextValue());
}
You can check the current value of a Sequence with the currentValue() method, but
only after you have called the nextValue() method at least once:
System.out.println("Records 1000-" + seq.currentValue() + "
added.");
Code Summary
Here is a working code example that illustrates how to use concepts discussed in this
section. First, we attempt to drop a sequence named “testseq” from the Oracle
server; this insures that we do not get an error when we try to create a sequence if one
already exists by that name. Then we create a sequence on the server, and use its name
to create a dbKona Sequence object:
package tutorial.dbkona;
import weblogic.db.jdbc.*;
import weblogic.db.jdbc.oracle.*;
import java.sql.*;
import java.util.Properties;
System.out.println(seq.currentValue());
7 Testing JDBC
Connections and
Troubleshooting
The following sections describe how to test, monitor, and troubleshoot JDBC
connections:
You can also access statistics for connection pools programmatically through the
JDBCConnectionPoolRuntimeMBean; see WebLogic Server Partner’s Guide at
http://e-docs.bea.com/wls/docs70/isv/index.html and the WebLogic
Javadoc. This MBean is the same API that populates the statistics in the
Administration Console. Read more about monitoring connectivity in Monitoring a
For information about using MBeans, see Programming WebLogic JMX Services at
http://e-docs.bea.com/wls/docs70/jmx/index.html.
! For Type 2 JDBC drivers, such as WebLogic jDriver for Oracle, set your PATH
(Windows) or shared/load library path (UNIX) to include both your
DBMS-supplied client installation and the BEA-supplied native libraries.
! For all drivers, include the classes of your JDBC driver in your CLASSPATH.
! Configuration instructions for the BEA WebLogic jDriver JDBC drivers are
available at:
" Using WebLogic jDriver for Oracle
" Using WebLogic jDriver for Microsoft SQL Server
Use the utils.dbping utility to confirm that you can make a connection between
Java and your database. The dbping utility is only for testing a two-tier connection,
using a WebLogic two-tier JDBC driver like WebLogic jDriver for Oracle.
Syntax
$ java utils.dbping DBMS user password DB
Arguments
DBMS
Use: ORACLE or MSSQLSERVER4
user
Valid username for database login. Use the same values and format that you use with
isql for SQL Server or sqlplus for Oracle.
password
Valid password for the user. Use the same values and format that you use with isql
or sqlplus.
DB
Name of the database. The format varies depending on the database and version. Use
the same values and format that you use with isql or sqlplus. Type 4 drivers, such
as MSSQLServer4, need additional information to locate the server since they cannot
access the environment.
Examples
Oracle
Connect to Oracle from Java with WebLogic jDriver for Oracle using the same values
that you use with sqlplus.
If you are not using SQLNet (and you have ORACLE_HOME and ORACLE_SID defined),
follow this example:
You could omit ":1433" in this example since 1433 is the default port number for
Microsoft SQL Server. By default, a Microsoft SQL Server may not be listening for
TCP/IP connections. Your DBA can configure it to do so.
If the two-tier JDBC driver is a WebLogic jDriver, you should test the two-tier
connection with utils.dbping. Otherwise, see the documentation for the two-tier
JDBC driver to find out how to test that connection before you test the multitier
connection.
Syntax
$ java utils.t3dbping URL user password DB driver_class driver_URL
Arguments
URL
URL of the WebLogic Server.
username
Valid username for the DBMS.
password
Valid password for that user.
DB
Name of the database. Use the same values and format that are shown above for testing
a two-tier connection.
driver_class
Class name of the JDBC driver between WebLogic and the DBMS. For instance, if you
are using WebLogic jDriver for Oracle on the server side, the driver class name is
weblogic.jdbc.oci.Driver. Note that the class name of the driver is in
dot-notation format.
driver_URL
URL of the JDBC driver between WebLogic and the DBMS. For instance, if you are
using WebLogic jDriver for Oracle on the server side, the URL of the driver is
jdbc:weblogic:oracle. Note that the URL of the driver is colon-separated.
Examples
These examples are displayed on multiple lines for readability. Each example should
be entered as a single command.
Oracle
Here is an example of how to ping the Oracle DBMS DEMO20 running on the server
bigbox, on the same host as WebLogic, which is listening on port 7001:
$ java utils.t3dbping // command
DEMO20 // DB
DEMO // database
sa // user name
abcd // password
hostname // database@hostname:port
//(optional if specified
// as part of the URL)
jdbc:weblogic:mssqlserver4:pubs@localhost:1433
// driver URL:database@hostname:port
//(optional if used in the database parameter)
Troubleshooting JDBC
The following sections provide troubleshooting tips.
JDBC Connections
If you are testing a connection to WebLogic, check the WebLogic Server log. By
default, the log is kept in a file with the following format:
domain\server\server.log
Where domain is the root folder of the domain and server is the name of the server.
The server name is used as a folder name and in the log file name.
Windows
If you get an error message that indicates that the .dll failed to load, make sure your
PATH includes the 32-bit database-related .dlls.
UNIX
If you get an error message that indicates that an .so or an .sl failed to load, make sure
your LD_LIBRARY_PATH or SHLIB_PATH includes the 32-bit database-related files.
Codeset Support
WebLogic supports Oracle codesets with the following consideration:
For more information, see Codeset Support in Using WebLogic jDriver for Oracle.
You can determine what type of threads you are using by checking the environment
variable called THREADS_TYPE. If this variable is not set, you can check the shell script
in your Java installation bin directory.
Some of the problems are related to the implementation of threads in the JVM for each
operating system. Not all JVMs handle operating-system specific threading issues
equally well. Here are some hints to avoid thread-related problems:
! If you are using HP UNIX, upgrade to version 11.x, because there are
compatibility issues with the JVM in earlier versions, such as HP UX 10.20.
! On HP UNIX, the new JDK does not append the green-threads library to the
SHLIB_PATH. The current JDK can not find the shared library (.sl) unless the
library is in the path defined by SHLIB_PATH. To check the current value of
SHLIB_PATH, at the command line type:
$ echo $SHLIB_PATH
Use the set or setenv command (depending on your shell) to append the
WebLogic shared library to the path defined by the symbol SHLIB_PATH. For the
shared library to be recognized in a location that is not part of your
SHLIB_PATH, you will need to contact your system administrator.
Driver d =
(Driver)Class.forName("weblogic.jdbc.oci.Driver").newInstance();
catch (Exception e) {
finally {
try {rs.close();}
catch (Exception rse) {}
try {stmt.close();}
catch (Exception sse) {}
try {conn.close();
catch (Exception cse) {}
Solaris
To find out which dynamic libraries are being used by an executable you can run the
ldd command for the application. If the output of this command indicates that libraries
are not found, then add the location of the libraries to the LD_LIBRARY_PATH
environment variable as follows (for C or Bash shells):
# setenv LD_LIBRARY_PATH weblogic_directory/lib/solaris/oci817_8
HP-UX
Incorrectly Set File Permissions
The shared library problem you are most likely to encounter after installing WebLogic
Server on an HP-UX system is incorrectly set file permissions. After installing
WebLogic Server, make sure that the shared library permissions are set correctly with
the chmod command. Here is an example to set the correct permissions for HP-UX
11.0:
% cd WL_HOME/lib/hpux11/oci817_8
If you encounter problems loading shared libraries after you set the file permissions,
there could be a problem locating the libraries. First, make sure that the
WL_HOME/server/lib/hpux11 is in the SHLIB_PATH environment variable:
% echo $SHLIB_PATH
Alternatively, copy (or link) the .sl files from the WebLogic Server distribution to a
directory that is already in the SHLIB_PATH variable.
If you still have problems, use the chatr command to specify that the application
should search directories in the SHLIB_PATH environment variable. The +s
enabled option sets an application to search the SHLIB_PATH variable. Here is an
example of this command, run on the WebLogic jDriver for Oracle shared library for
HP-UX 11.0:
# cd weblogic_directory/lib/hpux11
Check the chatr man page for more information on this command.
Incorrect SHLIB_PATH
You may also encounter a shared library problem if you do not include the proper paths
in your SHLIB_PATH when using Oracle 9. SHLIB_PATH should include the path to
the driver (oci901_8) and the path to the vendor-supplied libraries (lib32). For
example, your path may look like:
export SHLIB_PATH=
$WL_HOME/server/lib/hpux11/oci901_8:$ORACLE_HOME/lib32:$SHLIB_PAT
H
Note also that your path cannot include the path to the Oracle 8.1.7 libraries, or clashes
will occur. For more instructions, see Setting Up the Environment for Using WebLogic
jDriver for Oracle at
http://e-docs.bea.com/wls/docs70/oracle/install_jdbc.html.