Merge branch '6.0.x'

# Conflicts:
#	gradle.properties
#	spring-core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java
This commit is contained in:
Juergen Hoeller 2023-07-14 12:18:41 +02:00
commit 064cd3b7af
5 changed files with 26 additions and 34 deletions

View File

@ -281,8 +281,8 @@ Spring Data JPA, make sure to set up deferred bootstrapping for its repositories
[[orm-jpa-dao]] [[orm-jpa-dao]]
== Implementing DAOs Based on JPA: `EntityManagerFactory` and `EntityManager` == Implementing DAOs Based on JPA: `EntityManagerFactory` and `EntityManager`
NOTE: Although `EntityManagerFactory` instances are thread-safe, `EntityManager` instances are NOTE: Although `EntityManagerFactory` instances are thread-safe, `EntityManager` instances
not. The injected JPA `EntityManager` behaves like an `EntityManager` fetched from an are not. The injected JPA `EntityManager` behaves like an `EntityManager` fetched from an
application server's JNDI environment, as defined by the JPA specification. It delegates application server's JNDI environment, as defined by the JPA specification. It delegates
all calls to the current transactional `EntityManager`, if any. Otherwise, it falls back all calls to the current transactional `EntityManager`, if any. Otherwise, it falls back
to a newly created `EntityManager` per operation, in effect making its usage thread-safe. to a newly created `EntityManager` per operation, in effect making its usage thread-safe.
@ -290,8 +290,8 @@ to a newly created `EntityManager` per operation, in effect making its usage thr
It is possible to write code against the plain JPA without any Spring dependencies, by It is possible to write code against the plain JPA without any Spring dependencies, by
using an injected `EntityManagerFactory` or `EntityManager`. Spring can understand the using an injected `EntityManagerFactory` or `EntityManager`. Spring can understand the
`@PersistenceUnit` and `@PersistenceContext` annotations both at the field and the method level `@PersistenceUnit` and `@PersistenceContext` annotations both at the field and the method level
if a `PersistenceAnnotationBeanPostProcessor` is enabled. The following example shows a plain JPA DAO implementation if a `PersistenceAnnotationBeanPostProcessor` is enabled. The following example shows a plain
that uses the `@PersistenceUnit` annotation: JPA DAO implementation that uses the `@PersistenceUnit` annotation:
[tabs] [tabs]
====== ======
@ -384,9 +384,9 @@ Consider the following example:
---- ----
The main problem with such a DAO is that it always creates a new `EntityManager` through The main problem with such a DAO is that it always creates a new `EntityManager` through
the factory. You can avoid this by requesting a transactional `EntityManager` (also the factory. You can avoid this by requesting a transactional `EntityManager` (also called a
called a "`shared EntityManager`" because it is a shared, thread-safe proxy for the actual "`shared EntityManager`" because it is a shared, thread-safe proxy for the actual transactional
transactional EntityManager) to be injected instead of the factory. The following example shows how to do so: EntityManager) to be injected instead of the factory. The following example shows how to do so:
[tabs] [tabs]
====== ======
@ -430,19 +430,19 @@ The `@PersistenceContext` annotation has an optional attribute called `type`, wh
`EntityManager` proxy. The alternative, `PersistenceContextType.EXTENDED`, is a completely `EntityManager` proxy. The alternative, `PersistenceContextType.EXTENDED`, is a completely
different affair. This results in a so-called extended `EntityManager`, which is not different affair. This results in a so-called extended `EntityManager`, which is not
thread-safe and, hence, must not be used in a concurrently accessed component, such as a thread-safe and, hence, must not be used in a concurrently accessed component, such as a
Spring-managed singleton bean. Extended `EntityManager` instances are only supposed to be used in Spring-managed singleton bean. Extended `EntityManager` instances are only supposed to be used#
stateful components that, for example, reside in a session, with the lifecycle of the in stateful components that, for example, reside in a session, with the lifecycle of the
`EntityManager` not tied to a current transaction but rather being completely up to the `EntityManager` not tied to a current transaction but rather being completely up to the
application. application.
.Method- and field-level Injection .Method- and field-level Injection
**** ****
You can apply annotations that indicate dependency injections (such as `@PersistenceUnit` and You can apply annotations that indicate dependency injections (such as `@PersistenceUnit` and
`@PersistenceContext`) on field or methods inside a class -- hence the `@PersistenceContext`) on field or methods inside a class -- hence the expressions
expressions "`method-level injection`" and "`field-level injection`". Field-level "`method-level injection`" and "`field-level injection`". Field-level annotations are
annotations are concise and easier to use while method-level annotations allow for further concise and easier to use while method-level annotations allow for further processing of the
processing of the injected dependency. In both cases, the member visibility (public, injected dependency. In both cases, the member visibility (public, protected, or private)
protected, or private) does not matter. does not matter.
What about class-level annotations? What about class-level annotations?
@ -451,9 +451,9 @@ injection.
**** ****
The injected `EntityManager` is Spring-managed (aware of the ongoing transaction). The injected `EntityManager` is Spring-managed (aware of the ongoing transaction).
Even though the new DAO implementation uses method-level Even though the new DAO implementation uses method-level injection of an `EntityManager`
injection of an `EntityManager` instead of an `EntityManagerFactory`, no change is instead of an `EntityManagerFactory`, no change is required in the bean definition
required in the application context XML, due to annotation usage. due to annotation usage.
The main advantage of this DAO style is that it depends only on the Java Persistence API. The main advantage of this DAO style is that it depends only on the Java Persistence API.
No import of any Spring class is required. Moreover, as the JPA annotations are understood, No import of any Spring class is required. Moreover, as the JPA annotations are understood,

View File

@ -660,7 +660,7 @@ class DefaultConversionServiceTests {
foo.add("2"); foo.add("2");
foo.add("3"); foo.add("3");
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
List<Integer> bar = (List<Integer>) conversionService.convert(foo, TypeDescriptor.forObject(foo), List<Integer> bar = (List<Integer>) conversionService.convert(foo,
new TypeDescriptor(getClass().getField("genericList"))); new TypeDescriptor(getClass().getField("genericList")));
assertThat(bar).containsExactly(1, 2, 3); assertThat(bar).containsExactly(1, 2, 3);
} }

View File

@ -193,7 +193,7 @@ class CollectionToCollectionConverterTests {
@Test @Test
void listToCollectionNoCopyRequired() throws NoSuchFieldException { void listToCollectionNoCopyRequired() throws NoSuchFieldException {
List<?> input = new ArrayList<>(Arrays.asList("foo", "bar")); List<?> input = new ArrayList<>(Arrays.asList("foo", "bar"));
assertThat(conversionService.convert(input, TypeDescriptor.forObject(input), assertThat(conversionService.convert(input,
new TypeDescriptor(getClass().getField("wildcardCollection")))).isSameAs(input); new TypeDescriptor(getClass().getField("wildcardCollection")))).isSameAs(input);
} }
@ -253,7 +253,7 @@ class CollectionToCollectionConverterTests {
List<String> list = new ArrayList<>(); List<String> list = new ArrayList<>();
list.add("A"); list.add("A");
list.add("C"); list.add("C");
assertThat(conversionService.convert(list, TypeDescriptor.forObject(list), new TypeDescriptor(getClass().getField("enumSet")))).isEqualTo(EnumSet.of(MyEnum.A, MyEnum.C)); assertThat(conversionService.convert(list, new TypeDescriptor(getClass().getField("enumSet")))).isEqualTo(EnumSet.of(MyEnum.A, MyEnum.C));
} }

View File

@ -302,7 +302,7 @@ class GenericConversionServiceTests {
void wildcardMap() throws Exception { void wildcardMap() throws Exception {
Map<String, String> input = new LinkedHashMap<>(); Map<String, String> input = new LinkedHashMap<>();
input.put("key", "value"); input.put("key", "value");
Object converted = conversionService.convert(input, TypeDescriptor.forObject(input), new TypeDescriptor(getClass().getField("wildcardMap"))); Object converted = conversionService.convert(input, new TypeDescriptor(getClass().getField("wildcardMap")));
assertThat(converted).isEqualTo(input); assertThat(converted).isEqualTo(input);
} }

View File

@ -417,9 +417,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
logger.debug("Executing SQL statement [" + sql + "]"); logger.debug("Executing SQL statement [" + sql + "]");
} }
/** // Callback to execute the statement.
* Callback to execute the statement.
*/
class ExecuteStatementCallback implements StatementCallback<Object>, SqlProvider { class ExecuteStatementCallback implements StatementCallback<Object>, SqlProvider {
@Override @Override
@Nullable @Nullable
@ -445,9 +443,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
logger.debug("Executing SQL query [" + sql + "]"); logger.debug("Executing SQL query [" + sql + "]");
} }
/** // Callback to execute the query.
* Callback to execute the query.
*/
class QueryStatementCallback implements StatementCallback<T>, SqlProvider { class QueryStatementCallback implements StatementCallback<T>, SqlProvider {
@Override @Override
@Nullable @Nullable
@ -542,9 +538,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
logger.debug("Executing SQL update [" + sql + "]"); logger.debug("Executing SQL update [" + sql + "]");
} }
/** // Callback to execute the update statement.
* Callback to execute the update statement.
*/
class UpdateStatementCallback implements StatementCallback<Integer>, SqlProvider { class UpdateStatementCallback implements StatementCallback<Integer>, SqlProvider {
@Override @Override
public Integer doInStatement(Statement stmt) throws SQLException { public Integer doInStatement(Statement stmt) throws SQLException {
@ -570,9 +564,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
logger.debug("Executing SQL batch update of " + sql.length + " statements"); logger.debug("Executing SQL batch update of " + sql.length + " statements");
} }
/** // Callback to execute the batch update.
* Callback to execute the batch update.
*/
class BatchUpdateStatementCallback implements StatementCallback<int[]>, SqlProvider { class BatchUpdateStatementCallback implements StatementCallback<int[]>, SqlProvider {
@Nullable @Nullable
@ -1373,7 +1365,7 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
} }
} }
} }
if (!(param.isResultsParameter())) { if (!param.isResultsParameter()) {
sqlColIndex++; sqlColIndex++;
} }
} }