Java and Design Patterns JDBC
Java and Design Patterns JDBC
(Figure 1)
From the above figure, we can see that application code talks to databases
From the above figure, we can see that application code talks to databases
via JDBC API.This API is the key to satisfy JDBC’s design goals. But, from
the API doc we can see that, this API is only a set of interfaces:
(Figure 2)
Interface is only an abstraction, it cannot do anything. So there must be
something that really do the job (talk to database)—it’s the JDBC Driver that
does this behind the scene.When you are talking to Oracle, the Oracle JDBC
Driver is used, when talking to DB2, the DB2 JDBC Driver used.Well, another
question emerges, how the API and the JDBC Driver collaborates, since our
application code is talking to the JDBC API? This is done by employing the
Factory Pattern.Let’s review a typical usage of JDBC, we will understand this
well.
Suppose we are talking to Oracle.First we obtain a JDBC connection via:
1. Class.forName(“oracle.jdbc.driver.OracleDriver”);
2. Connection
cnn=DriverManager.getConnection(“jdbc:oracle:thin:@localhost:1521
:viscent”,
3. “userName”, “password”);
2. Statement stmt=null;
3. ResultSet rs=null;
4. try {
5. stmt = cnn.createStatement();
6. rs=stmt.executeQuery(sql);
7. } catch (SQLException e) {
8. e.printStackTrace();
9. }
Note the way we get a Statement, it is an interface, and we don’t have get it
with new keyword,
instead, the c reateStatement of java.sql.Connection is called.The
createStatement is also a Factory method with the Statement as its
product.Similarly, if we want to issue prepared SQL or to call a stored
procedure, we will call prepareStatement a n d prepareCall, then we get
PreparedStatement and CallableStatement(again they are intefaces!)—again,
Factory method does the job!
Now, let’s review the way we deal with the recordset.
1. try {
2. while(rs.next()){
3. int id=rs.getInt(0);
4. String name=rs.getString(1);
5. //…
6. }
7. } catch (SQLException e) {
8. e.printStackTrace();
9. }
We loop through the resultset with the call to next, this is where the Iterator
pattern comes into play. Recall the intent of this pattern:
The ResultSet (interface) wraps a set of records (the ‘aggregate object’), but
we don’t need to care about what (concrete classes) really they are, as long
as calling to next allows us to go forward from one record to another. In this
way, we deal with recordset using the interface ResultSet without knowing
what concrete class it is.Hence the abstraction (ResultSet) and its
implementation (part of JDBC Driver that implements the ResultSet interface)
are decoupled.
From above steps, we can see that from the beginning to end the application
code talks only to the JDBC API. And this API makes heavy use of the
Factory Method Pattern.We don’t talk to JDBC drivers directly, and it looks
as if they don’t exist at all.This is really important to achieve the goal “Offer
vendor-neutral access to common features”.Because JDBC drivers are
vendor-specific, application code should not directly talk to them.However, as
mentioned previously, JDBC drivers do the real job to talk to database.The
question is how those drivers play their role?This is where the Bridge Pattern
comes into play.
Previously, we view the getConnection method of DriverManager as a
Factory method.
Factory method.
This is actually an outward view. Internally, DriverManager itself doesn’t
know how to create a database connection at all. Further more it should not
know how to create one at all for the sake of maintainability and extensibility
of the JDBC:
There are many database systems the JDBC should support at present, and
in the future, it may need support other database systems, if the knowledge
of creating a database connection is placed in DriverManager,it might need to
be changed frequently which is not desirable.That’s why there are JDBC
Drivers. The JDBC Driver is pluggable, when a JDBC Driver class is loaded,
it will register an instance of the Driver with the DriverManager.When we
asking DriverManager for a connection (by calling getConnection),
DriverManager will loop through all Drivers register with it, and call
acceptsURL on them,if the return is true, DriverManager will understand that
current driver are able to handle current connection url, then it will call
connect on the selected Driver to get a connection and return
it to our application code.
In this way, if we need JDBC to support a new database system, there is no
need to change JDBC itself at all, only need to create a new Driver for the
new database system! That’s why I call the Drivers are pluggable. We will
examine how JDBC achieve this pluggability.
(Figure 3)
From figure3 we can see that:
This is actually an example of the Bridge Pattern. Let’s review the intent of
this pattern:
This entry was posted on Saturday, August 15th, 2009 at 6:33 am and is filed under
Desgin/Architecture, Java. You can follow any responses to this entry through the RSS
2.0 feed. You can leave a response, or trackback from your own site.
Leave a Reply
Name (required)
Website
Submit Comment
Powered by WordPress
Entries (RSS) and Comments (RSS).