1. Обзор
Spring Boot использует самоуверенный алгоритм для сканирования и настройки DataSource
. Это позволяет нам легко получить полностью настроенную реализацию DataSource
по умолчанию.
Кроме того, Spring Boot автоматически настраивает молниеносный пул соединений , либо HikariCP , Apache Tomcat , либо Commons DBCP , именно в таком порядке, в зависимости от того, какие из них находятся в пути к классам.
Хотя автоматическая настройка DataSource
Spring Boot в большинстве случаев работает очень хорошо, иногда нам потребуется более высокий уровень контроля , поэтому нам придется настроить собственную реализацию DataSource
, поэтому процесс автоматической настройки пропускается.
В этом руководстве мы узнаем , как программно настроить DataSource
в Spring Boot .
2. Зависимости Maven
Программное создание реализации DataSource
в целом несложно .
Чтобы узнать, как это сделать, мы реализуем простой слой репозитория, который будет выполнять операции CRUD над некоторыми объектами JPA .
Давайте посмотрим на зависимости нашего демонстрационного проекта:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.4.1</version>
<scope>runtime</scope>
</dependency>
Как показано выше, мы будем использовать экземпляр базы данных H2 в памяти для проверки уровня репозитория. При этом мы сможем протестировать наш программно настроенный источник данных
без затрат на выполнение дорогостоящих операций с базой данных.
Кроме того, давайте обязательно проверим последнюю версию spring-boot-starter-data-jpa
на Maven Central.
3. Программная настройка источника данных
Теперь, если мы будем придерживаться автоматической конфигурации DataSource
Spring Boot и запустим наш проект в его текущем состоянии, он будет работать так, как ожидалось.
Spring Boot сделает за нас всю тяжелую инфраструктуру. Это включает в себя создание реализации H2 DataSource
, которая будет автоматически обрабатываться HikariCP, Apache Tomcat или Commons DBCP, а также настройку экземпляра базы данных в памяти.
Кроме того, нам даже не нужно создавать файл application.properties
, поскольку Spring Boot также предоставит некоторые настройки базы данных по умолчанию.
Как мы упоминали ранее, иногда нам потребуется более высокий уровень настройки, поэтому нам придется программно настроить нашу собственную реализацию DataSource
.
Самый простой способ добиться этого — определить фабричный метод DataSource
и поместить его в класс, аннотированный аннотацией @Configuration
:
@Configuration
public class DataSourceConfig {
@Bean
public DataSource getDataSource() {
DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
dataSourceBuilder.driverClassName("org.h2.Driver");
dataSourceBuilder.url("jdbc:h2:mem:test");
dataSourceBuilder.username("SA");
dataSourceBuilder.password("");
return dataSourceBuilder.build();
}
}
В этом случае мы использовали удобный класс DataSourceBuilder
, негибкую версию шаблона построителя Джошуа Блоха , для программного создания нашего пользовательского объекта DataSource
.
Этот подход действительно удобен, потому что построитель упрощает настройку источника данных
с использованием некоторых общих свойств. Он также использует базовый пул соединений.
4. Экстернализация конфигурации источника
данных с помощью файла application.properties
Конечно, также возможно частично внедрить нашу конфигурацию DataSource .
Например, мы могли бы определить некоторые базовые свойства DataSource
в нашем фабричном методе:
@Bean
public DataSource getDataSource() {
DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
dataSourceBuilder.username("SA");
dataSourceBuilder.password("");
return dataSourceBuilder.build();
}
Затем мы можем указать несколько дополнительных в файле application.properties :
spring.datasource.url=jdbc:h2:mem:test
spring.datasource.driver-class-name=org.h2.Driver
Свойства, определенные во внешнем источнике, таком как указанный выше файл application.properties
, или через класс с аннотацией @ConfigurationProperties
, переопределяют свойства, определенные в Java API.
Становится очевидным, что при таком подходе мы больше не будем хранить настройки конфигурации DataSource
в одном месте .
С другой стороны, это позволяет нам отделить настройки времени компиляции и времени выполнения друг от друга.
Это действительно хорошо, так как позволяет нам легко установить точку привязки конфигурации. Таким образом, мы можем включать различные настройки DataSource
из других источников без необходимости рефакторинга методов нашей фабрики компонентов.
5. Тестирование конфигурации источника
данных
Тестировать нашу пользовательскую конфигурацию DataSource
очень просто. Весь процесс сводится к созданию объекта JPA , определению базового интерфейса репозитория и тестированию уровня репозитория.
5.1. Создание объекта JPA
Давайте начнем с определения нашего примера класса сущности JPA, который будет моделировать пользователей:
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
private String email;
// standard constructors / setters / getters / toString
}
5.2. Простой слой репозитория
Далее нам нужно реализовать базовый уровень репозитория, который позволяет нам выполнять операции CRUD над экземплярами класса сущностей User
, определенного выше.
Поскольку мы используем Spring Data JPA , нам не нужно создавать собственную реализацию DAO с нуля. Нам просто нужно расширить интерфейс CrudRepository
, чтобы получить работающую реализацию репозитория:
@Repository
public interface UserRepository extends CrudRepository<User, Long> {}
5.3. Тестирование слоя репозитория
Наконец, нам нужно проверить, действительно ли работает наш программно настроенный источник данных.
Мы можем легко выполнить это с помощью интеграционного теста:
@RunWith(SpringRunner.class)
@DataJpaTest
public class UserRepositoryIntegrationTest {
@Autowired
private UserRepository userRepository;
@Test
public void whenCalledSave_thenCorrectNumberOfUsers() {
userRepository.save(new User("Bob", "bob@domain.com"));
List<User> users = (List<User>) userRepository.findAll();
assertThat(users.size()).isEqualTo(1);
}
}
Класс UserRepositoryIntegrationTest говорит
сам за себя. Он просто использует два метода CRUD интерфейса репозитория для сохранения и поиска сущностей.
Обратите внимание, что независимо от того, решим ли мы программно настроить нашу реализацию DataSource
или разбить ее на метод конфигурации Java и файл application.properties
, мы всегда должны получать работающее соединение с базой данных .
5.4. Запуск примера приложения
Наконец, мы можем запустить наше демонстрационное приложение, используя стандартный метод main() :
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public CommandLineRunner run(UserRepository userRepository) throws Exception {
return (String[] args) -> {
User user1 = new User("John", "john@domain.com");
User user2 = new User("Julie", "julie@domain.com");
userRepository.save(user1);
userRepository.save(user2);
userRepository.findAll().forEach(user -> System.out.println(user);
};
}
}
Мы уже протестировали слой репозитория, поэтому уверены, что наш DataSource
настроен успешно. Таким образом, если мы запустим пример приложения, мы должны увидеть в нашей консоли вывод списка сущностей пользователя , хранящихся в базе данных.
6. Заключение
В этой статье мы узнали, как программно настроить реализацию DataSource
в Spring Boot .
Как обычно, все примеры кода, показанные в этой статье, доступны на GitHub .