Browse Source

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.
pull/44/merge
Jens Schauder 8 years ago committed by Christoph Strobl
parent
commit
aaae9a5f5c
  1. 11
      src/main/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategy.java
  2. 49
      src/main/java/org/springframework/data/jdbc/mybatis/MyBatisDataAccessStrategy.java
  3. 4
      src/main/java/org/springframework/data/jdbc/repository/config/JdbcConfiguration.java
  4. 13
      src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBean.java
  5. 1
      src/test/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategyUnitTests.java
  6. 10
      src/test/java/org/springframework/data/jdbc/mybatis/MyBatisHsqlIntegrationTests.java
  7. 3
      src/test/java/org/springframework/data/jdbc/repository/SimpleJdbcRepositoryEventsUnitTests.java
  8. 28
      src/test/java/org/springframework/data/jdbc/testing/TestConfiguration.java

11
src/main/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategy.java

@ -56,11 +56,11 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy { @@ -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 { @@ -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;
}

49
src/main/java/org/springframework/data/jdbc/mybatis/MyBatisDataAccessStrategy.java

@ -15,15 +15,22 @@ @@ -15,15 +15,22 @@
*/
package org.springframework.data.jdbc.mybatis;
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;
import java.util.Collections;
import java.util.Map;
/**
* {@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 { @@ -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}.
*/

4
src/main/java/org/springframework/data/jdbc/repository/config/JdbcConfiguration.java

@ -22,18 +22,20 @@ import org.springframework.context.annotation.Configuration; @@ -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,

13
src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBean.java

@ -21,6 +21,8 @@ import org.springframework.beans.factory.annotation.Autowired; @@ -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 @@ -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 @@ -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();
}
}

1
src/test/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategyUnitTests.java

@ -48,7 +48,6 @@ public class DefaultDataAccessStrategyUnitTests { @@ -48,7 +48,6 @@ public class DefaultDataAccessStrategyUnitTests {
DefaultDataAccessStrategy accessStrategy = new DefaultDataAccessStrategy( //
new SqlGeneratorSource(context), //
jdbcOperations, //
context //
);

10
src/test/java/org/springframework/data/jdbc/mybatis/MyBatisHsqlIntegrationTests.java

@ -15,7 +15,7 @@ @@ -15,7 +15,7 @@
*/
package org.springframework.data.jdbc.mybatis;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.*;
import junit.framework.AssertionFailedError;
@ -30,6 +30,8 @@ import org.mybatis.spring.SqlSessionTemplate; @@ -30,6 +30,8 @@ import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.data.jdbc.core.DataAccessStrategy;
import org.springframework.data.jdbc.mapping.model.JdbcMappingContext;
import org.springframework.data.jdbc.repository.config.EnableJdbcRepositories;
import org.springframework.data.jdbc.testing.TestConfiguration;
import org.springframework.data.repository.CrudRepository;
@ -39,8 +41,6 @@ import org.springframework.test.context.junit4.rules.SpringClassRule; @@ -39,8 +41,6 @@ import org.springframework.test.context.junit4.rules.SpringClassRule;
import org.springframework.test.context.junit4.rules.SpringMethodRule;
import org.springframework.transaction.annotation.Transactional;
import javax.net.ssl.SSLSocketFactory;
/**
* Tests the integration with Mybatis.
*
@ -83,8 +83,8 @@ public class MyBatisHsqlIntegrationTests { @@ -83,8 +83,8 @@ public class MyBatisHsqlIntegrationTests {
}
@Bean
MyBatisDataAccessStrategy dataAccessStrategy(SqlSession sqlSession) {
return new MyBatisDataAccessStrategy(sqlSession);
DataAccessStrategy dataAccessStrategy(JdbcMappingContext context, SqlSession sqlSession) {
return MyBatisDataAccessStrategy.createCombinedAccessStrategy(context, sqlSession);
}
}

3
src/test/java/org/springframework/data/jdbc/repository/SimpleJdbcRepositoryEventsUnitTests.java

@ -46,13 +46,12 @@ public class SimpleJdbcRepositoryEventsUnitTests { @@ -46,13 +46,12 @@ public class SimpleJdbcRepositoryEventsUnitTests {
@Before
public void before() {
final JdbcMappingContext context = new JdbcMappingContext(mock(NamedParameterJdbcOperations.class));
final JdbcMappingContext context = new JdbcMappingContext(createIdGeneratingOperations());
JdbcRepositoryFactory factory = new JdbcRepositoryFactory( //
publisher, //
context, //
new DefaultDataAccessStrategy( //
new SqlGeneratorSource(context), //
createIdGeneratingOperations(), //
context //
) //
);

28
src/test/java/org/springframework/data/jdbc/testing/TestConfiguration.java

@ -21,14 +21,12 @@ import javax.sql.DataSource; @@ -21,14 +21,12 @@ import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
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.ConversionCustomizer;
import org.springframework.data.jdbc.mapping.model.JdbcMappingContext;
@ -54,24 +52,21 @@ public class TestConfiguration { @@ -54,24 +52,21 @@ public class TestConfiguration {
@Autowired(required = false) SqlSessionFactory sqlSessionFactory;
@Bean
JdbcRepositoryFactory jdbcRepositoryFactory() {
JdbcRepositoryFactory jdbcRepositoryFactory(DataAccessStrategy dataAccessStrategy) {
NamedParameterJdbcTemplate jdbcTemplate = namedParameterJdbcTemplate();
NamedParameterJdbcOperations jdbcTemplate = namedParameterJdbcTemplate();
final JdbcMappingContext context = new JdbcMappingContext(NamingStrategy.INSTANCE, jdbcTemplate, __ -> {});
return new JdbcRepositoryFactory( //
publisher, //
context, //
new DefaultDataAccessStrategy( //
new SqlGeneratorSource(context), //
jdbcTemplate, //
context) //
dataAccessStrategy //
);
}
@Bean
NamedParameterJdbcTemplate namedParameterJdbcTemplate() {
NamedParameterJdbcOperations namedParameterJdbcTemplate() {
return new NamedParameterJdbcTemplate(dataSource);
}
@ -81,19 +76,8 @@ public class TestConfiguration { @@ -81,19 +76,8 @@ public class TestConfiguration {
}
@Bean
DataAccessStrategy defaultDataAccessStrategy(JdbcMappingContext context,
@Qualifier("namedParameterJdbcTemplate") NamedParameterJdbcOperations operations) {
DelegatingDataAccessStrategy accessStrategy = new DelegatingDataAccessStrategy();
accessStrategy.setDelegate(new DefaultDataAccessStrategy( //
new SqlGeneratorSource(context), //
operations, //
context, //
accessStrategy) //
);
return accessStrategy;
DataAccessStrategy defaultDataAccessStrategy(JdbcMappingContext context) {
return new DefaultDataAccessStrategy(new SqlGeneratorSource(context), context);
}
@Bean

Loading…
Cancel
Save