Получить несколько источников данных SpringBoot (1): стратегии с несколькими источниками

Spring Boot задняя часть

tags: multi-datasource java springboot


Одним предложением: при разработке Spring Boot подключение нескольких баз данных для операций чтения и записи с использованием нескольких наборов источников данных является наиболее прямым и простым способом.

1. Введение

В процессе разработки неизбежно одновременное использование нескольких баз данных.Обычные сценарии применения следующие:

  • Сценарии высокопроизводительных баз данных: ведущий-ведомый, включая один главный и один подчиненный, один главный и несколько подчиненных и т. д., операции добавления, удаления и изменения в главной базе данных и операции чтения в подчиненной базе данных.
  • Сценарий высокой доступности базы данных: главная/резервная, включая один к одному резервную, мультимастерную и мультирезервную и т. д., можно переключать, когда доступ к базе данных недоступен.
  • Бизнес-обработка однородных или разнородных данных: данные, подлежащие обработке, хранятся в разных базах данных, в том числе однородных (таких как MySQL) и разнородных (таких как одна MySQL, а PG или Oracle).

Как использовать Spring Boot для обработки чтения и записи нескольких баз данных, обычно существуют следующие стратегии:

  • Несколько наборов источников данных: то есть, чтобы установить набор логики обработки данных для базы данных, каждый набор баз данных включает конфигурацию источника данных, фабрику сеансов ( sessionFactory ), соединение, операцию SQL, сущность. Каждый набор баз данных независим друг от друга.
  • Динамические источники данных: определенное количество источников данных совместно используют фабрику сеансов, и источники данных динамически выбираются для подключения и операций SQL в соответствии с условиями.
  • Параметризованный источник данных изменения: добавьте источники данных в соответствии с параметрами и переключите источники данных, количество источников данных неизвестно. Обычно используется для управления несколькими базами данных.

В этой серии статей "Получение нескольких источников данных SpringBoot" будут описаны вышеуказанные стратегии. Эта статья является первой статьей: "Несколько источников данных", в которой в основном используется сценарий ведущий-подчиненный в качестве примера и комбинируется код для реализации реализации нескольких Источники данных Опишите, включая сборку проекта Spring Boot + MyBatis Plus, конфигурацию с несколькими источниками данных, обработку нескольких источников данных и логику использования.

в этой статьеобразец кода:https://github.com/mianshenglee/my-example/tree/master/multi-datasource, читатель может посмотреть его вместе.

2. Операционная среда

  • Операционная среда JAVA:JDK1.8
  • Spring Boot: 2.2.2.RELEASE
  • MyBatis Plus: 3.3.0
  • Среда разработки:IDEA
  • Инструмент сборки Maven:3.3.9
  • MySQL : 5.6.26
  • Lombok: 1.18.10

3. Несколько наборов источников данных

Несколько наборов источников данных, как следует из названия, каждая база данных имеет набор независимых операций. Снизу вверх база данных, фабрика сеансов, операция DAO и сервисный уровень — все это независимые наборы, как показано ниже:

多套数据源

В этом примере есть две базы данных, одна главная и одна подчиненная, в каждой из которых есть таблицаtest_user, структура таблицы одинаковая, для удобства пояснения данные в двух таблицах разные. Обе структуры таблиц доступны вобразец кодасерединаsqlполученный из справочника.

3.1 Создание проекта Spring Boot

3.1.1 Инициализация проекта Spring Boot

использоватьspring.ioЧтобы собрать начальный проект Spring Boot, выберите следующие компоненты:

  • Ломбок: используется для упрощения операций
  • Spring Configuration Processor: процессор файлов конфигурации
  • Spring Web: для создания веб-сервисов
  • Драйвер MySQL: драйвер базы данных

3.1.2 Добавление зависимости MyBatis Plus

MyBatis PlusЭто усовершенствование MyBatis, упрощающее операции DAO и повышающее эффективность операций с базой данных. Зависимости следующие:

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.3.0</version>
</dependency>

3.1.3 Добавить структуру пакета

В основном добавьте следующие пакеты:

├─config ---------------------------------- // 数据源配置
├─controller ------------------------------ // web服务
├─entity ---------------------------------- // 实体类
│ ├─master 
│ └─slave 
├─mapper ---------------------------------- // dao操作类
│ ├─master 
│ └─slave 
└─vo -------------------------------------- // 视图返回对象  

Примечание:

  • Опустите сервисный уровень из-за простоты примера.
  • Классы сущностей и мапперы делятся на главные и подчиненные.

3.2 Несколько наборов источников данных

3.2.1 Информация о подключении к независимой базе данных

Файл конфигурации по умолчанию для Spring Boot:application.properties, поскольку есть две конфигурации базы данных, рекомендуется настроить базу данных независимо, поэтому добавьте файл конфигурацииjbdc.properties, добавьте следующую пользовательскую конфигурацию базы данных master-slave:

# master
spring.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.master.jdbc-url=jdbc:mysql://localhost:3306/mytest?useSSL=false&serverTimezone=GMT%2B8&characterEncoding=UTF-8
spring.datasource.master.username=root
spring.datasource.master.password=111111

# slave
spring.datasource.slave.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.slave.jdbc-url=jdbc:mysql://localhost:3306/my_test1?useSSL=false&serverTimezone=GMT%2B8&characterEncoding=UTF-8
spring.datasource.slave.username=root
spring.datasource.slave.password=111111

3.2.2 Несколько наборов конфигурации источника данных

С информацией о подключении к источнику данных источник данных необходимо внедрить в Spring. Поскольку каждая база данных использует отдельный набор соединений с базой данных, соединение с базой данных используетSqlSessionустановить сеансовое соединение,SqlSessionОтSqlSessionFactoryгенерировать. Поэтому необходимо настроитьSqlSessionFactory. Следующие операцииconfigПод содержанием:

(1) ДобавитьDataSourceConfigФайл конфигурации, ввод источника данных master-slave

@Configuration
@PropertySource("classpath:config/jdbc.properties")
public class DatasourceConfig {
    @Bean("master")
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource masterDataSource(){
        return DataSourceBuilder.create().build();
    }

    @Bean("slave")
    @ConfigurationProperties(prefix = "spring.datasource.slave")
    public DataSource slaveDataSource(){
        return DataSourceBuilder.create().build();
    }
}
  • аннотацияPropertySourceУкажите файл с информацией о конфигурации
  • аннотацияConfigurationPropertiesУкажите префикс конфигурации master-slave
  • Укажите имена bean-компонентов главного и подчиненного источников данных соответственно какmaster,slave

(2) ДобавитьMasterMybatisConfigКонфигурационный файл, внедренный в мастерSqlSessionFactory

@Configuration
@MapperScan(basePackages = "me.mason.demo.basicmultidatasource.mapper.master", sqlSessionFactoryRef = "masterSqlSessionFactory")
public class MasterMybatisConfig {
    /**
     * 注意,此处需要使用MybatisSqlSessionFactoryBean,不是SqlSessionFactoryBean,
     * 否则,使用mybatis-plus的内置函数时就会报invalid bound statement (not found)异常
     */
    @Bean("masterSqlSessionFactory")
    public SqlSessionFactory masterSqlSessionFactory(@Qualifier("master") DataSource dataSource) throws Exception {
        // 设置数据源
        MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
        mybatisSqlSessionFactoryBean.setDataSource(dataSource);
        //mapper的xml文件位置
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        String locationPattern = "classpath*:/mapper/master/*.xml";
        mybatisSqlSessionFactoryBean.setMapperLocations(resolver.getResources(locationPattern));
        //对应数据库的entity位置
        String typeAliasesPackage = "me.mason.demo.basicmultidatasource.entity.master";
        mybatisSqlSessionFactoryBean.setTypeAliasesPackage(typeAliasesPackage);
        return mybatisSqlSessionFactoryBean.getObject();
    }
}
  • аннотацияMapperScanУкажите те, которые находятся под пакетомmapperИспользуйте этот источник данных и укажите, какой использоватьSqlSessionFactory, обратите внимание, что здесьsqlSessionFactoryRefТо есть инжектор в этой конфигурацииSqlSessionFactory.
  • Задает указанный источник данных, здесь именованныйmasterисточник данных, использованиеQualifierуказано.
  • Если у маппера, соответствующего MyBatis Plus, есть пользовательский mapper.xml, используйтеsetMapperLocationsуказано.
  • Если вам нужно псевдоним объекта, используйтеsetTypeAliasesPackageуказано.

(3) ДобавитьSlaveMybatisConfigФайл конфигурации, внедренный в SlaveSqlSessionFactory

В соответствии с (2), просто измените ведущее устройство на ведомое.

3.2.3 Несколько наборов сущностей

В конфигурации MyBatis параметры сущностиtypeAliasesКонфигурацию xml можно упростить, как упоминалось ранее, с помощьюtypeAliasesPackageУстановите путь объекта, вentityУстанавливается отдельно под пакетомmasterиslaveПакет хранит сущности таблицы, соответствующие двум библиотекам, и использует Lombok для упрощения операций с сущностями. следующее:

@Data
@TableName("test_user")
public class MasterTestUser implements Serializable {
    private static final long serialVersionUID = 1L;
    /** id */
    private Long id;
    /** 姓名 */
    private String name;
    ...
}

3.2.4 Несколько наборов операций Mapper

существуетmapperПод пакет добавить их отдельноmasterиslaveпакет, в котором хранится Mapper, соответствующий двум библиотекам.Поскольку сам MyBatis Plus уже содержит основные операции CRUD, во многих случаях его можно настроить без файлов xml. Если вам нужно настроить операцию, вам нужно объединить xml-файл, и при этом вам нужно указать каталог, в котором находится соответствующий xml-файл. следующее:

@Repository
public interface MasterTestUserMapper extends BaseMapper<MasterTestUser> {
    /**
     * 自定义查询
     * @param wrapper 条件构造器
     */
    List<MasterTestUser> selectAll(@Param(Constants.WRAPPER)Wrapper<MasterTestUser> wrapper);
}

Mapper, соответствующий ведомому, похож на этот

3.2.5 Несколько наборов XML-файлов картографа

Путь к XML-файлу Mapper по умолчанию MyBatis Plus:classpath*:/mapper/**/*.xml,Сейчасresources/mapper, и установите то же самоеmasterиslaveКаталог для хранения соответствующих XML-файлов преобразователя соответственно. Ниже приведены настраиваемые действия для мастера:

<mapper namespace="me.mason.demo.basicmultidatasource.mapper.master.MasterTestUserMapper">
    <select id="selectAll" resultType="masterTestUser">
        select * from test_user
        <if test="ew!=null">
          ${ew.customSqlSegment}
        </if>
    </select>
</mapper>

3.3 Использование нескольких источников данных

После приведенных выше нескольких наборов конфигураций источников данных вы можете узнать, с какой базой данных вам нужно работать, и вы можете напрямую использовать соответствующий преобразователь для выполнения операций CRUD. Ниже приведены две библиотеки, которые запрашиваются в контроллере по отдельности, и полученные данные возвращаются вместе:

@RestController
@RequestMapping("/user")
public class TestUserController {

    @Autowired
    private MasterTestUserMapper masterTestUserMapper;
    @Autowired
    private SlaveTestUserMapper slaveTestUserMapper;
    /**
     * 查询全部
     */
    @GetMapping("/listall")
    public Object listAll() {
        //master库,自定义接口查询
        QueryWrapper<MasterTestUser> queryWrapper = new QueryWrapper<>();
        List<MasterTestUser> resultData = masterTestUserMapper.selectAll(queryWrapper.isNotNull("name"));
        //slave库,mp内置接口
        List<SlaveTestUser> resultDataSlave = slaveTestUserMapper.selectList(null);
        //返回
        Map<String, Object> result = new HashMap<>();
        result.put("master" , resultData);
        result.put("slave" , resultDataSlave);
        return ResponseResult.success(result);
    }

}
  • Используйте аннотацию Autowired для внедрения соответствующего картографа.
  • Используйте маппер соответствующей базы данных для бизнес-операций
  • Выполнение соответствующих операций в базе данных в соответствии с бизнесом, например, только операции добавления, удаления и изменения в главном устройстве и операции только для чтения в подчиненном устройстве.

На данный момент реализация нескольких источников данных завершена.Текущий пример - две однородные базы данных.Конечно, если есть разнородные базы данных или более двух баз данных, метод обработки тот же, но источник данных увеличивается на 1. Просто набор.

4. Преимущества и недостатки

Из приведенного выше описания мы можем обобщить преимущества и недостатки использования нескольких наборов источников данных для операций с несколькими базами данных.

4.1 Преимущества

  • Просто и понятно: библиотека соответствует набору методов обработки, которые легко понять.
  • Соблюдайте принцип открытости-закрытости (OCP): схема разработки говорит нам, что она открыта для расширения, закрыта для модификации и добавляется еще одна база данных.Исходный набор не нужно менять, просто добавьте его.

4.2 Недостатки

  • Пустая трата ресурсов: Напишите набор операций для каждого источника данных, а ресурсы, подключенные к базе данных, также независимы, занимая такое же количество ресурсов.SqlSessionFactoryЭто фабрика. Рекомендуется использовать один экземпляр, который можно полностью использовать повторно. Нет необходимости создавать несколько экземпляров. Вам нужно только изменить источник данных. Это то же самое, что многопоточность и использование пулов потоков для снизить потребление ресурсов.
  • Избыточность кода: Как видно из предыдущей конфигурации с несколькими источниками данных, фактически многие операции ведущего и ведомого совпадают, но изменено имя, что вызовет избыточность кода.
  • Недостаток гибкости: Соответствующие мапперы нужно вводить во все места, которые нужно использовать.Для многих операций по-разному выбирается только источник данных, а логика кода непротиворечива. Кроме того, в случае одного главного и нескольких подчиненных относительно сложно выполнять балансировку нагрузки на несколько подчиненных библиотек.

Из-за вышеперечисленных недостатков есть еще возможности для улучшения. Итак, есть динамический источник данных.Что касается того, как реализовать динамический источник данных, он будет разбит в следующий раз.

5. Резюме

В этой статье проводится предварительное обсуждение работы с несколькими базами данных и объясняется стратегия использования нескольких наборов источников.В сочетании с примерами кода master-slave создается проект Spring Boot + MyBatis Plus, настраиваются несколько источников данных и Mapper используется для операций с несколькими источниками данных и, наконец, суммирует преимущества и недостатки нескольких наборов источников данных. Я надеюсь, что у вас может сложиться предварительное впечатление о работе с несколькими источниками данных.

Эта статья сопровождаетсяобразец кода, если вам интересно, вы можете запустить пример, чтобы почувствовать это.

использованная литература

Прошлые статьи

Мой официальный аккаунт (поискMason技术记录) для более технических записей:

mason