Added batchUpdate method taking a Collection, a batch size and a ParameterizedPreparedStatementSetter as arguments (SPR-6334)
This commit is contained in:
parent
cfb387383b
commit
0adcb2ad2e
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package org.springframework.jdbc.core;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
|
@ -1004,7 +1005,19 @@ public interface JdbcOperations {
|
|||
* @return an array containing the numbers of rows affected by each update in the batch
|
||||
*/
|
||||
public int[] batchUpdate(String sql, List<Object[]> batchArgs, int[] argTypes);
|
||||
|
||||
|
||||
/**
|
||||
* Execute multiple batches using the supplied SQL statement with the collect of supplied arguments.
|
||||
* The arguments' values will be set using the ParameterizedPreparedStatementSetter.
|
||||
* Each batch should be of size indicated in 'batchSize'.
|
||||
* @param sql the SQL statement to execute.
|
||||
* @param batchArgs the List of Object arrays containing the batch of arguments for the query
|
||||
* @param argTypes SQL types of the arguments
|
||||
* (constants from <code>java.sql.Types</code>)
|
||||
* @return an array containing for each batch another array containing the numbers of rows affected
|
||||
* by each update in the batch
|
||||
*/
|
||||
public <T> int[][] batchUpdate(String sql, Collection<T> batchArgs, int batchSize, ParameterizedPreparedStatementSetter<T> pss);
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Methods dealing with callable statements
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import java.sql.SQLException;
|
|||
import java.sql.SQLWarning;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
|
|
@ -929,7 +930,59 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
|
|||
public int[] batchUpdate(String sql, List<Object[]> batchArgs, int[] argTypes) {
|
||||
return BatchUpdateUtils.executeBatchUpdate(sql, batchArgs, argTypes, this);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.jdbc.core.JdbcOperations#batchUpdate(java.lang.String, java.util.Collection, int, org.springframework.jdbc.core.ParameterizedPreparedStatementSetter)
|
||||
*
|
||||
* Contribution by Nicolas Fabre
|
||||
*/
|
||||
public <T> int[][] batchUpdate(String sql, final Collection<T> batchArgs, final int batchSize, final ParameterizedPreparedStatementSetter<T> pss) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Executing SQL batch update [" + sql + "] with a batch size of " + batchSize);
|
||||
}
|
||||
return execute(sql, new PreparedStatementCallback<int[][]>() {
|
||||
public int[][] doInPreparedStatement(PreparedStatement ps) throws SQLException {
|
||||
List<int[]> rowsAffected = new ArrayList<int[]>();
|
||||
try {
|
||||
boolean batchSupported = true;
|
||||
if (!JdbcUtils.supportsBatchUpdates(ps.getConnection())) {
|
||||
batchSupported = false;
|
||||
logger.warn("JDBC Driver does not support Batch updates; resorting to single statement execution");
|
||||
}
|
||||
int n = 0;
|
||||
for (T obj : batchArgs) {
|
||||
pss.setValues(ps, obj);
|
||||
n++;
|
||||
if (batchSupported) {
|
||||
ps.addBatch();
|
||||
if (n % batchSize == 0 || n == batchArgs.size()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
int batchIdx = (n % batchSize == 0) ? n / batchSize : (n / batchSize) + 1;
|
||||
int items = n - ((n % batchSize == 0) ? n / batchSize - 1 : (n / batchSize)) * batchSize;
|
||||
logger.debug("Sending SQL batch update #" + batchIdx + " with " + items + " items");
|
||||
}
|
||||
rowsAffected.add(ps.executeBatch());
|
||||
}
|
||||
}
|
||||
else {
|
||||
int i = ps.executeUpdate();
|
||||
rowsAffected.add(new int[] {i});
|
||||
}
|
||||
}
|
||||
int[][] result = new int[rowsAffected.size()][];
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = rowsAffected.get(i);
|
||||
}
|
||||
return result;
|
||||
} finally {
|
||||
if (pss instanceof ParameterDisposer) {
|
||||
((ParameterDisposer) pss).cleanupParameters();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Methods dealing with callable statements
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.jdbc.core;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Parameterized callback interface used by the {@link JdbcTemplate} class for batch updates.
|
||||
*
|
||||
* <p>This interface sets values on a {@link java.sql.PreparedStatement} provided
|
||||
* by the JdbcTemplate class, for each of a number of updates in a batch using the
|
||||
* same SQL. Implementations are responsible for setting any necessary parameters.
|
||||
* SQL with placeholders will already have been supplied.
|
||||
*
|
||||
* <p>Implementations <i>do not</i> need to concern themselves with SQLExceptions
|
||||
* that may be thrown from operations they attempt. The JdbcTemplate class will
|
||||
* catch and handle SQLExceptions appropriately.
|
||||
*
|
||||
* @author Nicolas Fabre
|
||||
* @author Thomas Risberg
|
||||
* @since 3.1
|
||||
* @see JdbcTemplate#batchUpdate(String sql, Collection<T> objs, int batchSize, ParameterizedPreparedStatementSetter<T> pss)
|
||||
*/
|
||||
public interface ParameterizedPreparedStatementSetter<T> {
|
||||
|
||||
/**
|
||||
* Set parameter values on the given PreparedStatement.
|
||||
*
|
||||
* @param ps the PreparedStatement to invoke setter methods on
|
||||
* @param argument the object containing the values to be set
|
||||
* @throws SQLException if a SQLException is encountered (i.e. there is no need to catch SQLException)
|
||||
*/
|
||||
void setValues(PreparedStatement ps, T argument) throws SQLException;
|
||||
|
||||
}
|
||||
|
|
@ -26,6 +26,7 @@ import java.sql.SQLWarning;
|
|||
import java.sql.Statement;
|
||||
import java.sql.Types;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -1189,6 +1190,76 @@ public class JdbcTemplateTests extends AbstractJdbcTests {
|
|||
BatchUpdateTestHelper.verifyBatchUpdateMocks(ctrlPreparedStatement, ctrlDatabaseMetaData);
|
||||
}
|
||||
|
||||
public void testBatchUpdateWithCollectionOfObjects() throws Exception {
|
||||
final String sql = "UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = ?";
|
||||
final List<Integer> ids = new ArrayList<Integer>();
|
||||
ids.add(Integer.valueOf(100));
|
||||
ids.add(Integer.valueOf(200));
|
||||
ids.add(Integer.valueOf(300));
|
||||
final int[] rowsAffected1 = new int[] { 1, 2 };
|
||||
final int[] rowsAffected2 = new int[] { 3 };
|
||||
|
||||
MockControl ctrlPreparedStatement = MockControl.createControl(PreparedStatement.class);
|
||||
PreparedStatement mockPreparedStatement = (PreparedStatement) ctrlPreparedStatement.getMock();
|
||||
mockPreparedStatement.getConnection();
|
||||
ctrlPreparedStatement.setReturnValue(mockConnection);
|
||||
mockPreparedStatement.setInt(1, ids.get(0));
|
||||
ctrlPreparedStatement.setVoidCallable();
|
||||
mockPreparedStatement.addBatch();
|
||||
ctrlPreparedStatement.setVoidCallable();
|
||||
mockPreparedStatement.setInt(1, ids.get(1));
|
||||
ctrlPreparedStatement.setVoidCallable();
|
||||
mockPreparedStatement.addBatch();
|
||||
ctrlPreparedStatement.setVoidCallable();
|
||||
mockPreparedStatement.setInt(1, ids.get(2));
|
||||
ctrlPreparedStatement.setVoidCallable();
|
||||
mockPreparedStatement.executeBatch();
|
||||
ctrlPreparedStatement.setReturnValue(rowsAffected1);
|
||||
mockPreparedStatement.addBatch();
|
||||
ctrlPreparedStatement.setVoidCallable();
|
||||
mockPreparedStatement.executeBatch();
|
||||
ctrlPreparedStatement.setReturnValue(rowsAffected2);
|
||||
if (debugEnabled) {
|
||||
mockPreparedStatement.getWarnings();
|
||||
ctrlPreparedStatement.setReturnValue(null);
|
||||
}
|
||||
mockPreparedStatement.close();
|
||||
ctrlPreparedStatement.setVoidCallable();
|
||||
|
||||
MockControl ctrlDatabaseMetaData = MockControl.createControl(DatabaseMetaData.class);
|
||||
DatabaseMetaData mockDatabaseMetaData = (DatabaseMetaData) ctrlDatabaseMetaData.getMock();
|
||||
mockDatabaseMetaData.getDatabaseProductName();
|
||||
ctrlDatabaseMetaData.setReturnValue("MySQL");
|
||||
mockDatabaseMetaData.supportsBatchUpdates();
|
||||
ctrlDatabaseMetaData.setReturnValue(true);
|
||||
|
||||
mockConnection.prepareStatement(sql);
|
||||
ctrlConnection.setReturnValue(mockPreparedStatement);
|
||||
mockConnection.getMetaData();
|
||||
ctrlConnection.setReturnValue(mockDatabaseMetaData, 2);
|
||||
|
||||
ctrlPreparedStatement.replay();
|
||||
ctrlDatabaseMetaData.replay();
|
||||
replay();
|
||||
|
||||
ParameterizedPreparedStatementSetter setter = new ParameterizedPreparedStatementSetter<Integer>() {
|
||||
public void setValues(PreparedStatement ps, Integer argument) throws SQLException {
|
||||
ps.setInt(1, argument.intValue());
|
||||
}
|
||||
};
|
||||
|
||||
JdbcTemplate template = new JdbcTemplate(mockDataSource, false);
|
||||
|
||||
int[][] actualRowsAffected = template.batchUpdate(sql, ids, 2, setter);
|
||||
assertTrue("executed 2 updates", actualRowsAffected[0].length == 2);
|
||||
assertEquals(rowsAffected1[0], actualRowsAffected[0][0]);
|
||||
assertEquals(rowsAffected1[1], actualRowsAffected[0][1]);
|
||||
assertEquals(rowsAffected2[0], actualRowsAffected[1][0]);
|
||||
|
||||
ctrlPreparedStatement.verify();
|
||||
ctrlDatabaseMetaData.verify();
|
||||
}
|
||||
|
||||
public void testCouldntGetConnectionOrExceptionTranslator() throws SQLException {
|
||||
SQLException sex = new SQLException("foo", "07xxx");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
|
||||
<chapter id="jdbc">
|
||||
|
|
@ -8,9 +8,9 @@
|
|||
<title>Introduction to Spring Framework JDBC</title>
|
||||
|
||||
<para>The value-add provided by the Spring Framework JDBC abstraction is
|
||||
perhaps best shown by the sequence of actions outlined in the table
|
||||
below. The table shows what actions Spring will take care of and which
|
||||
actions are the responsibility of you, the application developer.<!--Is this sequence correct, as far as what developer does and doesn't do? Does it adhere to info in the rest of the chapter?
|
||||
perhaps best shown by the sequence of actions outlined in the table below.
|
||||
The table shows what actions Spring will take care of and which actions
|
||||
are the responsibility of you, the application developer.<!--Is this sequence correct, as far as what developer does and doesn't do? Does it adhere to info in the rest of the chapter?
|
||||
--><!--How does JDBC know what connection parameters are if a human does not at some point define them?--><!--TR: OK. I have rewritten this as a table indicating who has what responsibility. --></para>
|
||||
|
||||
<table align="left" width="">
|
||||
|
|
@ -1036,7 +1036,8 @@ public class ExecuteAnUpdate {
|
|||
<section id="jdbc-auto-genereted-keys">
|
||||
<title>Retrieving auto-generated keys</title>
|
||||
|
||||
<para>An <methodname>update()</methodname> convenience method supports<!--Give name of this method. Also indicate *what* is acquiring the primary keys. TR: Changed to *retrieval*.
|
||||
<para>An <methodname>update()</methodname> convenience method
|
||||
supports<!--Give name of this method. Also indicate *what* is acquiring the primary keys. TR: Changed to *retrieval*.
|
||||
The name of the method is *update*.--> the retrieval of primary keys generated
|
||||
by the database. This support is part of the JDBC 3.0 standard; see
|
||||
Chapter 13.6 of the specification for details. The method takes a
|
||||
|
|
@ -1368,7 +1369,7 @@ dataSource.setPassword("");</programlisting>
|
|||
<classname>SimpleJdbcTemplate</classname>.</para>
|
||||
|
||||
<section id="jdbc-advanced-classic">
|
||||
<title>Batch operations with the JdbcTemplate</title>
|
||||
<title>Basic batch operations with the JdbcTemplate</title>
|
||||
|
||||
<para>You accomplish <classname>JdbcTemplate</classname> batch
|
||||
processing by implementing two methods of a special interface,
|
||||
|
|
@ -1418,11 +1419,12 @@ dataSource.setPassword("");</programlisting>
|
|||
</section>
|
||||
|
||||
<section id="jdbc-advanced-simple">
|
||||
<title>Batch operations with the SimpleJdbcTemplate</title>
|
||||
<title>Batch operations with a List of objects</title>
|
||||
|
||||
<para>The <classname>SimpleJdbcTemplate</classname> provides an
|
||||
alternate way of providing the batch update. Instead of implementing a
|
||||
special batch interface, you provide all parameter values in the call.
|
||||
<para>Both the <classname>JdbcTemplate</classname> and the
|
||||
<classname>NamedParameterJdbcTemplate</classname> provides an alternate
|
||||
way of providing the batch update. Instead of implementing a special
|
||||
batch interface, you provide all parameter values in the call as a list.
|
||||
The framework loops over these values and uses an internal prepared
|
||||
statement setter. The API varies depending on whether you use named
|
||||
parameters. For the named parameters you provide an array of
|
||||
|
|
@ -1435,15 +1437,15 @@ dataSource.setPassword("");</programlisting>
|
|||
<para>This example shows a batch update using named parameters:</para>
|
||||
|
||||
<para><programlisting language="java">public class JdbcActorDao implements ActorDao {
|
||||
private SimpleJdbcTemplate simpleJdbcTemplate;
|
||||
private NamedParameterTemplate namedParameterJdbcTemplate;
|
||||
|
||||
public void setDataSource(DataSource dataSource) {
|
||||
this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
|
||||
this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
public int[] batchUpdate(final List<Actor> actors) {
|
||||
SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch(actors.toArray());
|
||||
int[] updateCounts = simpleJdbcTemplate.batchUpdate(
|
||||
int[] updateCounts = namedParameterJdbcTemplate.batchUpdate(
|
||||
"update t_actor set first_name = :firstName, last_name = :lastName where id = :id",
|
||||
batch);
|
||||
return updateCounts;
|
||||
|
|
@ -1459,10 +1461,10 @@ dataSource.setPassword("");</programlisting>
|
|||
<para>The same example using classic JDBC "?" placeholders:</para>
|
||||
|
||||
<para><programlisting language="java">public class JdbcActorDao implements ActorDao {
|
||||
private SimpleJdbcTemplate simpleJdbcTemplate;
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
public void setDataSource(DataSource dataSource) {
|
||||
this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
public int[] batchUpdate(final List<Actor> actors) {
|
||||
|
|
@ -1474,17 +1476,79 @@ dataSource.setPassword("");</programlisting>
|
|||
actor.getId()};
|
||||
batch.add(values);
|
||||
}
|
||||
int[] updateCounts = simpleJdbcTemplate.batchUpdate(
|
||||
int[] updateCounts = jdbcTemplate.batchUpdate(
|
||||
"update t_actor set first_name = ?, last_name = ? where id = ?",
|
||||
batch);
|
||||
return updateCounts;
|
||||
}
|
||||
|
||||
// ... additional methods
|
||||
}</programlisting>All batch update methods return an int array containing the
|
||||
number of affected rows for each batch entry. This count is reported by
|
||||
the JDBC driver. If the count is not available, the JDBC driver returns
|
||||
a -2 value.</para>
|
||||
}</programlisting>All of the above batch update methods return an int array
|
||||
containing the number of affected rows for each batch entry. This count
|
||||
is reported by the JDBC driver. If the count is not available, the JDBC
|
||||
driver returns a -2 value.</para>
|
||||
</section>
|
||||
|
||||
<section id="jdbc-advanced-simple">
|
||||
<title>Batch operations with multiple batches</title>
|
||||
|
||||
<para>The last example of a batch update deals with batches that are so
|
||||
large that you want to break them up into several smaller batches. You
|
||||
can of course do this with the methods mentioned above by making
|
||||
multiple calls to the <classname>batchUpdate</classname> method, but
|
||||
there is now a more convenient method. This method takes, in addition to
|
||||
the SQL statement, a Collection of objects containing the parameters,
|
||||
the number of updates to make for each batch and a
|
||||
<classname>ParameterizedPreparedStatementSetter</classname> to set the
|
||||
values for the parameters of the prepared statement. The framework loops
|
||||
over the provided values and breaks the update calls into batches of the
|
||||
size specified. </para>
|
||||
|
||||
<para>This example shows a batch update using a batch size of
|
||||
100:</para>
|
||||
|
||||
<para><programlisting language="java">public class JdbcActorDao implements ActorDao {
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
public void setDataSource(DataSource dataSource) {
|
||||
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||
}
|
||||
|
||||
public int[][] batchUpdate(final Collection<Actor> actors) {
|
||||
Collection<Object[]> batch = new ArrayList<Object[]>();
|
||||
for (Actor actor : actors) {
|
||||
Object[] values = new Object[] {
|
||||
actor.getFirstName(),
|
||||
actor.getLastName(),
|
||||
actor.getId()};
|
||||
batch.add(values);
|
||||
}
|
||||
int[][] updateCounts = jdbcTemplate.batchUpdate(
|
||||
"update t_actor set first_name = ?, last_name = ? where id = ?",
|
||||
actors,
|
||||
100,
|
||||
new ParameterizedPreparedStatementSetter<Actor>() {
|
||||
public void setValues(PreparedStatement ps, Actor argument) throws SQLException {
|
||||
ps.setString(1, argument.getFirstName());
|
||||
ps.setString(2, argument.getLastName());
|
||||
ps.setLong(3, argument.getId().longValue());
|
||||
|
||||
}
|
||||
} );
|
||||
return updateCounts;
|
||||
}
|
||||
|
||||
// ... additional methods
|
||||
}</programlisting>The batch update methods for this call returns an array of
|
||||
int arrays containing an array entry for each batch with an array of the
|
||||
number of affected rows for each update. The top level array's length
|
||||
indicates the number of batches executed and the second level array's
|
||||
length indicates the number of updates in that batch. The number of
|
||||
updates in each batch should be the the batch size provided for all
|
||||
batches except for the last one that might be less, depending on the
|
||||
total number of updat objects provided. The update count for each update
|
||||
stament is the one reported by the JDBC driver. If the count is not
|
||||
available, the JDBC driver returns a -2 value.</para>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
|
@ -1715,9 +1779,9 @@ END;</programlisting>The <code>in_id</code> parameter contains the
|
|||
<para>The <classname>SimpleJdbcCall</classname> is declared in a similar
|
||||
manner to the <classname>SimpleJdbcInsert</classname>. You should
|
||||
instantiate and configure the class in the initialization method of your
|
||||
data access layer. Compared to the StoredProcedure class, you don't
|
||||
have to create a subclass and you don't have to declare parameters that
|
||||
can be looked up in the database metadata. <!--Reword preceding: You need not subclass *what?* and you declare *what* in init method? TR: Revised, pplease review.-->Following
|
||||
data access layer. Compared to the StoredProcedure class, you don't have
|
||||
to create a subclass and you don't have to declare parameters that can
|
||||
be looked up in the database metadata. <!--Reword preceding: You need not subclass *what?* and you declare *what* in init method? TR: Revised, pplease review.-->Following
|
||||
is an example of a SimpleJdbcCall configuration using the above stored
|
||||
procedure. The only configuration option, in addition to the
|
||||
<classname>DataSource</classname>, is the name of the stored
|
||||
|
|
@ -2651,9 +2715,9 @@ clobReader.close();</programlisting>
|
|||
<para>In addition to the primitive values in the value list, you can
|
||||
create a <classname>java.util.List</classname> of object arrays. This
|
||||
list would support multiple expressions defined for the <code>in</code>
|
||||
clause such as <code>select * from T_ACTOR where (id, last_name) in
|
||||
((1, 'Johnson'), (2, 'Harrop'))</code>. This
|
||||
of course requires that your database supports this syntax.</para>
|
||||
clause such as <code>select * from T_ACTOR where (id, last_name) in ((1,
|
||||
'Johnson'), (2, 'Harrop'))</code>. This of course requires that your
|
||||
database supports this syntax.</para>
|
||||
</section>
|
||||
|
||||
<section id="jdbc-complex-types">
|
||||
|
|
@ -2815,7 +2879,7 @@ SqlTypeValue value = new AbstractSqlTypeValue() {
|
|||
<title>Using HSQL</title>
|
||||
|
||||
<para>Spring supports HSQL 1.8.0 and above. HSQL is the default embedded
|
||||
database if no type is specified explicitly. To specify HSQL explicitly,
|
||||
database if no type is specified explicitly. To specify HSQL explicitly,
|
||||
set the <literal>type</literal> attribute of the
|
||||
<literal>embedded-database</literal> tag to <literal>HSQL</literal>. If
|
||||
you are using the builder API, call the
|
||||
|
|
@ -2920,8 +2984,7 @@ public class DataAccessUnitTestTemplate {
|
|||
existing data, the XML namespace provides a couple more options. The
|
||||
first is flag to switch the initialization on and off. This can be set
|
||||
according to the environment (e.g. to pull a boolean value from system
|
||||
properties or an environment bean), e.g.
|
||||
<programlisting><jdbc:initialize-database data-source="dataSource"
|
||||
properties or an environment bean), e.g. <programlisting><jdbc:initialize-database data-source="dataSource"
|
||||
<emphasis role="bold">enabled="#{systemProperties.INITIALIZE_DATABASE}"</emphasis>>
|
||||
<jdbc:script location="..."/>
|
||||
</jdbc:initialize-database></programlisting></para>
|
||||
|
|
@ -2979,23 +3042,20 @@ public class DataAccessUnitTestTemplate {
|
|||
<para>The first option might be easy if the application is in your
|
||||
control, and not otherwise. Some suggestions for how to implement this
|
||||
are<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<para>Make the cache initialize lazily on first usage, which
|
||||
improves application startup time</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>Have your cache or a separate component that
|
||||
initializes the cache implement <code>Lifecycle</code> or
|
||||
<code>SmartLifecycle</code>. When the application context
|
||||
starts up a <code>SmartLifecycle</code> can be automatically
|
||||
started if its <code>autoStartup</code> flag is set,
|
||||
and a <code>Lifecycle</code> can be started
|
||||
manually by calling
|
||||
<para>Have your cache or a separate component that initializes
|
||||
the cache implement <code>Lifecycle</code> or
|
||||
<code>SmartLifecycle</code>. When the application context starts
|
||||
up a <code>SmartLifecycle</code> can be automatically started if
|
||||
its <code>autoStartup</code> flag is set, and a
|
||||
<code>Lifecycle</code> can be started manually by calling
|
||||
<code>ConfigurableApplicationContext.start()</code> on the
|
||||
enclosing context.
|
||||
</para>
|
||||
enclosing context.</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
|
|
@ -3003,10 +3063,9 @@ public class DataAccessUnitTestTemplate {
|
|||
custom observer mechanism to trigger the cache initialization.
|
||||
<code>ContextRefreshedEvent</code> is always published by the
|
||||
context when it is ready for use (after all beans have been
|
||||
initialized), so that is often a useful hook (this is
|
||||
how the <code>SmartLifecycle</code> works by default).</para>
|
||||
initialized), so that is often a useful hook (this is how the
|
||||
<code>SmartLifecycle</code> works by default).</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist></para>
|
||||
|
||||
<para>The second option can also be easy. Some suggestions on how to
|
||||
|
|
|
|||
Loading…
Reference in New Issue