JDBC"

From Documentation
(Created page with '{{ZKDevelopersReferencePageHeader}} ZK is aimed to be as thin as the presentation tier. In addition, as the code executes at the server, so connecting database is no different f…')
 
Line 64: Line 64:
  
 
To know when a desktop becomes invalid, you have to implement a listener by use of <javadoc type="interface">org.zkoss.zk.ui.util.DesktopCleanup</javadoc>.
 
To know when a desktop becomes invalid, you have to implement a listener by use of <javadoc type="interface">org.zkoss.zk.ui.util.DesktopCleanup</javadoc>.
 +
 +
= Use with Connection Pooling (recommended)=
 +
Connection pooling is a technique of creating and managing a pool of connections that are ready for use by any thread that needs them. Instead of closing a connection immediately, it keeps them in a pool such that the next connect request could be served very efficiently. Connection pooling, in addition, has a lot of benefits, such as control resource usage.
 +
 +
There is no reason not to use connection pooling when developing Web-based applications, including ZK applications.
 +
 +
The concept of using connection pooling is simple: configure, connect and close. The way to connect and close a connection is very similar the ad-hoc approach, while configuration depends on what Web server and database server are in use.
 +
 +
== Connect and Close a Connection ==
 +
After configuring connection pooling (which will be discussed in the following section), you could use JNDI to retrieve an connection as follows.
 +
 +
<source lang="java" >
 +
import java.sql.Connection;
 +
import java.sql.SQLException;
 +
import java.sql.Statement;
 +
 +
import javax.naming.InitialContext;
 +
import javax.sql.DataSource;
 +
 +
import org.zkoss.zul.Window;
 +
 +
public class MyWindows extends Window {
 +
    private Textbox name, email;
 +
    public void onCreate() {
 +
        //initial name and email
 +
        name = getFellow("name");
 +
        email = getFellow("email");
 +
    }
 +
    public void onOK() throws Exception {
 +
            DataSource ds = (DataSource)new InitialContext()
 +
            .lookup("java:comp/env/jdbc/MyDB");
 +
            //Assumes your database is configured and
 +
            //named as "java:comp/env/jdbc/MyDB"
 +
 +
        Connection conn = null;
 +
        Statement stmt = null;
 +
        try {
 +
            conn = ds.getConnection();
 +
            stmt = conn.prepareStatement("INSERT INTO user values(?, ?)");
 +
 +
            //insert what end user entered into database table
 +
            stmt.setString(1, name.value);
 +
            stmt.setString(2, email.value);
 +
 +
            //execute the statement
 +
            stmt.executeUpdate();
 +
            stmt.close(); stmt = null;
 +
                //optional because the finally clause will close it
 +
                //However, it is a good habit to close it as soon as done, especially
 +
                //you might have to create a lot of statement to complete a job
 +
        } finally { //cleanup
 +
            if (stmt != null) {
 +
                try {
 +
                    stmt.close();
 +
                } catch (SQLException ex) {
 +
                    //(optional log and) ignore
 +
                }
 +
            }
 +
            if (conn != null) {
 +
                try {
 +
                    conn.close();
 +
                } catch (SQLException ex) {
 +
                    //(optional log and) ignore
 +
                }
 +
            }
 +
        }
 +
    }
 +
}
 +
</source>
 +
 +
'''Notes:'''
 +
 +
* It is important to close the statement and connection after use.
 +
* You could access multiple database at the same time by use of multiple connections. Depending on the configuration and J2EE/Web servers, these connections could even form a distributed transaction.
 +
 +
== Configure Connection Pooling ==
 +
The configuration of connection pooling varies from one J2EE/Web/Database server to another. Here we illustrated some of them. You have to consult the document of the server you are using.
 +
 +
=== Tomcat 5.5 + MySQL ===
 +
To configure connection pooling for Tomcat 5.5, you have to edit <tt>$TOMCAT_DIR/conf/context.xml</tt><ref>Thanks Thomas Muller ([http://asconet.org:8000/antville/oberinspector http://asconet.org:8000/antville/oberinspector]) for correction.
 +
 +
See also [http://tomcat.apache.org/tomcat-5.5-doc/jndi-resources-howto.html http://tomcat.apache.org/tomcat-5.5-doc/jndi-resources-howto.html] and [http://en.wikibooks.org/wiki/ZK/How-Tos/HowToHandleHibernateSessions#Working_with_the_Hibernate_session http://en.wikibooks.org/wiki/ZK/How-Tos/HowToHandleHibernateSessions#Working_with_the_Hibernate_session] for more details.</ref>, and add the following content under the <tt><Context></tt> element. The information that depends on your installation and usually need to be changed is marked in the blue color.
 +
 +
<source lang="xml" >
 +
<!-- The name you used above, must match _exactly_ here!
 +
    The connection pool will be bound into JNDI with the name
 +
    "java:/comp/env/jdbc/MyDB"
 +
-->
 +
<Resource name="jdbc/MyDB" username="someuser" password="somepass"
 +
    url="jdbc:mysql://localhost:3306/test"
 +
    auth="Container" defaultAutoCommit="false"
 +
    driverClassName="com.mysql.jdbc.Driver" maxActive="20"
 +
    timeBetweenEvictionRunsMillis="60000"
 +
    type="javax.sql.DataSource" />
 +
</ResourceParams>
 +
</source>
 +
 +
Then, in <tt>web.xml</tt>, you have to add the following content under the <tt><web-app></tt> element as follows.
 +
 +
<source lang="xml" >
 +
<resource-ref>
 +
  <res-ref-name>jdbc/MyDB</res-ref-name>
 +
  <res-type>javax.sql.DataSource</res-type>
 +
  <res-auth>Container</res-auth>
 +
</resource-ref>
 +
</source>
 +
 +
'''Notes'''
 +
<references/>
 +
 +
=== JBoss + MySQL ===
 +
The following instructions is based on section 23.3.4.3 of the reference manual of MySQL 5.0.
 +
 +
To configure connection pooling for JBoss, you have to add a new file to the directory called deploy (<tt>$JBOSS_DIR/server/default/deploy)</tt>. The file name must end with "<tt>-ds.xml</tt>", which tells JBoss to deploy this file as JDBC Datasource. The file must have the following contents. The information that depends on your installation and usually need to be changed is marked in the blue color.
 +
 +
<source lang="xml" >
 +
<datasources>
 +
    <local-tx-datasource>
 +
        <!-- This connection pool will be bound into JNDI with the name
 +
              "java:/MyDB" -->
 +
        <jndi-name>MyDB</jndi-name>
 +
        <connection-url>jdbc:mysql://localhost:3306/test</connection-url>
 +
        <driver-class>com.mysql.jdbc.Driver</driver-class>
 +
        <user-name>someuser</user-name>
 +
        <password>somepass</password>
 +
 +
        <min-pool-size>5</min-pool-size>
 +
 +
        <!-- Don't set this any higher than max_connections on your
 +
          MySQL server, usually this should be a 10 or a few 10's
 +
          of connections, not hundreds or thousands -->
 +
 +
        <max-pool-size>20</max-pool-size>
 +
 +
        <!-- Don't allow connections to hang out idle too long,
 +
          never longer than what wait_timeout is set to on the
 +
          server...A few minutes is usually okay here,
 +
          it depends on your application
 +
          and how much spikey load it will see -->
 +
 +
        <idle-timeout-minutes>5</idle-timeout-minutes>
 +
 +
        <!-- If you're using Connector/J 3.1.8 or newer, you can use
 +
              our implementation of these to increase the robustness
 +
              of the connection pool. -->
 +
 +
        <exception-sorter-class-name>com.mysql.jdbc.integration.jboss.ExtendedMysqlExceptionSorter</exception-sorter-class-name>
 +
        <valid-connection-checker-class-name>com.mysql.jdbc.integration.jboss.MysqlValidConnectionChecker</valid-connection-checker-class-name>
 +
 +
    </local-tx-datasource>
 +
</datasources>
 +
</source>
 +
 +
==== JBoss + PostgreSQL ====
 +
<source lang="xml" >
 +
<datasources>
 +
    <local-tx-datasource>
 +
    <!-- This connection pool will be bound into JNDI with the name
 +
          "java:/MyDB" -->
 +
    <jndi-name>MyDB</jndi-name>
 +
 +
    <!-- jdbc:postgresql://[servername]:[port]/[database name] -->
 +
    <connection-url>jdbc:postgresql://localhost/test</connection-url>
 +
 +
    <driver-class>org.postgresql.Driver</driver-class>
 +
    <user-name>someuser</user-name>
 +
    <password>somepass</password>
 +
    <min-pool-size>5</min-pool-size>
 +
    <max-pool-size>20</max-pool-size>
 +
    <track-statements>false</track-statements>
 +
    </local-tx-datasource>
 +
</datasources>
 +
</source>
  
 
=Version History=
 
=Version History=

Revision as of 07:18, 26 November 2010

ZK is aimed to be as thin as the presentation tier. In addition, as the code executes at the server, so connecting database is no different from any desktop applications. In other words, ZK doesn't change the way you access the database, no matter you use JDBC or other persistence framework, such as Hibernate.

Simplest Way to Use JDBC (but not recommended)

The simplest way to use JDBC, like any JDBC tutorial might suggest, is to use java.sql.DriverManager. Here is an example to store the name and email into a MySQL database.

<window title="JDBC demo" border="normal">
     <zscript><![CDATA[
     import java.sql.*;
     void submit() {
         //load driver and get a database connetion
         Class.forName("com.mysql.jdbc.Driver");
         Connection conn = DriverManager.getConnection(
             "jdbc:mysql://localhost/test?user=root&password=R3f@ct0r");
         PreparedStatement stmt = null;
         try {
             stmt = conn.prepareStatement("INSERT INTO user values(?, ?)");
 
             //insert what end user entered into database table
             stmt.setString(1, name.value);
             stmt.setString(2, email.value);
 
             //execute the statement
             stmt.executeUpdate();
         } finally { //cleanup
             if (stmt != null) {
                 try {
                     stmt.close();
                 } catch (SQLException ex) {
                     log.error(ex); //log and ignore
                 }
             }
             if (conn != null) {
                 try {
                     conn.close();
                 } catch (SQLException ex) {
                     log.error(ex); //log and ignore
                 }
             }
         }
     }
     ]]>
     </zscript>
     <vbox>
         <hbox>Name : <textbox id="name"/></hbox>
         <hbox>Email: <textbox id="email"/></hbox>
         <button label="submit" onClick="submit()"/>
     </vbox>
 </window>

Though simple, it is not recommended. After all, ZK applications are Web-based applications, where loading is unpredictable and treasurable resources such as database connections have to be managed effectively.

Luckily, all J2EE frameworks and Web servers support a utility called connection pooling. It is straightforward to use, while managing the database connections well. We will discuss more in the next section.


Tip: Unlike other Web applications, it is possible to use DriverManager with ZK, though not recommended.

First, you could cache the connection in the desktop, reuse it for each event, and close it when the desktop becomes invalid. It works just like traditional Client/Server applications. Like Client/Server applications, it works efficiently only if there are at most tens concurrent users.

To know when a desktop becomes invalid, you have to implement a listener by use of DesktopCleanup.

Use with Connection Pooling (recommended)

Connection pooling is a technique of creating and managing a pool of connections that are ready for use by any thread that needs them. Instead of closing a connection immediately, it keeps them in a pool such that the next connect request could be served very efficiently. Connection pooling, in addition, has a lot of benefits, such as control resource usage.

There is no reason not to use connection pooling when developing Web-based applications, including ZK applications.

The concept of using connection pooling is simple: configure, connect and close. The way to connect and close a connection is very similar the ad-hoc approach, while configuration depends on what Web server and database server are in use.

Connect and Close a Connection

After configuring connection pooling (which will be discussed in the following section), you could use JNDI to retrieve an connection as follows.

 import java.sql.Connection;
 import java.sql.SQLException;
 import java.sql.Statement;

 import javax.naming.InitialContext;
 import javax.sql.DataSource;

 import org.zkoss.zul.Window;

 public class MyWindows extends Window {
     private Textbox name, email;
     public void onCreate() {
         //initial name and email
         name = getFellow("name");
         email = getFellow("email");
     }
     public void onOK() throws Exception {
             DataSource ds = (DataSource)new InitialContext()
             .lookup("java:comp/env/jdbc/MyDB");
             //Assumes your database is configured and
             //named as "java:comp/env/jdbc/MyDB"

         Connection conn = null;
         Statement stmt = null;
         try {
             conn = ds.getConnection();
             stmt = conn.prepareStatement("INSERT INTO user values(?, ?)");

             //insert what end user entered into database table
             stmt.setString(1, name.value);
             stmt.setString(2, email.value);

             //execute the statement
             stmt.executeUpdate();
             stmt.close(); stmt = null;
                 //optional because the finally clause will close it
                 //However, it is a good habit to close it as soon as done, especially 
                 //you might have to create a lot of statement to complete a job
         } finally { //cleanup
             if (stmt != null) {
                 try {
                     stmt.close();
                 } catch (SQLException ex) {
                     //(optional log and) ignore
                 }
             }
             if (conn != null) {
                 try {
                     conn.close();
                 } catch (SQLException ex) {
                     //(optional log and) ignore
                 }
             }
         }
     }
 }

Notes:

  • It is important to close the statement and connection after use.
  • You could access multiple database at the same time by use of multiple connections. Depending on the configuration and J2EE/Web servers, these connections could even form a distributed transaction.

Configure Connection Pooling

The configuration of connection pooling varies from one J2EE/Web/Database server to another. Here we illustrated some of them. You have to consult the document of the server you are using.

Tomcat 5.5 + MySQL

To configure connection pooling for Tomcat 5.5, you have to edit $TOMCAT_DIR/conf/context.xml[1], and add the following content under the <Context> element. The information that depends on your installation and usually need to be changed is marked in the blue color.

 <!-- The name you used above, must match _exactly_ here!
     The connection pool will be bound into JNDI with the name
     "java:/comp/env/jdbc/MyDB"
 -->
 <Resource name="jdbc/MyDB" username="someuser" password="somepass" 
     url="jdbc:mysql://localhost:3306/test" 
     auth="Container" defaultAutoCommit="false" 
     driverClassName="com.mysql.jdbc.Driver" maxActive="20" 
     timeBetweenEvictionRunsMillis="60000" 
     type="javax.sql.DataSource" />
 </ResourceParams>

Then, in web.xml, you have to add the following content under the <web-app> element as follows.

 <resource-ref>
   <res-ref-name>jdbc/MyDB</res-ref-name>
   <res-type>javax.sql.DataSource</res-type>
   <res-auth>Container</res-auth>
 </resource-ref>

Notes

JBoss + MySQL

The following instructions is based on section 23.3.4.3 of the reference manual of MySQL 5.0.

To configure connection pooling for JBoss, you have to add a new file to the directory called deploy ($JBOSS_DIR/server/default/deploy). The file name must end with "-ds.xml", which tells JBoss to deploy this file as JDBC Datasource. The file must have the following contents. The information that depends on your installation and usually need to be changed is marked in the blue color.

 <datasources>
     <local-tx-datasource>
         <!-- This connection pool will be bound into JNDI with the name
              "java:/MyDB" -->
         <jndi-name>MyDB</jndi-name>
         <connection-url>jdbc:mysql://localhost:3306/test</connection-url>
         <driver-class>com.mysql.jdbc.Driver</driver-class>
         <user-name>someuser</user-name>
         <password>somepass</password>

         <min-pool-size>5</min-pool-size>

         <!-- Don't set this any higher than max_connections on your
          MySQL server, usually this should be a 10 or a few 10's
          of connections, not hundreds or thousands -->

         <max-pool-size>20</max-pool-size>

         <!-- Don't allow connections to hang out idle too long,
          never longer than what wait_timeout is set to on the
          server...A few minutes is usually okay here,
          it depends on your application
          and how much spikey load it will see -->

         <idle-timeout-minutes>5</idle-timeout-minutes>

         <!-- If you're using Connector/J 3.1.8 or newer, you can use
              our implementation of these to increase the robustness
              of the connection pool. -->

         <exception-sorter-class-name>com.mysql.jdbc.integration.jboss.ExtendedMysqlExceptionSorter</exception-sorter-class-name>
         <valid-connection-checker-class-name>com.mysql.jdbc.integration.jboss.MysqlValidConnectionChecker</valid-connection-checker-class-name>

     </local-tx-datasource>
 </datasources>

JBoss + PostgreSQL

 <datasources>
     <local-tx-datasource>
     <!-- This connection pool will be bound into JNDI with the name
          "java:/MyDB" -->
     <jndi-name>MyDB</jndi-name>

     <!-- jdbc:postgresql://[servername]:[port]/[database name] -->
     <connection-url>jdbc:postgresql://localhost/test</connection-url>

     <driver-class>org.postgresql.Driver</driver-class>
     <user-name>someuser</user-name>
     <password>somepass</password>
     <min-pool-size>5</min-pool-size>
     <max-pool-size>20</max-pool-size>
     <track-statements>false</track-statements>
     </local-tx-datasource>
 </datasources>

Version History

Last Update : 2010/11/26


Version Date Content
     



Last Update : 2010/11/26

Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.