Polishing

This commit is contained in:
Juergen Hoeller 2023-09-11 17:36:57 +02:00
parent 4235a11c4f
commit 659500bc1f
5 changed files with 85 additions and 63 deletions

View File

@ -5,16 +5,11 @@ The Spring Framework provides abstractions for the asynchronous execution and sc
tasks with the `TaskExecutor` and `TaskScheduler` interfaces, respectively. Spring also tasks with the `TaskExecutor` and `TaskScheduler` interfaces, respectively. Spring also
features implementations of those interfaces that support thread pools or delegation to features implementations of those interfaces that support thread pools or delegation to
CommonJ within an application server environment. Ultimately, the use of these CommonJ within an application server environment. Ultimately, the use of these
implementations behind the common interfaces abstracts away the differences between Java implementations behind the common interfaces abstracts away the differences between
SE 5, Java SE 6, and Jakarta EE environments. Java SE and Jakarta EE environments.
Spring also features integration classes to support scheduling with the `Timer` Spring also features integration classes to support scheduling with the
(part of the JDK since 1.3) and the https://www.quartz-scheduler.org/[Quartz Scheduler]. https://www.quartz-scheduler.org/[Quartz Scheduler].
You can set up both of those schedulers by using a `FactoryBean` with optional references to
`Timer` or `Trigger` instances, respectively. Furthermore, a convenience class for both
the Quartz Scheduler and the `Timer` is available that lets you invoke a method of
an existing target object (analogous to the normal `MethodInvokingFactoryBean`
operation).
@ -261,8 +256,8 @@ execution.
[[scheduling-enable-annotation-support]] [[scheduling-enable-annotation-support]]
=== Enable Scheduling Annotations === Enable Scheduling Annotations
To enable support for `@Scheduled` and `@Async` annotations, you can add `@EnableScheduling` and To enable support for `@Scheduled` and `@Async` annotations, you can add `@EnableScheduling`
`@EnableAsync` to one of your `@Configuration` classes, as the following example shows: and `@EnableAsync` to one of your `@Configuration` classes, as the following example shows:
[source,java,indent=0,subs="verbatim,quotes"] [source,java,indent=0,subs="verbatim,quotes"]
---- ----
@ -336,7 +331,7 @@ For example, the previous example can also be written as follows.
If you need a fixed-rate execution, you can use the `fixedRate` attribute within the If you need a fixed-rate execution, you can use the `fixedRate` attribute within the
annotation. The following method is invoked every five seconds (measured between the annotation. The following method is invoked every five seconds (measured between the
successive start times of each invocation). successive start times of each invocation):
[source,java,indent=0,subs="verbatim,quotes"] [source,java,indent=0,subs="verbatim,quotes"]
---- ----
@ -346,9 +341,9 @@ successive start times of each invocation).
} }
---- ----
For fixed-delay and fixed-rate tasks, you can specify an initial delay by indicating the For fixed-delay and fixed-rate tasks, you can specify an initial delay by indicating
amount of time to wait before the first execution of the method, as the following the amount of time to wait before the first execution of the method, as the following
`fixedRate` example shows. `fixedRate` example shows:
[source,java,indent=0,subs="verbatim,quotes"] [source,java,indent=0,subs="verbatim,quotes"]
---- ----
@ -417,8 +412,8 @@ to a method that returns `void`, as the following example shows:
Unlike the methods annotated with the `@Scheduled` annotation, these methods can expect Unlike the methods annotated with the `@Scheduled` annotation, these methods can expect
arguments, because they are invoked in the "`normal`" way by callers at runtime rather arguments, because they are invoked in the "`normal`" way by callers at runtime rather
than from a scheduled task being managed by the container. For example, the following code is than from a scheduled task being managed by the container. For example, the following
a legitimate application of the `@Async` annotation: code is a legitimate application of the `@Async` annotation:
[source,java,indent=0,subs="verbatim,quotes"] [source,java,indent=0,subs="verbatim,quotes"]
---- ----
@ -442,15 +437,15 @@ that returns a value:
} }
---- ----
TIP: `@Async` methods may not only declare a regular `java.util.concurrent.Future` return type TIP: `@Async` methods may not only declare a regular `java.util.concurrent.Future` return
but also Spring's `org.springframework.util.concurrent.ListenableFuture` or, as of Spring type but also Spring's `org.springframework.util.concurrent.ListenableFuture` or, as of
4.2, JDK 8's `java.util.concurrent.CompletableFuture`, for richer interaction with the Spring 4.2, JDK 8's `java.util.concurrent.CompletableFuture`, for richer interaction with
asynchronous task and for immediate composition with further processing steps. the asynchronous task and for immediate composition with further processing steps.
You can not use `@Async` in conjunction with lifecycle callbacks such as You can not use `@Async` in conjunction with lifecycle callbacks such as `@PostConstruct`.
`@PostConstruct`. To asynchronously initialize Spring beans, you currently have to use To asynchronously initialize Spring beans, you currently have to use a separate
a separate initializing Spring bean that then invokes the `@Async` annotated method on the initializing Spring bean that then invokes the `@Async` annotated method on the target,
target, as the following example shows: as the following example shows:
[source,java,indent=0,subs="verbatim,quotes"] [source,java,indent=0,subs="verbatim,quotes"]
---- ----
@ -504,8 +499,8 @@ used when executing a given method. The following example shows how to do so:
---- ----
In this case, `"otherExecutor"` can be the name of any `Executor` bean in the Spring In this case, `"otherExecutor"` can be the name of any `Executor` bean in the Spring
container, or it may be the name of a qualifier associated with any `Executor` (for example, as container, or it may be the name of a qualifier associated with any `Executor` (for example,
specified with the `<qualifier>` element or Spring's `@Qualifier` annotation). as specified with the `<qualifier>` element or Spring's `@Qualifier` annotation).
[[scheduling-annotation-support-exception]] [[scheduling-annotation-support-exception]]
@ -673,14 +668,15 @@ invoked on that object. The following listing shows a simple example:
---- ----
The scheduler is referenced by the outer element, and each individual The scheduler is referenced by the outer element, and each individual
task includes the configuration of its trigger metadata. In the preceding example, that task includes the configuration of its trigger metadata. In the preceding example,
metadata defines a periodic trigger with a fixed delay indicating the number of that metadata defines a periodic trigger with a fixed delay indicating the number of
milliseconds to wait after each task execution has completed. Another option is milliseconds to wait after each task execution has completed. Another option is
`fixed-rate`, indicating how often the method should be run regardless of how long `fixed-rate`, indicating how often the method should be run regardless of how long
any previous execution takes. Additionally, for both `fixed-delay` and `fixed-rate` tasks, you can specify an any previous execution takes. Additionally, for both `fixed-delay` and `fixed-rate`
'initial-delay' parameter, indicating the number of milliseconds to wait tasks, you can specify an 'initial-delay' parameter, indicating the number of
before the first execution of the method. For more control, you can instead provide a `cron` attribute milliseconds to wait before the first execution of the method. For more control,
to provide a xref:integration/scheduling.adoc#scheduling-cron-expression[cron expression]. you can instead provide a `cron` attribute to provide a
xref:integration/scheduling.adoc#scheduling-cron-expression[cron expression].
The following example shows these other options: The following example shows these other options:
[source,xml,indent=0] [source,xml,indent=0]
@ -703,9 +699,8 @@ The following example shows these other options:
All Spring cron expressions have to conform to the same format, whether you are using them in All Spring cron expressions have to conform to the same format, whether you are using them in
xref:integration/scheduling.adoc#scheduling-annotation-support-scheduled[`@Scheduled` annotations], xref:integration/scheduling.adoc#scheduling-annotation-support-scheduled[`@Scheduled` annotations],
xref:integration/scheduling.adoc#scheduling-task-namespace-scheduled-tasks[`task:scheduled-tasks` elements], xref:integration/scheduling.adoc#scheduling-task-namespace-scheduled-tasks[`task:scheduled-tasks` elements],
or someplace else. or someplace else. A well-formed cron expression, such as `* * * * * *`, consists of six
A well-formed cron expression, such as `* * * * * *`, consists of six space-separated time and date space-separated time and date fields, each with its own range of valid values:
fields, each with its own range of valid values:
.... ....
@ -770,9 +765,10 @@ Here are some examples:
[[macros]] [[macros]]
=== Macros === Macros
Expressions such as `0 0 * * * *` are hard for humans to parse and are, therefore, hard to fix in case of bugs. Expressions such as `0 0 * * * *` are hard for humans to parse and are, therefore,
To improve readability, Spring supports the following macros, which represent commonly used sequences. hard to fix in case of bugs. To improve readability, Spring supports the following
You can use these macros instead of the six-digit value, thus: `@Scheduled(cron = "@hourly")`. macros, which represent commonly used sequences. You can use these macros instead
of the six-digit value, thus: `@Scheduled(cron = "@hourly")`.
|=== |===
|Macro | Meaning |Macro | Meaning
@ -789,8 +785,8 @@ You can use these macros instead of the six-digit value, thus: `@Scheduled(cron
[[scheduling-quartz]] [[scheduling-quartz]]
== Using the Quartz Scheduler == Using the Quartz Scheduler
Quartz uses `Trigger`, `Job`, and `JobDetail` objects to realize scheduling of all kinds Quartz uses `Trigger`, `Job`, and `JobDetail` objects to realize scheduling of all
of jobs. For the basic concepts behind Quartz, see the kinds of jobs. For the basic concepts behind Quartz, see the
https://www.quartz-scheduler.org/[Quartz Web site]. For convenience purposes, Spring https://www.quartz-scheduler.org/[Quartz Web site]. For convenience purposes, Spring
offers a couple of classes that simplify using Quartz within Spring-based applications. offers a couple of classes that simplify using Quartz within Spring-based applications.
@ -798,9 +794,9 @@ offers a couple of classes that simplify using Quartz within Spring-based applic
[[scheduling-quartz-jobdetail]] [[scheduling-quartz-jobdetail]]
=== Using the `JobDetailFactoryBean` === Using the `JobDetailFactoryBean`
Quartz `JobDetail` objects contain all the information needed to run a job. Spring provides a Quartz `JobDetail` objects contain all the information needed to run a job. Spring
`JobDetailFactoryBean`, which provides bean-style properties for XML configuration purposes. provides a `JobDetailFactoryBean`, which provides bean-style properties for XML
Consider the following example: configuration purposes. Consider the following example:
[source,xml,indent=0,subs="verbatim,quotes"] [source,xml,indent=0,subs="verbatim,quotes"]
---- ----
@ -817,9 +813,9 @@ Consider the following example:
The job detail configuration has all the information it needs to run the job (`ExampleJob`). The job detail configuration has all the information it needs to run the job (`ExampleJob`).
The timeout is specified in the job data map. The job data map is available through the The timeout is specified in the job data map. The job data map is available through the
`JobExecutionContext` (passed to you at execution time), but the `JobDetail` also gets `JobExecutionContext` (passed to you at execution time), but the `JobDetail` also gets
its properties from the job data mapped to properties of the job instance. So, in the following example, its properties from the job data mapped to properties of the job instance. So, in the
the `ExampleJob` contains a bean property named `timeout`, and the `JobDetail` following example, the `ExampleJob` contains a bean property named `timeout`, and the
has it applied automatically: `JobDetail` has it applied automatically:
[source,java,indent=0,subs="verbatim,quotes",chomp="-packages"] [source,java,indent=0,subs="verbatim,quotes",chomp="-packages"]
---- ----
@ -912,8 +908,8 @@ NOTE: By default, jobs will run in a concurrent fashion.
[[scheduling-quartz-cron]] [[scheduling-quartz-cron]]
=== Wiring up Jobs by Using Triggers and `SchedulerFactoryBean` === Wiring up Jobs by Using Triggers and `SchedulerFactoryBean`
We have created job details and jobs. We have also reviewed the convenience bean that lets We have created job details and jobs. We have also reviewed the convenience bean that
you invoke a method on a specific object. Of course, we still need to schedule the lets you invoke a method on a specific object. Of course, we still need to schedule the
jobs themselves. This is done by using triggers and a `SchedulerFactoryBean`. Several jobs themselves. This is done by using triggers and a `SchedulerFactoryBean`. Several
triggers are available within Quartz, and Spring offers two Quartz `FactoryBean` triggers are available within Quartz, and Spring offers two Quartz `FactoryBean`
implementations with convenient defaults: `CronTriggerFactoryBean` and implementations with convenient defaults: `CronTriggerFactoryBean` and
@ -944,9 +940,9 @@ The following listing uses both a `SimpleTriggerFactoryBean` and a `CronTriggerF
</bean> </bean>
---- ----
The preceding example sets up two triggers, one running every 50 seconds with a starting delay of 10 The preceding example sets up two triggers, one running every 50 seconds with a starting
seconds and one running every morning at 6 AM. To finalize everything, we need to set up the delay of 10 seconds and one running every morning at 6 AM. To finalize everything,
`SchedulerFactoryBean`, as the following example shows: we need to set up the `SchedulerFactoryBean`, as the following example shows:
[source,xml,indent=0,subs="verbatim,quotes"] [source,xml,indent=0,subs="verbatim,quotes"]
---- ----

View File

@ -56,5 +56,4 @@ public class FixedRateTask extends IntervalTask {
super(task); super(task);
} }
} }

View File

@ -99,8 +99,6 @@ public class IntervalTask extends Task {
} }
/** /**
* Return how often in milliseconds the task should be executed. * Return how often in milliseconds the task should be executed.
* @deprecated as of 6.0, in favor of {@link #getIntervalDuration()} * @deprecated as of 6.0, in favor of {@link #getIntervalDuration()}

View File

@ -66,15 +66,17 @@ public class JdbcTemplateQueryTests {
@BeforeEach @BeforeEach
public void setUp() throws Exception { public void setup() throws Exception {
given(this.dataSource.getConnection()).willReturn(this.connection); given(this.dataSource.getConnection()).willReturn(this.connection);
given(this.connection.createStatement()).willReturn(this.statement);
given(this.connection.prepareStatement(anyString())).willReturn(this.preparedStatement);
given(this.statement.getConnection()).willReturn(this.connection);
given(this.statement.executeQuery(anyString())).willReturn(this.resultSet);
given(this.preparedStatement.getConnection()).willReturn(this.connection);
given(this.preparedStatement.executeQuery()).willReturn(this.resultSet);
given(this.resultSet.getMetaData()).willReturn(this.resultSetMetaData); given(this.resultSet.getMetaData()).willReturn(this.resultSetMetaData);
given(this.resultSetMetaData.getColumnCount()).willReturn(1); given(this.resultSetMetaData.getColumnCount()).willReturn(1);
given(this.resultSetMetaData.getColumnLabel(1)).willReturn("age"); given(this.resultSetMetaData.getColumnLabel(1)).willReturn("age");
given(this.connection.createStatement()).willReturn(this.statement);
given(this.connection.prepareStatement(anyString())).willReturn(this.preparedStatement);
given(this.preparedStatement.executeQuery()).willReturn(this.resultSet);
given(this.statement.executeQuery(anyString())).willReturn(this.resultSet);
} }
@ -89,6 +91,7 @@ public class JdbcTemplateQueryTests {
assertThat(((Integer) li.get(1).get("age"))).as("Second row is Integer").isEqualTo(12); assertThat(((Integer) li.get(1).get("age"))).as("Second row is Integer").isEqualTo(12);
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.statement).close(); verify(this.statement).close();
verify(this.connection).close();
} }
@Test @Test
@ -99,6 +102,7 @@ public class JdbcTemplateQueryTests {
assertThat(li).as("All rows returned").isEmpty(); assertThat(li).as("All rows returned").isEmpty();
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.statement).close(); verify(this.statement).close();
verify(this.connection).close();
} }
@Test @Test
@ -111,6 +115,7 @@ public class JdbcTemplateQueryTests {
assertThat(((Integer) li.get(0).get("age"))).as("First row is Integer").isEqualTo(11); assertThat(((Integer) li.get(0).get("age"))).as("First row is Integer").isEqualTo(11);
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.statement).close(); verify(this.statement).close();
verify(this.connection).close();
} }
@Test @Test
@ -123,6 +128,7 @@ public class JdbcTemplateQueryTests {
assertThat(li.get(0)).as("Element is Integer").isEqualTo(11); assertThat(li.get(0)).as("Element is Integer").isEqualTo(11);
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.statement).close(); verify(this.statement).close();
verify(this.connection).close();
} }
@Test @Test
@ -134,6 +140,7 @@ public class JdbcTemplateQueryTests {
assertThat((Integer) map.get("age")).as("Wow is Integer").isEqualTo(11); assertThat((Integer) map.get("age")).as("Wow is Integer").isEqualTo(11);
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.statement).close(); verify(this.statement).close();
verify(this.connection).close();
} }
@Test @Test
@ -145,6 +152,7 @@ public class JdbcTemplateQueryTests {
this.template.queryForObject(sql, String.class)); this.template.queryForObject(sql, String.class));
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.statement).close(); verify(this.statement).close();
verify(this.connection).close();
} }
@Test @Test
@ -156,6 +164,7 @@ public class JdbcTemplateQueryTests {
assertThat(o).as("Correct result type").isInstanceOf(Integer.class); assertThat(o).as("Correct result type").isInstanceOf(Integer.class);
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.statement).close(); verify(this.statement).close();
verify(this.connection).close();
} }
@Test @Test
@ -173,6 +182,7 @@ public class JdbcTemplateQueryTests {
assertThat(count.get()).isEqualTo(1); assertThat(count.get()).isEqualTo(1);
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.statement).close(); verify(this.statement).close();
verify(this.connection).close();
} }
@Test @Test
@ -183,6 +193,7 @@ public class JdbcTemplateQueryTests {
assertThat(this.template.queryForObject(sql, String.class)).isEqualTo("myvalue"); assertThat(this.template.queryForObject(sql, String.class)).isEqualTo("myvalue");
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.statement).close(); verify(this.statement).close();
verify(this.connection).close();
} }
@Test @Test
@ -193,6 +204,7 @@ public class JdbcTemplateQueryTests {
assertThat(this.template.queryForObject(sql, BigInteger.class)).isEqualTo(new BigInteger("22")); assertThat(this.template.queryForObject(sql, BigInteger.class)).isEqualTo(new BigInteger("22"));
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.statement).close(); verify(this.statement).close();
verify(this.connection).close();
} }
@Test @Test
@ -203,6 +215,7 @@ public class JdbcTemplateQueryTests {
assertThat(this.template.queryForObject(sql, BigDecimal.class)).isEqualTo(new BigDecimal("22.5")); assertThat(this.template.queryForObject(sql, BigDecimal.class)).isEqualTo(new BigDecimal("22.5"));
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.statement).close(); verify(this.statement).close();
verify(this.connection).close();
} }
@Test @Test
@ -213,6 +226,7 @@ public class JdbcTemplateQueryTests {
assertThat(this.template.queryForObject(sql, Integer.class)).isEqualTo(Integer.valueOf(22)); assertThat(this.template.queryForObject(sql, Integer.class)).isEqualTo(Integer.valueOf(22));
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.statement).close(); verify(this.statement).close();
verify(this.connection).close();
} }
@Test @Test
@ -224,6 +238,7 @@ public class JdbcTemplateQueryTests {
assertThat(this.template.queryForObject(sql, Integer.class)).isNull(); assertThat(this.template.queryForObject(sql, Integer.class)).isNull();
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.statement).close(); verify(this.statement).close();
verify(this.connection).close();
} }
@Test @Test
@ -235,6 +250,7 @@ public class JdbcTemplateQueryTests {
assertThat(i).as("Return of an int").isEqualTo(22); assertThat(i).as("Return of an int").isEqualTo(22);
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.statement).close(); verify(this.statement).close();
verify(this.connection).close();
} }
@Test @Test
@ -246,6 +262,7 @@ public class JdbcTemplateQueryTests {
assertThat(i).as("Return of an int").isEqualTo(22); assertThat(i).as("Return of an int").isEqualTo(22);
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.statement).close(); verify(this.statement).close();
verify(this.connection).close();
} }
@Test @Test
@ -257,6 +274,7 @@ public class JdbcTemplateQueryTests {
assertThat(l).as("Return of a long").isEqualTo(87); assertThat(l).as("Return of a long").isEqualTo(87);
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.statement).close(); verify(this.statement).close();
verify(this.connection).close();
} }
@Test @Test
@ -268,6 +286,7 @@ public class JdbcTemplateQueryTests {
assertThat(l).as("Return of a long").isEqualTo(87); assertThat(l).as("Return of a long").isEqualTo(87);
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.statement).close(); verify(this.statement).close();
verify(this.connection).close();
} }
@Test @Test
@ -290,6 +309,7 @@ public class JdbcTemplateQueryTests {
verify(this.preparedStatement).setObject(1, 3); verify(this.preparedStatement).setObject(1, 3);
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.preparedStatement).close(); verify(this.preparedStatement).close();
verify(this.connection).close();
} }
@Test @Test
@ -301,6 +321,7 @@ public class JdbcTemplateQueryTests {
verify(this.preparedStatement).setObject(1, 3); verify(this.preparedStatement).setObject(1, 3);
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.preparedStatement).close(); verify(this.preparedStatement).close();
verify(this.connection).close();
} }
@Test @Test
@ -314,6 +335,7 @@ public class JdbcTemplateQueryTests {
verify(this.preparedStatement).setObject(1, 3); verify(this.preparedStatement).setObject(1, 3);
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.preparedStatement).close(); verify(this.preparedStatement).close();
verify(this.connection).close();
} }
@Test @Test
@ -327,6 +349,7 @@ public class JdbcTemplateQueryTests {
verify(this.preparedStatement).setObject(1, 3); verify(this.preparedStatement).setObject(1, 3);
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.preparedStatement).close(); verify(this.preparedStatement).close();
verify(this.connection).close();
} }
@Test @Test
@ -339,6 +362,7 @@ public class JdbcTemplateQueryTests {
verify(this.preparedStatement).setObject(1, 3); verify(this.preparedStatement).setObject(1, 3);
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.preparedStatement).close(); verify(this.preparedStatement).close();
verify(this.connection).close();
} }
@Test @Test
@ -351,6 +375,7 @@ public class JdbcTemplateQueryTests {
verify(this.preparedStatement).setObject(1, 3); verify(this.preparedStatement).setObject(1, 3);
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.preparedStatement).close(); verify(this.preparedStatement).close();
verify(this.connection).close();
} }
@Test @Test
@ -369,6 +394,7 @@ public class JdbcTemplateQueryTests {
verify(this.preparedStatement).setObject(1, 3); verify(this.preparedStatement).setObject(1, 3);
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.preparedStatement).close(); verify(this.preparedStatement).close();
verify(this.connection).close();
} }
@Test @Test
@ -381,6 +407,7 @@ public class JdbcTemplateQueryTests {
verify(this.preparedStatement).setObject(1, 3); verify(this.preparedStatement).setObject(1, 3);
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.preparedStatement).close(); verify(this.preparedStatement).close();
verify(this.connection).close();
} }
@Test @Test
@ -393,6 +420,7 @@ public class JdbcTemplateQueryTests {
verify(this.preparedStatement).setObject(1, 3); verify(this.preparedStatement).setObject(1, 3);
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.preparedStatement).close(); verify(this.preparedStatement).close();
verify(this.connection).close();
} }
@Test @Test
@ -405,6 +433,7 @@ public class JdbcTemplateQueryTests {
verify(this.preparedStatement).setObject(1, 3); verify(this.preparedStatement).setObject(1, 3);
verify(this.resultSet).close(); verify(this.resultSet).close();
verify(this.preparedStatement).close(); verify(this.preparedStatement).close();
verify(this.connection).close();
} }
} }

View File

@ -94,12 +94,12 @@ public class JdbcTemplateTests {
public void setup() throws Exception { public void setup() throws Exception {
given(this.dataSource.getConnection()).willReturn(this.connection); given(this.dataSource.getConnection()).willReturn(this.connection);
given(this.connection.prepareStatement(anyString())).willReturn(this.preparedStatement); given(this.connection.prepareStatement(anyString())).willReturn(this.preparedStatement);
given(this.connection.prepareCall(anyString())).willReturn(this.callableStatement);
given(this.statement.getConnection()).willReturn(this.connection);
given(this.statement.executeQuery(anyString())).willReturn(this.resultSet);
given(this.preparedStatement.executeQuery()).willReturn(this.resultSet); given(this.preparedStatement.executeQuery()).willReturn(this.resultSet);
given(this.preparedStatement.executeQuery(anyString())).willReturn(this.resultSet); given(this.preparedStatement.executeQuery(anyString())).willReturn(this.resultSet);
given(this.preparedStatement.getConnection()).willReturn(this.connection); given(this.preparedStatement.getConnection()).willReturn(this.connection);
given(this.statement.getConnection()).willReturn(this.connection);
given(this.statement.executeQuery(anyString())).willReturn(this.resultSet);
given(this.connection.prepareCall(anyString())).willReturn(this.callableStatement);
given(this.callableStatement.getResultSet()).willReturn(this.resultSet); given(this.callableStatement.getResultSet()).willReturn(this.resultSet);
} }