DATAJDBC-155 - Simplified construction of JdbcRepositoryFactory.

Made the DefaultDataAccessStrategy actually the default for JdbcRepositoryFactoryBean.
Therefore the injection of a strategy is optional.

Simplified constructors of DefaultDataAccessStrategy.
Created factory method to construct a correct DataAccessStrategy for use with MyBatis.

Did some untangling in the test application context configurations.

Original pull request: #54.
This commit is contained in:
Jens Schauder
2018-03-23 08:45:32 +01:00
committed by Christoph Strobl
parent ce020a403e
commit aaae9a5f5c
8 changed files with 77 additions and 46 deletions

View File

@@ -56,11 +56,11 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
private final JdbcMappingContext context;
private final DataAccessStrategy accessStrategy;
public DefaultDataAccessStrategy(SqlGeneratorSource sqlGeneratorSource, NamedParameterJdbcOperations operations,
JdbcMappingContext context, DataAccessStrategy accessStrategy) {
public DefaultDataAccessStrategy(SqlGeneratorSource sqlGeneratorSource, JdbcMappingContext context,
DataAccessStrategy accessStrategy) {
this.sqlGeneratorSource = sqlGeneratorSource;
this.operations = operations;
this.operations = context.getTemplate();
this.context = context;
this.accessStrategy = accessStrategy;
}
@@ -69,11 +69,10 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
* Creates a {@link DefaultDataAccessStrategy} which references it self for resolution of recursive data accesses.
* Only suitable if this is the only access strategy in use.
*/
public DefaultDataAccessStrategy(SqlGeneratorSource sqlGeneratorSource, NamedParameterJdbcOperations operations,
JdbcMappingContext context) {
public DefaultDataAccessStrategy(SqlGeneratorSource sqlGeneratorSource, JdbcMappingContext context) {
this.sqlGeneratorSource = sqlGeneratorSource;
this.operations = operations;
this.operations = context.getTemplate();
this.context = context;
this.accessStrategy = this;
}

View File

@@ -15,15 +15,22 @@
*/
package org.springframework.data.jdbc.mybatis;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.data.jdbc.core.DataAccessStrategy;
import org.springframework.data.jdbc.mapping.model.JdbcPersistentProperty;
import org.springframework.data.mapping.PropertyPath;
import static java.util.Arrays.*;
import java.util.Collections;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.data.jdbc.core.CascadingDataAccessStrategy;
import org.springframework.data.jdbc.core.DataAccessStrategy;
import org.springframework.data.jdbc.core.DefaultDataAccessStrategy;
import org.springframework.data.jdbc.core.DelegatingDataAccessStrategy;
import org.springframework.data.jdbc.core.SqlGeneratorSource;
import org.springframework.data.jdbc.mapping.model.JdbcMappingContext;
import org.springframework.data.jdbc.mapping.model.JdbcPersistentProperty;
import org.springframework.data.mapping.PropertyPath;
/**
* {@link DataAccessStrategy} implementation based on MyBatis. Each method gets mapped to a statement. The name of the
* statement gets constructed as follows: The namespace is based on the class of the entity plus the suffix "Mapper".
@@ -41,11 +48,43 @@ public class MyBatisDataAccessStrategy implements DataAccessStrategy {
private final SqlSession sqlSession;
/**
* Create a {@link DataAccessStrategy} that first checks for queries defined by MyBatis and if it doesn't find one
* used a {@link DefaultDataAccessStrategy}
*
* @param context
* @param sqlSession
* @return
*/
public static DataAccessStrategy createCombinedAccessStrategy(JdbcMappingContext context, SqlSession sqlSession) {
// the DefaultDataAccessStrategy needs a reference to the returned DataAccessStrategy. This creates a dependency
// cycle. In order to create it, we need something that allows to defer closing the cycle until all the elements are
// created. That is the purpose of the DelegatingAccessStrategy.
DelegatingDataAccessStrategy delegatingDataAccessStrategy = new DelegatingDataAccessStrategy();
MyBatisDataAccessStrategy myBatisDataAccessStrategy = new MyBatisDataAccessStrategy(sqlSession);
CascadingDataAccessStrategy cascadingDataAccessStrategy = new CascadingDataAccessStrategy(
asList(myBatisDataAccessStrategy, delegatingDataAccessStrategy));
DefaultDataAccessStrategy defaultDataAccessStrategy = new DefaultDataAccessStrategy( //
new SqlGeneratorSource(context), //
context, //
cascadingDataAccessStrategy);
delegatingDataAccessStrategy.setDelegate(defaultDataAccessStrategy);
return cascadingDataAccessStrategy;
}
/**
* Constructs a {@link DataAccessStrategy} based on MyBatis.
* <p>
* Use a {@link SqlSessionTemplate} for {@link SqlSession} or a similar implementation tying the session to the
* proper transaction.
* Use a {@link SqlSessionTemplate} for {@link SqlSession} or a similar implementation tying the session to the proper
* transaction. Note that the resulting {@link DataAccessStrategy} only handles MyBatis. It does not include the
* functionality of the {@link org.springframework.data.jdbc.core.DefaultDataAccessStrategy} which one normally still
* wants. Use {@link #createCombinedAccessStrategy(JdbcMappingContext, SqlSession)} to create such a
* {@link DataAccessStrategy}.
*
* @param sqlSession Must be non {@literal null}.
*/

View File

@@ -22,18 +22,20 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.data.jdbc.mapping.model.ConversionCustomizer;
import org.springframework.data.jdbc.mapping.model.JdbcMappingContext;
import org.springframework.data.jdbc.mapping.model.NamingStrategy;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
/**
* Beans that must be registered for Spring Data JDBC to work.
*
* @author Greg Turnquist
* @author Jens Schauder
*/
@Configuration
public class JdbcConfiguration {
@Bean
JdbcMappingContext jdbcMappingContext(NamedParameterJdbcTemplate template, Optional<NamingStrategy> namingStrategy,
JdbcMappingContext jdbcMappingContext(NamedParameterJdbcOperations template, Optional<NamingStrategy> namingStrategy,
Optional<ConversionCustomizer> conversionCustomizer) {
return new JdbcMappingContext(namingStrategy.orElse(NamingStrategy.INSTANCE), template,

View File

@@ -21,6 +21,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.data.jdbc.core.DataAccessStrategy;
import org.springframework.data.jdbc.core.DefaultDataAccessStrategy;
import org.springframework.data.jdbc.core.SqlGeneratorSource;
import org.springframework.data.jdbc.mapping.model.JdbcMappingContext;
import org.springframework.data.jdbc.repository.RowMapperMap;
import org.springframework.data.repository.Repository;
@@ -80,7 +82,7 @@ public class JdbcRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extend
this.mappingContext = mappingContext;
}
@Autowired
@Autowired(required = false)
public void setDataAccessStrategy(DataAccessStrategy dataAccessStrategy) {
this.dataAccessStrategy = dataAccessStrategy;
}
@@ -93,8 +95,15 @@ public class JdbcRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extend
@Override
public void afterPropertiesSet() {
Assert.notNull(this.dataAccessStrategy, "DataAccessStrategy must not be null!");
Assert.notNull(this.mappingContext, "MappingContext must not be null!");
if (dataAccessStrategy == null) {
dataAccessStrategy = new DefaultDataAccessStrategy( //
new SqlGeneratorSource(mappingContext), //
mappingContext);
}
super.afterPropertiesSet();
}
}