| <?xml version="1.0"?> |
| |
| <document url="./database.xml"> |
| |
| <properties> |
| <author>Craig R. McClanahan</author> |
| <author>Mike Schachter</author> |
| <author>Ted Husted</author> |
| <author>Martin Cooper</author> |
| <author>Ed Burns</author> |
| <author>Anthony Kay</author> |
| <title>Accessing a Database</title> |
| </properties> |
| |
| <body> |
| <section href="actionForm" name="How to Access a Database"/> |
| |
| <section name="Accessing a Database" href="database"> |
| |
| <p> |
| The best thing is use the Action as a thin adaptor between the |
| web/presentation-tier and your business classes (including those that |
| access a database). |
| </p> |
| |
| <p> |
| So you first design a business API that uses plain Java classes. |
| The best thing is to use objects that take ordinary Java types and return |
| a JavaBean or collection of JavaBeans. |
| The Action then calls these objects and passes the result back to the |
| web/presentation tier. |
| </p> |
| |
| <p> |
| A common approach is to create an Action class for each of the business |
| API methods/classes that you need to call. |
| Ideally, all the database access code should be encapsulated in the |
| business API classes, so Struts doesn't know what persistent layer you |
| are using (or even if there is a persistence layer). |
| It just passes a key or search String and gets back a bean or collection |
| of beans. |
| This lets you use the same business API classes in other environments, |
| and also to run unit tests against your business API outside of Struts or |
| a HTTP environment. |
| </p> |
| |
| <p> |
| To get started, it's simplest to setup a 1:1 correspondence between the |
| Actions and the entry-points to your business API. |
| As you gain experience, you will find ways to combine your Actions, say |
| by using the DispatchAction. |
| It's even possible to use a single "framework" Action to call all of your |
| business classes, as is done with Scaffold ProcessAction in the contrib |
| folder. |
| Using fewer Actions does require a deeper understanding of how Struts and |
| MVC frameworks operate. |
| Don't hesitate to err on the side of creating more Actions at first. |
| The Struts configuration makes it easy to refactor your Actions later, |
| since you can change the Action type without changing anything else in the |
| application. |
| </p> |
| |
| <p> |
| Ideally, the business logic layer should encapsulate the data access |
| details, including acquiring a database connection. |
| However, some application designs expect that the caller be able to provide a |
| database connection or DataSource instance. |
| When this is the case, the Struts DataSource manager can make it easy for |
| your Action to produce these resources on demand. |
| </p> |
| |
| <p> |
| The Struts DataSource manager is configured as an element in the |
| <a href="../userGuide/configuration.html#data-source_config"> |
| Struts configuration file</a> (struts-config.xml). |
| The manager can be used to deploy any connection pool that implements the |
| <code>javax.sql.DataSource</code> interface and is configurable totally |
| from JavaBean properties. |
| If your DBMS or container provides a connection pool that meets these |
| requirements, then that component might be your first choice. |
| </p> |
| |
| <p> |
| The Jakarta Commons dbcp's BasicDataSource |
| [<code>org.apache.commons.dbcp.BasicDataSource</code>] also works well |
| with the DataSource manager, if a native component is not available. |
| </p> |
| |
| <p> |
| <strong>Note:</strong> The Generic DataSource which was included with previous |
| versions of Struts has been removed as of release 1.2.0 in favor of |
| plugging in the BasicDataSource, or another DataSource implementation. |
| </p> |
| |
| <p> |
| This is how you would specify a DBCP BasicDataSource for your application: |
| </p> |
| |
| <pre><code><![CDATA[ |
| <data-sources> |
| <!-- configuration for commons BasicDataSource --> |
| <data-source type="org.apache.commons.dbcp.BasicDataSource"> |
| <set-property |
| property="driverClassName" |
| value="org.postgresql.Driver" /> |
| <set-property |
| property="url" |
| value="jdbc:postgresql://localhost/mydatabase" /> |
| <set-property |
| property="username" |
| value="me" /> |
| <set-property |
| property="password" |
| value="test" /> |
| <set-property |
| property="maxActive" |
| value="10" /> |
| <set-property |
| property="maxWait" |
| value="5000" /> |
| <set-property |
| property="defaultAutoCommit" |
| value="false" /> |
| <set-property |
| property="defaultReadOnly" |
| value="false" /> |
| <set-property |
| property="validationQuery" |
| value="SELECT COUNT(*) FROM market" /> |
| </data-source> |
| </data-sources> |
| ]]></code></pre> |
| |
| <p> |
| Note that you can define as many datasource objects as your application |
| requires and refer to each using a logical name. |
| This can be useful in providing better security or scalability, or even |
| to test datasource implementations against each other. |
| </p> |
| |
| <p> |
| After a DataSource is defined, here is an example of using the |
| manager to establish a connection from within an Action's |
| <code>execute</code> method. |
| </p> |
| |
| <pre><code> |
| public ActionForward |
| execute(ActionMapping mapping, |
| ActionForm form, |
| HttpServletRequest request, |
| HttpServletResponse response) throws Exception |
| { |
| javax.sql.DataSource dataSource; |
| java.sql.Connection myConnection; |
| try { |
| dataSource = getDataSource(request); |
| myConnection = dataSource.getConnection(); |
| // do what you wish with myConnection |
| } catch (SQLException sqle) { |
| getServlet().log("Connection.process", sqle); |
| } finally { |
| //enclose this in a finally block to make |
| //sure the connection is closed |
| try { |
| myConnection.close(); |
| } catch (SQLException e) { |
| getServlet().log("Connection.close", e); |
| } |
| } |
| } |
| </code></pre> |
| |
| <p> |
| <em>Note: If you use the Commons BasicDataSource with Struts, |
| the query you provide for the pingQuery attribute (if you choose to |
| include it) must return at least one row.</em> |
| </p> |
| |
| <p> |
| <strong>Example:</strong> <code>SELECT COUNT(*) FROM VALIDTABLE</code> |
| </p> |
| |
| <p> |
| Just be sure you to replace "VALIDTABLE" with the name of a valid table |
| in your database. |
| </p> |
| |
| </section> |
| |
| <section name="Using Multiple Datasources" href="multi_dsrc"> |
| <p> |
| If you need more than one data source in a module, you can include a key |
| attribute in the data-source element: |
| </p> |
| <pre><code><![CDATA[ |
| <data-sources> |
| <data-source key="A" type="org.apache.commons.dbcp.BasicDataSource"> |
| ... properties as before ... |
| </data-source> |
| <data-source key="B" type="org.apache.commons.dbcp.BasicDataSource"> |
| ... properties as before ... |
| </data-source> |
| ... |
| </data-sources> |
| ]]></code></pre> |
| |
| <p> |
| Which can then be accessed by including the key ("A" in this case) as an |
| additional parameter to the Action.getDataSource() method. |
| </p> |
| |
| <pre><code> |
| ... |
| try { |
| dataSourceA = getDataSource(request, "A"); |
| dataSourceB = getDataSource(request, "B"); |
| ... |
| </code></pre> |
| |
| <p> |
| Each module can have as many data sources as it needs. The keys only |
| need to be unique within a module since the struts module system maintains |
| a name space for the items in each module to protect you from name |
| clashes. |
| </p> |
| </section> |
| |
| <section href="more" name="See Also"> |
| |
| <p> |
| <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg24621.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg24621.html</a><br/> |
| <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg24709.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg24709.html</a><br/> |
| <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg24626.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg24626.html</a><br/> |
| <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg24331.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg24331.html</a><br/> |
| <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg24102.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg24102.html</a><br/> |
| <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg23501.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg23501.html</a><br/> |
| <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg23455.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg23455.html</a><br/> |
| <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg23375.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg23375.html</a><br/> |
| <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg23321.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg23321.html</a><br/> |
| <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg23098.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg23098.html</a><br/> |
| <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg22713.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg22713.html</a><br/> |
| <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg21974.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg21974.html</a><br/> |
| <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg21026.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg21026.html</a><br/> |
| <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg19338.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg19338.html</a><br/> |
| <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg18323.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg18323.html</a><br/> |
| <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg14975.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg14975.html</a><br/> |
| <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg14914.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg14914.html</a><br/> |
| <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg14435.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg14435.html</a><br/> |
| <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg01562.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg01562.html</a> |
| </p> |
| |
| <p> |
| Transformation/Data Transfer<br/> |
| <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg24480.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg24480.html</a><br/> |
| <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg23623.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg23623.html</a><br/> |
| <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg10195.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg10195.html</a><br/> |
| <a href="http://www.mail-archive.com/struts-user@jakarta.apache.org/msg10205.html">http://www.mail-archive.com/struts-user@jakarta.apache.org/msg10205.html</a> |
| </p> |
| |
| </section> |
| |
| |
| <section href="DynaResultSet" name="Rendering a dynamic result set"> |
| |
| <p> |
| The result of most queries will map to the ActionForms you are already using, |
| and so you can render the ResultSet as a collection of ActionForms. |
| But sometimes there are columns in a ResultSet that are not properties of an ActionForm, |
| or even known in advance. |
| </p> |
| |
| <p> |
| Happily, the Struts tags don't care what type of bean you use with them. |
| You could even output a ResultSet directly. |
| But a ResultSet retains a connection to the database, and passing "all that" directly to a JSP gets messy. |
| So what's a developer to do? |
| </p> |
| |
| <p> |
| Since Struts 1.1, the simplest option is to use a |
| <a href="http://jakarta.apache.org/commons/beanutils/api/org/apache/commons/beanutils/ResultSetDynaClass.html">ResultSetDynaClass</a> |
| to transfer the ResultSet into an ArrayList of DynaBeans. |
| The Struts custom tags can use DynaBean properties as easily as they use conventional JavaBean properties. |
| (See <strong>DynaActionForm classes</strong> in the Struts User Guide for details.) |
| </p> |
| |
| <p> |
| Since this is in the BeanUtils jar, you already have it on board, and just need to implement the transfer routine |
| (see the ResultSetDynaClass link). |
| </p> |
| |
| </section> |
| |
| </body> |
| </document> |
| |