Browse Source

Merge branch '6.0.x'

# Conflicts:
#	gradle.properties
#	spring-core/src/main/java/org/springframework/core/convert/support/GenericConversionService.java
pull/28374/merge
Juergen Hoeller 1 year ago
parent
commit
064cd3b7af
  1. 34
      framework-docs/modules/ROOT/pages/data-access/orm/jpa.adoc
  2. 2
      spring-core/src/test/java/org/springframework/core/convert/converter/DefaultConversionServiceTests.java
  3. 4
      spring-core/src/test/java/org/springframework/core/convert/support/CollectionToCollectionConverterTests.java
  4. 2
      spring-core/src/test/java/org/springframework/core/convert/support/GenericConversionServiceTests.java
  5. 18
      spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java

34
framework-docs/modules/ROOT/pages/data-access/orm/jpa.adoc

@ -281,8 +281,8 @@ Spring Data JPA, make sure to set up deferred bootstrapping for its repositories @@ -281,8 +281,8 @@ Spring Data JPA, make sure to set up deferred bootstrapping for its repositories
[[orm-jpa-dao]]
== Implementing DAOs Based on JPA: `EntityManagerFactory` and `EntityManager`
NOTE: Although `EntityManagerFactory` instances are thread-safe, `EntityManager` instances are
not. The injected JPA `EntityManager` behaves like an `EntityManager` fetched from an
NOTE: Although `EntityManagerFactory` instances are thread-safe, `EntityManager` instances
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
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.
@ -290,8 +290,8 @@ to a newly created `EntityManager` per operation, in effect making its usage thr @@ -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
using an injected `EntityManagerFactory` or `EntityManager`. Spring can understand the
`@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
that uses the `@PersistenceUnit` annotation:
if a `PersistenceAnnotationBeanPostProcessor` is enabled. The following example shows a plain
JPA DAO implementation that uses the `@PersistenceUnit` annotation:
[tabs]
======
@ -384,9 +384,9 @@ Consider the following example: @@ -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 factory. You can avoid this by requesting a transactional `EntityManager` (also
called a "`shared EntityManager`" because it is a shared, thread-safe proxy for the actual
transactional EntityManager) to be injected instead of the factory. The following example shows how to do so:
the factory. You can avoid this by requesting a transactional `EntityManager` (also called a
"`shared EntityManager`" because it is a shared, thread-safe proxy for the actual transactional
EntityManager) to be injected instead of the factory. The following example shows how to do so:
[tabs]
======
@ -430,19 +430,19 @@ The `@PersistenceContext` annotation has an optional attribute called `type`, wh @@ -430,19 +430,19 @@ The `@PersistenceContext` annotation has an optional attribute called `type`, wh
`EntityManager` proxy. The alternative, `PersistenceContextType.EXTENDED`, is a completely
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
Spring-managed singleton bean. Extended `EntityManager` instances are only supposed to be used in
stateful components that, for example, reside in a session, with the lifecycle of the
Spring-managed singleton bean. Extended `EntityManager` instances are only supposed to be used#
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
application.
.Method- and field-level Injection
****
You can apply annotations that indicate dependency injections (such as `@PersistenceUnit` and
`@PersistenceContext`) on field or methods inside a class -- hence the
expressions "`method-level injection`" and "`field-level injection`". Field-level
annotations are concise and easier to use while method-level annotations allow for further
processing of the injected dependency. In both cases, the member visibility (public,
protected, or private) does not matter.
`@PersistenceContext`) on field or methods inside a class -- hence the expressions
"`method-level injection`" and "`field-level injection`". Field-level annotations are
concise and easier to use while method-level annotations allow for further processing of the
injected dependency. In both cases, the member visibility (public, protected, or private)
does not matter.
What about class-level annotations?
@ -451,9 +451,9 @@ injection. @@ -451,9 +451,9 @@ injection.
****
The injected `EntityManager` is Spring-managed (aware of the ongoing transaction).
Even though the new DAO implementation uses method-level
injection of an `EntityManager` instead of an `EntityManagerFactory`, no change is
required in the application context XML, due to annotation usage.
Even though the new DAO implementation uses method-level injection of an `EntityManager`
instead of an `EntityManagerFactory`, no change is required in the bean definition
due to annotation usage.
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,

2
spring-core/src/test/java/org/springframework/core/convert/converter/DefaultConversionServiceTests.java

@ -660,7 +660,7 @@ class DefaultConversionServiceTests { @@ -660,7 +660,7 @@ class DefaultConversionServiceTests {
foo.add("2");
foo.add("3");
@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")));
assertThat(bar).containsExactly(1, 2, 3);
}

4
spring-core/src/test/java/org/springframework/core/convert/support/CollectionToCollectionConverterTests.java

@ -193,7 +193,7 @@ class CollectionToCollectionConverterTests { @@ -193,7 +193,7 @@ class CollectionToCollectionConverterTests {
@Test
void listToCollectionNoCopyRequired() throws NoSuchFieldException {
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);
}
@ -253,7 +253,7 @@ class CollectionToCollectionConverterTests { @@ -253,7 +253,7 @@ class CollectionToCollectionConverterTests {
List<String> list = new ArrayList<>();
list.add("A");
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));
}

2
spring-core/src/test/java/org/springframework/core/convert/support/GenericConversionServiceTests.java

@ -302,7 +302,7 @@ class GenericConversionServiceTests { @@ -302,7 +302,7 @@ class GenericConversionServiceTests {
void wildcardMap() throws Exception {
Map<String, String> input = new LinkedHashMap<>();
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);
}

18
spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java

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

Loading…
Cancel
Save