<para>The <classname>DriverManagerDataSource</classname> class should
only be used for testing puposes since it does not provide pooling and
will perform poorly when multiple requests for a connection are
only be used for testing purposes since it does not provide pooling
and will perform poorly when multiple requests for a connection are
made.</para>
</note>
@ -1969,28 +1969,33 @@ END;]]></programlisting>In order to call this procedure we need to declare the
@@ -1969,28 +1969,33 @@ END;]]></programlisting>In order to call this procedure we need to declare the
<para><classname>MappingSqlQuery</classname> is a reusable query in
which concrete subclasses must implement the abstract
<methodname>mapRow(..)</methodname> method to convert each row of the
supplied <interfacename>ResultSet</interfacename> into an object. Find
below a brief example of a custom query that maps the data from the
customer relation to an instance of the <classname>Customer</classname>
class.</para>
supplied <interfacename>ResultSet</interfacename> into an object of the
type specified. Below is a brief example of a custom query that maps the
data from the t_actor relation to an instance of the
<classname>Actor</classname>class.</para>
<programlistinglanguage="java"><![CDATA[private class CustomerMappingQuery extends MappingSqlQuery {
<programlistinglanguage="java"><![CDATA[public class ActorMappingQuery extends MappingSqlQuery<Actor> {
public CustomerMappingQuery(DataSource ds) {
super(ds, "SELECT id, name FROM customer WHERE id = ?");
public ActorMappingQuery(DataSource ds) {
super(ds, "select id, first_name, last_name from t_actor where id = ?");
public Object mapRow(ResultSet rs, int rowNumber) throws SQLException {
Customer cust = new Customer();
cust.setId((Integer) rs.getObject("id"));
cust.setName(rs.getString("name"));
return cust;
}
@Override
protected Actor mapRow(ResultSet rs, int rowNumber) throws SQLException {
Actor actor = new Actor();
actor.setId(rs.getLong("id"));
actor.setFirstName(rs.getString("first_name"));
actor.setLastName(rs.getString("last_name"));
return actor;
}
}]]></programlisting>
<para>We provide a constructor for this customer query that takes the
<para>The class extends <classname>MappingSqlQuery</classname>
parameterized with the <classname>Actor</classname> type. We provide a
constructor for this customer query that takes the
<interfacename>DataSource</interfacename> as the only parameter. In this
constructor we call the constructor on the superclass with the
<interfacename>DataSource</interfacename> and the SQL that should be
@ -2003,31 +2008,33 @@ END;]]></programlisting>In order to call this procedure we need to declare the
@@ -2003,31 +2008,33 @@ END;]]></programlisting>In order to call this procedure we need to declare the
<classname>SqlParameter</classname> takes a name and the JDBC type as
defined in <classname>java.sql.Types</classname>. After all parameters
have been defined we call the <literal>compile()</literal> method so the
statement can be prepared and later be executed.</para>
@ -2040,10 +2047,11 @@ END;]]></programlisting>In order to call this procedure we need to declare the
@@ -2040,10 +2047,11 @@ END;]]></programlisting>In order to call this procedure we need to declare the
<methodname>update(..)</methodname> methods analogous to the
<methodname>execute(..)</methodname> methods of query objects. This
class is concrete. Although it can be subclassed (for example to add a
custom update method) it can easily be parameterized by setting SQL and
declaring parameters.</para>
custom update method - like in this example where we call it execute) it
can easily be parameterized by setting SQL and declaring
@ -2212,11 +2213,11 @@ public class TitlesAndGenresStoredProcedure extends StoredProcedure {
@@ -2212,11 +2213,11 @@ public class TitlesAndGenresStoredProcedure extends StoredProcedure {
compile();
}
public Map execute() {
<lineannotation>// again, this sproc has no input parameters, so an empty Map is supplied...</lineannotation>
return super.execute(new HashMap());
public Map<String,Object> execute() {
// again, this sproc has no input parameters, so an empty Map is supplied
<literal>declareParameter(..)</literal> method that have been used in
@ -2227,20 +2228,21 @@ public class TitlesAndGenresStoredProcedure extends StoredProcedure {
@@ -2227,20 +2228,21 @@ public class TitlesAndGenresStoredProcedure extends StoredProcedure {
<interfacename>RowMapper</interfacename> implementations is provided
below in the interest of completeness.)</para>
<para>Firstly the <classname>TitleMapper</classname> class, which simply
<para>First the <classname>TitleMapper</classname> class, which simply
maps a <interfacename>ResultSet</interfacename> to a
<classname>Title</classname> domain object for each row in the supplied
@ -2294,46 +2300,11 @@ public class TitlesAfterDateStoredProcedure extends StoredProcedure {
@@ -2294,46 +2300,11 @@ public class TitlesAfterDateStoredProcedure extends StoredProcedure {
compile();
}
public Map execute(Date cutoffDate) {
Map inputs = new HashMap();
public Map<String,Object> execute(Date cutoffDate) {
Map<String,Object> inputs = new HashMap<String,Object>();
inputs.put(CUTOFF_DATE_PARAM, cutoffDate);
return super.execute(inputs);
}
}]]></programlisting>
</section>
<sectionid="jdbc-SqlFunction">
<title><classname>SqlFunction</classname></title>
<para>The <classname>SqlFunction</classname> RDBMS operation class
encapsulates an SQL "function" wrapper for a query that returns a single
row of results. The default behavior is to return an
<literal>int</literal>, but that can be overridden by using the methods
with an extra return type parameter. This is similar to using the
<literal>queryForXxx</literal> methods of the
<classname>JdbcTemplate</classname>. The advantage with
<classname>SqlFunction</classname> is that you don't have to create the
<classname>JdbcTemplate</classname>, it is done behind the
scenes.</para>
<para>This class is intended to use to call SQL functions that return a
single result using a query like "select user()" or "select sysdate from
dual". It is not intended for calling more complex stored functions or
for using a <classname>CallableStatement</classname> to invoke a stored
procedure or stored function. (Use the
<classname>StoredProcedure</classname> or <classname>SqlCall</classname>
classes for this type of processing).</para>
<para><classname>SqlFunction</classname> is a concrete class, and there
is typically no need to subclass it. Code using this package can create
an object of this type, declaring SQL and parameters, and then invoke
the appropriate run method repeatedly to execute the function. Here is
an example of retrieving the count of rows from a table:</para>
<programlistinglanguage="java"><![CDATA[public int countRows() {
SqlFunction sf = new SqlFunction(dataSource, "select count(*) from mytable");
sf.compile();
return sf.run();
}]]></programlisting>
</section>
</section>
@ -2472,7 +2443,7 @@ final InputStream clobIs = new FileInputStream(clobIn);
@@ -2472,7 +2443,7 @@ final InputStream clobIs = new FileInputStream(clobIn);
final InputStreamReader clobReader = new InputStreamReader(clobIs);
jdbcTemplate.execute(
"INSERT INTO lob_table (id, a_clob, a_blob) VALUES (?, ?, ?)",
new AbstractLobCreatingPreparedStatementCallback(lobhandler) {
new AbstractLobCreatingPreparedStatementCallback(lobHandler) {