Résumé : Le cadre de persistance actuel utilisé dans le projet est mybatis. Après analyse, il n'est pas difficile de constater que la configuration multi-sources de données doit résoudre deux problèmes. L'un consiste à passer de la méthode Spring Classic d'origine à la méthode Springboot. . Qu'en est-il de la configuration de plusieurs sources de données ? Y a-t-il eu beaucoup de changements ? L'autre est comment associer plusieurs sources de données à la configuration de mybatis ?
Récemment, en raison des besoins du projet, l'auteur s'est lancé dans un voyage de configuration de plusieurs sources de données Springboot. L'auteur a déjà configuré la commutation dynamique de sources multi-données de Spring, en utilisant le modèle JDBC à cette époque.
Le framework de persistance actuel utilisé dans le projet est mybatis. Après analyse, il n'est pas difficile de constater que la configuration multi-sources de données doit résoudre deux problèmes. L'un consiste à passer de la méthode classique originale de Spring à la méthode classique. la méthode springboot. Plusieurs sources de données Comment configurer ? Y a-t-il eu beaucoup de changements ? L'autre est comment associer plusieurs sources de données à la configuration de mybatis ?
Voyons d'abord comment configurer mybatis sous une seule source de données ?
Tout d'abord, permettez-moi de déclarer que lorsque le projet ne repose que sur une seule source de données, si cela ne vous dérange pas que Springboot fasse les choses pour vous, alors félicitations, vous évitez les ennuis ! Il vous suffit d'ajouter la configuration de propriété appropriée de la source de données dans le fichier de propriétés du projet, et Springboot vous fournira une source de données "gratuitement". La valeur par défaut est le pool de connexions Tomcat JDBC.
Bien sûr, vous pouvez refuser la gentillesse de Springboot. Si vous comptez sur une technologie de pool de connexions tierce, vous pouvez configurer votre propre source de données. Springboot ne configurera alors pas automatiquement la source de données après avoir détecté que vous avez défini la DataSource. toi-même. .
L'auteur ne pouvait pas refuser la gentillesse de Springboot, j'ai donc seulement ajouté les propriétés suivantes au application.properties du projet :
spring.datasource.url=jdbc:mysql://localhost:3306/test spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.max-idle=10 spring.datasource.max-wait=10000 spring.datasource.min-idle=5 spring.datasource.initial-size=5 spring.datasource.validation-query=SELECT 1 spring.datasource.test-on-borrow=false spring.datasource.test-while-idle=true spring.datasource.time-between-eviction-runs-millis=18800 然后笔者创建了一个专门用于配置mybatis的类,如下: @Configuration public class MybatisSpringConfig { @Bean(name = "sqlSessionFactory") public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); factoryBean.setDataSource(dataSource); factoryBean.setTypeAliasesPackage("demo.model"); return factoryBean.getObject(); } [[[@Bean](http://my.oschina.net/bean)](http://my.oschina.net/bean)](http://my.oschina.net/bean) public MapperScannerConfigurer mapperScannerConfigurer() { MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); mapperScannerConfigurer.setBasePackage("demo.repository"); return mapperScannerConfigurer; } }
Oui, mybatis peut fonctionner normalement au printemps grâce à une configuration aussi simple. Vous n'avez pas besoin de créer délibérément le fichier de configuration de mybatis, d'enregistrer l'interface du mappeur et de spécifier l'emplacement du fichier XML correspondant. Cela est entièrement dû à mybatis-spring, qui est comme une "colle" qui peut facilement Mybatis et spring. sont « collés » ensemble.
Étapes de configuration de MyBatis-Spring
Voulez-vous d'abord parler des étapes générales de la configuration de mybatis-spring :
Configurer le Bean du source de données Source de données.
Configurez le gestionnaire de transactions à l'aide de DataSource.
Utilisez DataSource pour configurer le Bean de SqlSessionFactory.
Configurez le bean de MapperScannerConfigurer.
Ici, il est requis que la source de données du gestionnaire de transactions configuré et de SqlSessionFactory soit la même, sinon la gestion des transactions ne fonctionnera pas. Le but de la configuration de MapperScannerConfigurer est d'analyser automatiquement le package où se trouve l'interface du mappeur et de vous aider automatiquement à enregistrer l'interface du mappeur en tant que Bean (la classe d'implémentation de l'interface générée par l'agent), afin que vous puissiez l'utiliser directement pour les dépendances. injection. Il est recommandé que l'interface du mappeur et ses fichiers XML correspondants soient placés sous le même package, vous n'avez donc pas besoin de spécifier l'emplacement du fichier XML dans SqlSessionFactory.
OK, par rapport au contenu de configuration que j'ai posté ci-dessus, vous découvrirez peut-être pourquoi j'ai raté quelques étapes ? Grâce à springboot, parce qu'il configure automatiquement une DataSource, il configure également automatiquement un gestionnaire de transactions. L'auteur a donc uniquement configuré SqlSessionFactory et MapperScannerConfigurer.
Bien sûr, si vous insistez toujours pour configurer votre propre source de données après avoir vu cela, reportez-vous aux instructions de configuration multi-sources de données ci-dessous et extrayez l'une des multiples sources de données pour réaliser la configuration personnalisée d'une seule source de données. .
Après l'exemple de source de données unique ci-dessus, on peut dire que lorsque nous passons à Springboot pour écrire du code, Springboot nous apporte une grande commodité, et cela n'affecte pas non plus notre personnalisation, donc l'auteur pense que quelle que soit la configuration de Spring que vous utilisez avant d'utiliser Springboot, après avoir utilisé Springboot, il n'y aura aucun obstacle, et ce sera encore plus rapide qu'avant !
Parlons brièvement des scénarios qui nécessitent plusieurs sources de données. L'auteur s'est référé à d'autres articles et a constaté que la plupart des besoins proviennent de la méthode maître-esclave de la base de données ou de la séparation lecture-écriture. Puis selon les deux sources de données maître et esclave, publiez directement la classe de configuration de la source de données.
application.properties
datasource.master.url=jdbc:mysql://localhost:3306/master datasource.master.username=root datasource.master.password=root datasource.master.driver-class-name=com.mysql.jdbc.Driver datasource.master.max-idle=10 datasource.master.max-wait=10000 datasource.master.min-idle=5 datasource.master.initial-size=5 datasource.master.validation-query=SELECT 1 datasource.master.test-on-borrow=false datasource.master.test-while-idle=true datasource.master.time-between-eviction-runs-millis=18800 datasource.slave.url=jdbc:mysql://localhost:3306/slave datasource.slave.username=root datasource.slave.password=root datasource.slave.driver-class-name=com.mysql.jdbc.Driver datasource.slave.max-idle=10 datasource.slave.max-wait=10000 datasource.slave.min-idle=5 datasource.slave.initial-size=5 datasource.slave.validation-query=SELECT 1 datasource.slave.test-on-borrow=false datasource.slave.test-while-idle=true datasource.slave.time-between-eviction-runs-millis=18800
source de données principale
@Configuration public class MasterConfig { [[[@Primary](http://my.oschina.net/primary)](http://my.oschina.net/primary)](http://my.oschina.net/primary) @Bean(name = "masterDataSource") @ConfigurationProperties(prefix = "datasource.master") public DataSource dataSource() { return DataSourceBuilder.create().build(); }
@Primary @Bean(name = "masterTransactionManager") public DataSourceTransactionManager transactionManager(@Qualifier("masterDataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } }
source de données esclave
@Configuration public class SlaveConfig { @Bean(name = "slaveDataSource") @ConfigurationProperties(prefix = "datasource.slave") public DataSource dataSource() { return DataSourceBuilder.create().build(){ } @Bean(name = "slaveTransactionManager") public DataSourceTransactionManager transactionManager(@Qualifier("slaveDataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } }
Il n'est pas difficile de voir les étapes de configuration des deux sources de données :
Configurez les valeurs d'attribut nécessaires pour les deux sources de données dans le fichier de propriétés Pay. attention. Le nom du préfixe du point.
Créez des classes de configuration pour deux sources de données. Bien sûr, ce n'est pas une mauvaise idée si vous êtes prêt à les empiler dans une seule classe de configuration.
Dans la classe de configuration, configurez le Bean du DataSource. Pensez à lui donner un nom identifiable !
Configurez les gestionnaires de transactions correspondant aux deux sources de données Ne soyez pas trop gênant, sinon vous vous enterrerez dans un piège. Pensez à lui donner un nom identifiable !
配置DataSource时,利用@ConfigurationProperties(prefix = "xxx.xxx")可以依靠指定的前缀,在诸多的属性值中“挑选”出数据源依赖的属性,进而完成数据源的构建。
当自己定义了DataSource后,springboot就会取消自动配置的动作了。为了各司其职,为每个数据源配置各自的事务管理器,springboot自然也会取消自动配置事务管理器的动作。由于是多个数据源和多个事务管理器,都是一个类型的,你要是不起个区别的名字,任谁都分辨不出来吧?
@Primary 有什么作用呢?简单地说,当有两个同一类型的Bean,依赖注入时你没有指定name,正常情况下会报错,有两个你要的Bean,识别不了。但是 @Primary 相当于指定这个Bean为默认的,如果你没有指定name,就采用 @Primary 标识的Bean。
OK,两个数据源的配置配好了,还需要配置各自的Mybatis来进行持久化的操作。
MyBatis-Spring相关配置
mybatis for master
@Configuration @MapperScan(basePackages = {"demo.repository.master"}, sqlSessionFactoryRef = "masterSqlSessionFactory") public class MasterConfig { @Primary @Bean(name = "masterDataSource") @ConfigurationProperties(prefix = "datasource.master") public DataSource dataSource() { return DataSourceBuilder.create().build(); } @Primary @Bean(name = "masterTransactionManager") public DataSourceTransactionManager transactionManager(@Qualifier("masterDataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Primary @Bean(name = "masterSqlSessionFactory") public SqlSessionFactory sqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource) throws Exception { SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); factoryBean.setDataSource(dataSource); factoryBean.setTypeAliasesPackage("demo.model"); return factoryBean.getObject(); } }
mybatis for slave
@Configuration @MapperScan(basePackages = {"demo.repository.slave"}, sqlSessionFactoryRef = "slaveSqlSessionFactory") public class SlaveConfig { @Bean(name = "slaveDataSource") @ConfigurationProperties(prefix = "datasource.slave") public DataSource dataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "slaveTransactionManager") public DataSourceTransactionManager transactionManager(@Qualifier("slaveDataSource") DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Bean(name = "slaveSqlSessionFactory") public SqlSessionFactory basicSqlSessionFactory(@Qualifier("slaveDataSource") DataSource basicDataSource) throws Exception { SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean(); factoryBean.setDataSource(basicDataSource); factoryBean.setTypeAliasesPackage("demo.model"); return factoryBean.getObject(); } }
这里需要强调几个地方:
细心人会发现上面的配置类中,少了MapperScannerConfigurer的Bean配置,改用了@MapperScan注解。其实两者的作用是一样的,但是@MapperScan比较新,稍后会做解释为什么它比较新。
由于两个数据源的原因,引出了两套SqlSessionFactory的配置,所以@MapperScan中需要指明依赖的是哪个SqlSessionFactory,“sqlSessionFactoryRef”对应就是SqlSessionFactory的name属性。
@MapperScan会将扫描的mapper接口代理生成实现类,并自动注册为Bean。由于两个数据源的配置类中都有@MapperScan注解,为了避免造成冲突和排错时的困扰,猛烈提醒,两个数据源的配置,mybatis对应的mapper接口及对应xml文件也构建两套,最好接口名上也做些区分。model类使用同一套倒是没什么影响。所以你会看到上面的配置中,@MapperScan中basePackages指向的是两个包路径。
好了,来解释下@MapperScan为何比较新,并且笔者推荐使用@MapperScan。
首先@MapperScan要求的mybatis-spring版本比较新,说明它是新推出的特性。
其次@MapperScan要比配置MapperScannerConfigurer的Bean要简练的多,代码量上就看得出来。
最后,@MapperScan中的basePackageClasses属性是MapperScannerConfigurer所没有的。并且笔者用到了这个basePackageClasses属性,所以这里强力推荐使用@MapperScan注解。
多聊一些,描述下笔者为何会用到@MapperScan中的basePackageClasses属性吧,况且与上述示例中的basePackages有何区别呢?
上面提到了多数据源的一般场景,笔者的不同。笔者的项目中划分了n个子模块,每个子模块有各自的数据库,现在需要每个子模块共享一个公共信息的数据库。
从代码上来说,由于各个子模块依赖的公共信息数据库-数据源、mapper接口和xml映射文件是相同的,笔者希望将这些类和文件抽离到maven的一个公共module(最后会打包为一个jar文件)中,供其他n个子模块依赖使用,这样可以避免重复代码嘛。
笔者这么做之后,发现配置MapperScannerConfigurer的basePackages找不到mapper接口所在的包路径,因为笔者是在子模块中配置的MapperScannerConfigurer,它自然会在子模块的结构中去寻找指定的包路径,是mapper接口被笔者放到了公共的module中,所以是找不到的!
不过还好在@MapperScan中发现了basePackageClasses属性,它会“接受”你指定的mapper接口的全名。再次提醒,记得把xml映射文件和mapper接口放在一起,mybatis-spring会帮你做关联。
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!