Skip to content

Commit d17bff8

Browse files
kota65535mp911de
authored andcommitted
Add jdbcAggregateOperationsRef to @EnableJdbcRepositories.
Closes #687 Original pull request: #1704
1 parent 38f2af0 commit d17bff8

15 files changed

+300
-38
lines changed

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateOperations.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import org.springframework.data.domain.Page;
2525
import org.springframework.data.domain.Pageable;
2626
import org.springframework.data.domain.Sort;
27+
import org.springframework.data.jdbc.core.convert.DataAccessStrategy;
28+
import org.springframework.data.jdbc.core.convert.JdbcConverter;
2729
import org.springframework.data.relational.core.query.Query;
2830
import org.springframework.lang.Nullable;
2931

@@ -37,6 +39,7 @@
3739
* @author Diego Krupitza
3840
* @author Myeonghyeon Lee
3941
* @author Sergey Korotaev
42+
* @author Tomohiko Ozawa
4043
*/
4144
public interface JdbcAggregateOperations {
4245

@@ -324,4 +327,18 @@ public interface JdbcAggregateOperations {
324327
* @param <T> the type of the aggregate roots.
325328
*/
326329
<T> void deleteAll(Iterable<? extends T> aggregateRoots);
330+
331+
/**
332+
* Returns the {@link JdbcConverter}.
333+
*
334+
* @return the {@link JdbcConverter}.
335+
*/
336+
JdbcConverter getConverter();
337+
338+
/**
339+
* Return the {@link DataAccessStrategy}
340+
*
341+
* @return the {@link DataAccessStrategy}
342+
*/
343+
DataAccessStrategy getDataAccessStrategy();
327344
}

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/JdbcAggregateTemplate.java

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
* @author Diego Krupitza
7171
* @author Sergey Korotaev
7272
* @author Mikhail Polivakha
73+
* @author Tomohiko Ozawa
7374
*/
7475
public class JdbcAggregateTemplate implements JdbcAggregateOperations {
7576

@@ -84,6 +85,57 @@ public class JdbcAggregateTemplate implements JdbcAggregateOperations {
8485

8586
private EntityCallbacks entityCallbacks = EntityCallbacks.create();
8687

88+
/**
89+
* Creates a new {@link JdbcAggregateTemplate} given {@link ApplicationContext}, {@link RelationalMappingContext} and
90+
* {@link DataAccessStrategy}.
91+
*
92+
* @param publisher must not be {@literal null}.
93+
* @param dataAccessStrategy must not be {@literal null}.
94+
* @since 3.3
95+
*/
96+
public JdbcAggregateTemplate(ApplicationContext publisher, JdbcConverter converter,
97+
DataAccessStrategy dataAccessStrategy) {
98+
99+
Assert.notNull(publisher, "ApplicationContext must not be null");
100+
Assert.notNull(converter, "RelationalConverter must not be null");
101+
Assert.notNull(dataAccessStrategy, "DataAccessStrategy must not be null");
102+
103+
this.eventDelegate.setPublisher(publisher);
104+
this.converter = converter;
105+
this.accessStrategy = dataAccessStrategy;
106+
this.context = converter.getMappingContext();
107+
108+
this.jdbcEntityDeleteWriter = new RelationalEntityDeleteWriter(context);
109+
110+
this.executor = new AggregateChangeExecutor(converter, accessStrategy);
111+
112+
setEntityCallbacks(EntityCallbacks.create(publisher));
113+
}
114+
115+
/**
116+
* Creates a new {@link JdbcAggregateTemplate} given {@link ApplicationEventPublisher},
117+
* {@link RelationalMappingContext} and {@link DataAccessStrategy}.
118+
*
119+
* @param publisher must not be {@literal null}.
120+
* @param dataAccessStrategy must not be {@literal null}.
121+
* @since 3.3
122+
*/
123+
public JdbcAggregateTemplate(ApplicationEventPublisher publisher, JdbcConverter converter,
124+
DataAccessStrategy dataAccessStrategy) {
125+
126+
Assert.notNull(publisher, "ApplicationEventPublisher must not be null");
127+
Assert.notNull(converter, "RelationalConverter must not be null");
128+
Assert.notNull(dataAccessStrategy, "DataAccessStrategy must not be null");
129+
130+
this.eventDelegate.setPublisher(publisher);
131+
this.converter = converter;
132+
this.accessStrategy = dataAccessStrategy;
133+
this.context = converter.getMappingContext();
134+
135+
this.jdbcEntityDeleteWriter = new RelationalEntityDeleteWriter(context);
136+
this.executor = new AggregateChangeExecutor(converter, accessStrategy);
137+
}
138+
87139
/**
88140
* Creates a new {@link JdbcAggregateTemplate} given {@link ApplicationContext}, {@link RelationalMappingContext} and
89141
* {@link DataAccessStrategy}.
@@ -92,7 +144,10 @@ public class JdbcAggregateTemplate implements JdbcAggregateOperations {
92144
* @param context must not be {@literal null}.
93145
* @param dataAccessStrategy must not be {@literal null}.
94146
* @since 1.1
147+
* @deprecated since 3.3, use {@link JdbcAggregateTemplate(ApplicationContext, JdbcConverter, DataAccessStrategy)}
148+
* instead.
95149
*/
150+
@Deprecated(since = "3.3")
96151
public JdbcAggregateTemplate(ApplicationContext publisher, RelationalMappingContext context, JdbcConverter converter,
97152
DataAccessStrategy dataAccessStrategy) {
98153

@@ -120,7 +175,10 @@ public JdbcAggregateTemplate(ApplicationContext publisher, RelationalMappingCont
120175
* @param publisher must not be {@literal null}.
121176
* @param context must not be {@literal null}.
122177
* @param dataAccessStrategy must not be {@literal null}.
178+
* @deprecated since 3.3, use {@link JdbcAggregateTemplate(ApplicationEventPublisher, JdbcConverter,
179+
* DataAccessStrategy)} instead.
123180
*/
181+
@Deprecated(since = "3.3")
124182
public JdbcAggregateTemplate(ApplicationEventPublisher publisher, RelationalMappingContext context,
125183
JdbcConverter converter, DataAccessStrategy dataAccessStrategy) {
126184

@@ -705,4 +763,14 @@ private record EntityAndChangeCreator<T>(T entity, AggregateChangeCreator<T> cha
705763
private interface AggregateChangeCreator<T> {
706764
RootAggregateChange<T> createAggregateChange(T instance);
707765
}
766+
767+
@Override
768+
public DataAccessStrategy getDataAccessStrategy() {
769+
return accessStrategy;
770+
}
771+
772+
@Override
773+
public JdbcConverter getConverter() {
774+
return converter;
775+
}
708776
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*
2+
* Copyright 2020-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.jdbc.dialect;
17+
18+
import java.sql.Connection;
19+
import java.util.Optional;
20+
21+
import javax.sql.DataSource;
22+
23+
import org.springframework.core.io.support.SpringFactoriesLoader;
24+
import org.springframework.data.jdbc.core.dialect.JdbcDialect;
25+
import org.springframework.data.relational.core.dialect.Dialect;
26+
import org.springframework.jdbc.core.JdbcOperations;
27+
28+
/**
29+
* Resolves a {@link Dialect}. Resolution typically uses {@link JdbcOperations} to obtain and inspect a
30+
* {@link Connection}. Dialect resolution uses Spring's {@link SpringFactoriesLoader spring.factories} to determine
31+
* available {@link JdbcDialectProvider extensions}.
32+
*
33+
* @author Jens Schauder
34+
* @author Mikhail Polivakha
35+
* @since 2.0
36+
* @see Dialect
37+
* @see SpringFactoriesLoader
38+
* @deprecated since 3.5, replacement {@link org.springframework.data.jdbc.core.dialect.DialectResolver} was moved to
39+
* the {@link org.springframework.data.jdbc.core.dialect} package.
40+
*/
41+
@Deprecated(since = "3.5", forRemoval = true)
42+
public class DialectResolver {
43+
44+
// utility constructor.
45+
private DialectResolver() {}
46+
47+
/**
48+
* Retrieve a {@link Dialect} by inspecting a {@link Connection}.
49+
*
50+
* @param operations must not be {@literal null}.
51+
* @return the resolved {@link Dialect} {@link NoDialectException} if the database type cannot be determined from
52+
* {@link DataSource}.
53+
* @throws NoDialectException if no {@link Dialect} can be found.
54+
*/
55+
public static JdbcDialect getDialect(JdbcOperations operations) {
56+
return org.springframework.data.jdbc.core.dialect.DialectResolver.getDialect(operations);
57+
}
58+
59+
/**
60+
* SPI to extend Spring's default JDBC Dialect discovery mechanism. Implementations of this interface are discovered
61+
* through Spring's {@link SpringFactoriesLoader} mechanism.
62+
*
63+
* @author Jens Schauder
64+
* @see org.springframework.core.io.support.SpringFactoriesLoader
65+
* @deprecated since 3.5, replacement {@link org.springframework.data.jdbc.core.dialect.DialectResolver} was moved to
66+
* the {@link org.springframework.data.jdbc.core.dialect} package.
67+
*/
68+
@Deprecated(since = "3.5", forRemoval = true)
69+
public interface JdbcDialectProvider
70+
extends org.springframework.data.jdbc.core.dialect.DialectResolver.JdbcDialectProvider {
71+
72+
/**
73+
* Returns a {@link Dialect} for a {@link DataSource}.
74+
*
75+
* @param operations the {@link JdbcOperations} to be used with the {@link Dialect}.
76+
* @return {@link Optional} containing the {@link Dialect} if the {@link JdbcDialectProvider} can provide a dialect
77+
* object, otherwise {@link Optional#empty()}.
78+
*/
79+
Optional<Dialect> getDialect(JdbcOperations operations);
80+
}
81+
82+
@Deprecated(since = "3.5", forRemoval = true)
83+
static public class DefaultDialectProvider extends
84+
org.springframework.data.jdbc.core.dialect.DialectResolver.DefaultDialectProvider implements JdbcDialectProvider {
85+
86+
}
87+
88+
/**
89+
* Exception thrown when {@link DialectResolver} cannot resolve a {@link Dialect}.
90+
*/
91+
@Deprecated(since = "3.5", forRemoval = true)
92+
public static class NoDialectException
93+
extends org.springframework.data.jdbc.core.dialect.DialectResolver.NoDialectException {
94+
95+
/**
96+
* Constructor for NoDialectFoundException.
97+
*
98+
* @param msg the detail message
99+
*/
100+
NoDialectException(String msg) {
101+
super(msg);
102+
}
103+
}
104+
105+
}

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/AbstractJdbcConfiguration.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.springframework.data.jdbc.core.dialect.JdbcDialect;
4242
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
4343
import org.springframework.data.jdbc.core.mapping.JdbcSimpleTypes;
44+
import org.springframework.data.jdbc.dialect.DialectResolver;
4445
import org.springframework.data.mapping.model.SimpleTypeHolder;
4546
import org.springframework.data.relational.RelationalManagedTypes;
4647
import org.springframework.data.relational.core.conversion.RelationalConverter;
@@ -65,6 +66,7 @@
6566
* @author Myeonghyeon Lee
6667
* @author Chirag Tailor
6768
* @author Mikhail Polivakha
69+
* @author Tomohiko Ozawa
6870
* @since 1.1
6971
*/
7072
@Configuration(proxyBeanMethods = false)
@@ -221,7 +223,7 @@ private List<Object> storeConverters(Dialect dialect) {
221223
public JdbcAggregateTemplate jdbcAggregateTemplate(ApplicationContext applicationContext,
222224
JdbcMappingContext mappingContext, JdbcConverter converter, DataAccessStrategy dataAccessStrategy) {
223225

224-
return new JdbcAggregateTemplate(applicationContext, mappingContext, converter, dataAccessStrategy);
226+
return new JdbcAggregateTemplate(applicationContext, converter, dataAccessStrategy);
225227
}
226228

227229
/**
@@ -249,8 +251,7 @@ public DataAccessStrategy dataAccessStrategyBean(NamedParameterJdbcOperations op
249251
* @param operations the {@link NamedParameterJdbcOperations} allowing access to a {@link java.sql.Connection}.
250252
* @return the {@link Dialect} to be used.
251253
* @since 2.0
252-
* @throws org.springframework.data.jdbc.repository.config.DialectResolver.NoDialectException if the {@link Dialect}
253-
* cannot be determined.
254+
* @throws DialectResolver.NoDialectException if the {@link Dialect} cannot be determined.
254255
*/
255256
@Bean
256257
public Dialect jdbcDialect(NamedParameterJdbcOperations operations) {

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/EnableJdbcRepositories.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,9 @@
131131
/**
132132
* Configures the name of the {@link org.springframework.data.jdbc.core.convert.DataAccessStrategy} bean definition to
133133
* be used to create repositories discovered through this annotation. Defaults to {@code defaultDataAccessStrategy}.
134+
* @deprecated since 3.3 use {@link #jdbcAggregateOperationsRef()} instead
134135
*/
136+
@Deprecated(since = "3.3")
135137
String dataAccessStrategyRef() default "";
136138

137139
/**
@@ -142,6 +144,12 @@
142144
*/
143145
String transactionManagerRef() default "transactionManager";
144146

147+
/**
148+
* Configure the name of the {@link org.springframework.data.jdbc.core.JdbcAggregateOperations} bean definition to be
149+
* used to create repositories discovered through this annotation.
150+
*/
151+
String jdbcAggregateOperationsRef() default "";
152+
145153
/**
146154
* Returns the key of the {@link QueryLookupStrategy} to be used for lookup queries for query methods. Defaults to
147155
* {@link QueryLookupStrategy.Key#CREATE_IF_NOT_FOUND}.

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/config/JdbcRepositoryConfigExtension.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
* @author Fei Dong
4141
* @author Mark Paluch
4242
* @author Antoine Sauray
43+
* @author Tomohiko Ozawa
4344
*/
4445
public class JdbcRepositoryConfigExtension extends RepositoryConfigurationExtensionSupport {
4546

@@ -79,9 +80,15 @@ public void postProcess(BeanDefinitionBuilder builder, RepositoryConfigurationSo
7980
Optional<String> transactionManagerRef = source.getAttribute("transactionManagerRef");
8081
builder.addPropertyValue("transactionManager", transactionManagerRef.orElse(DEFAULT_TRANSACTION_MANAGER_BEAN_NAME));
8182

82-
builder.addPropertyValue("mappingContext", new RuntimeBeanReference(JdbcMappingContext.class));
83-
builder.addPropertyValue("dialect", new RuntimeBeanReference(Dialect.class));
84-
builder.addPropertyValue("converter", new RuntimeBeanReference(JdbcConverter.class));
83+
Optional<String> jdbcAggregateOperationsRef = source.getAttribute("jdbcAggregateOperationsRef");
84+
85+
if (jdbcAggregateOperationsRef.isPresent()) {
86+
builder.addPropertyReference("jdbcAggregateOperations", jdbcAggregateOperationsRef.get());
87+
} else {
88+
builder.addPropertyValue("mappingContext", new RuntimeBeanReference(JdbcMappingContext.class));
89+
builder.addPropertyValue("dialect", new RuntimeBeanReference(Dialect.class));
90+
builder.addPropertyValue("converter", new RuntimeBeanReference(JdbcConverter.class));
91+
}
8592
}
8693

8794
/**

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactory.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@
1919

2020
import org.springframework.beans.factory.BeanFactory;
2121
import org.springframework.context.ApplicationEventPublisher;
22+
import org.springframework.data.jdbc.core.JdbcAggregateOperations;
2223
import org.springframework.data.jdbc.core.JdbcAggregateTemplate;
2324
import org.springframework.data.jdbc.core.convert.DataAccessStrategy;
2425
import org.springframework.data.jdbc.core.convert.JdbcConverter;
26+
import org.springframework.data.jdbc.dialect.DialectResolver;
2527
import org.springframework.data.jdbc.core.convert.QueryMappingConfiguration;
2628
import org.springframework.data.mapping.callback.EntityCallbacks;
2729
import org.springframework.data.relational.core.dialect.Dialect;
@@ -50,6 +52,7 @@
5052
* @author Diego Krupitza
5153
* @author Christopher Klein
5254
* @author Marcin Grzejszczak
55+
* @author Tomohiko Ozawa
5356
*/
5457
public class JdbcRepositoryFactory extends RepositoryFactorySupport {
5558

@@ -64,6 +67,20 @@ public class JdbcRepositoryFactory extends RepositoryFactorySupport {
6467
private QueryMappingConfiguration queryMappingConfiguration = QueryMappingConfiguration.EMPTY;
6568
private EntityCallbacks entityCallbacks;
6669

70+
public JdbcRepositoryFactory(ApplicationEventPublisher publisher, JdbcAggregateOperations jdbcAggregateOperations,
71+
NamedParameterJdbcOperations operations) {
72+
Assert.notNull(publisher, "ApplicationEventPublisher must not be null");
73+
Assert.notNull(jdbcAggregateOperations, "JdbcAggregateOperations must not be null");
74+
Assert.notNull(operations, "NamedParameterJdbcOperations must not be null");
75+
76+
this.converter = jdbcAggregateOperations.getConverter();
77+
this.accessStrategy = jdbcAggregateOperations.getDataAccessStrategy();
78+
this.context = jdbcAggregateOperations.getConverter().getMappingContext();
79+
this.dialect = DialectResolver.getDialect(operations.getJdbcOperations());
80+
this.operations = operations;
81+
this.publisher = publisher;
82+
}
83+
6784
/**
6885
* Creates a new {@link JdbcRepositoryFactory} for the given {@link DataAccessStrategy},
6986
* {@link RelationalMappingContext} and {@link ApplicationEventPublisher}.
@@ -115,7 +132,7 @@ public void setQueryMappingConfiguration(QueryMappingConfiguration queryMappingC
115132
@Override
116133
protected Object getTargetRepository(RepositoryInformation repositoryInformation) {
117134

118-
JdbcAggregateTemplate template = new JdbcAggregateTemplate(publisher, context, converter, accessStrategy);
135+
JdbcAggregateTemplate template = new JdbcAggregateTemplate(publisher, converter, accessStrategy);
119136

120137
if (entityCallbacks != null) {
121138
template.setEntityCallbacks(entityCallbacks);

0 commit comments

Comments
 (0)