springboot获取datasource为null_spring-boot-start。。。
⼤部分 Java 应⽤都需要访问数据库,尤其是服务层,所以,SpringBoot 会为我们⾃动配置相应的数据访问设施。
若想 SpringBoot 为我们⾃动配置数据访问的基础设施,那么,我们需要直接或者间接地依赖 spring-jdbc,⼀旦 spring-jdbc 位于我们SpringBoot 应⽤的 classpath,即会触发数据访问相关的⾃动配置⾏为,最简单的做法就是把 spring-boot-starter-jdbc 加为应⽤的依赖。
默认情况下,如果我们没有配置任何 DataSource,那么,SpringBoot 会为我们⾃动配置⼀个基于嵌⼊式数据库的 DataSource,这种⾃动配置⾏为其实很适合于测试场景,但对实际的开发帮助不⼤,基本上我们会⾃⼰配置⼀个 DataSource 实例,或者通过⾃动配置模块提
供的配置参数对 DataSource 实例进⾏⾃定义的配置。
假设我们的 SpringBoot 应⽤只依赖⼀个数据库,那么,使⽤ DataSource ⾃动配置模块提供的配置参数是最⽅便的:
jdbctemplate查询一条数据spring.datasource.url=jdbc:mysql://{database host}:3306/{databaseName}spring.datasource.username={database username}spring.datasource.password
当然,⾃⼰配置⼀个 DataSource 也是可以的,SpringBoot 也会智能地选择我们⾃⼰配置的这个 DataSource 实例(只不过必要性真不⼤)。
除了 DataSource 会⾃动配置,SpringBoot 还会⾃动配置相应的 JdbcTemplate、DataSourceTransactionManager 等关联“设
施”,可谓服务周到,我们只要在使⽤的地⽅注⼊就可以了:
class SomeDao { @Autowired JdbcTemplate jdbcTemplate; public List queryForList(String sql){ // ... } // ...}
不过,spring-boot-starter-jdbc 以及与其相关的⾃动配置也不总是带来便利,在某些场景下,我们可能会在⼀个应⽤中需要依赖和访问多个数据库,这个时候就会出现问题了。
假设我们在 ApplicationContext 中配置了多个 DataSource 实例指向多个数据库:
@Beanpublic DataSource dataSource1() throws Throwable { DruidDataSource dataSource = new DruidDataSource(); dataSource.setUrl(...); dataSo 那么,不好意思,启动 SpringBoot 应⽤的时候会抛出类似如下的异常(Exception):
Exception):No qualifying bean of type [javax.sql.DataSource] is defined: expected single matching bean but found 2
为了避免这种情况的发⽣,我们需要在 SpringBoot 的启动类上做点⼉“⼿脚”:
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class })public class Unve
也就是说,我们需要在这种场景下排除掉对 SpringBoot 默认提供的 DataSource 相关的⾃动配置。但如果我们还是想要享受
SpringBoot 提供的⾃动配置 DataSource 的机能,也可以通过为其中⼀个 DataSource 配置添加
t.annotation.Primary 这个 Annotation 的⽅式以实现两全其美:
@Bean@Primarypublic DataSource dataSource1() throws Throwable { DruidDataSource dataSource = new DruidDataSource(); dataSource.setUrl(...);
另外,SpringBoot 还提供了很多其他数据访问相关的⾃动配置模块,⽐如 spring-boot-starter-data-jpa、spring-boot-starter-data-mongodb 等,⼤家可以根据⾃⼰数据访问的具体场景选择使⽤这些⾃动配置模块。
如果选择了 spring-boot-starter-data-jpa 等关系数据库相关的数据访问⾃动配置模块,并且还需要同时依赖访问多个数据库,那么,也
需要相应的在 SpringBoot 启动类中排除掉这些⾃动配置模块中的 AutoConfiguration 实现类(对应 spring-boot-starter-data-jpa 是JpaRepositoriesAutoConfiguration),或者标注某个 DataSource 为 @Primary。
SpringBoot 应⽤的数据库版本化管理
关于如何针对数据库的变更进⾏版本化管理,从 Ruby On Rails 的 migration ⽀持,到 Java 的 MyBatis Migrations,Flyway 以及Liquibase,都给出了相应的最佳实践建议和⽅案。
但是,数据库 migrations 的实践⽅式并没有在国内普遍应⽤起来,⼤部分都是靠⼈来解决,这或许可以⽤⼀句“成熟度不够”来解释,另外⼀个原因或许是职能明确分⼯后造成的局⾯。
如果仔细分析以上数据库 migration ⽅案就会发现,它们给出的应⽤场景和实践⼏乎都是单应⽤、单部署的,这在庞⼤单⼀部署单元(Monolith)的年代显然是很适合的,因为应⽤从开发到发布部署,再到启动,整个⽣命周期内,应⽤相关的所有“原材料”都集中在⼀起进⾏管理,⽽且国外开发者往往偏“特种作战”(Full-Stack Developer),⼀⾝多能,从⽽数据库 migration 这种实践⾃然可以成型并⼴泛应⽤。
但回到国内来看,我们往往是“集团军作战”,拼的是“⼤部队+明确分⼯”的模式,⽽且应⽤所⾯向的服务⼈数也往往更为庞⼤,所以,整个应⽤的交付链路上各个环节之间的衔接是不同的⼈,⽽应⽤最终部署的拓扑⼜往往是分布式部署居多,所以,在⼀个项⽬单元⾥维护数据库的 migration 脚本然后部署后启动前执⾏这些脚本就变得不合时宜了:
1)从职责上,这些 migration 脚本虽然⼤部分情况下都是开发⼈员写,但写完之后要不要进⾏ SQL 审查,是否符合规范,这些⼜会涉及应⽤运维 DBA。
代码管理系统对开发来说很亲切,对 DBA 来说则不尽然,⽽且 DBA 往往还要⼀⼈服务多个团队多个项⽬,从 DBA 的⾓度来说,他更愿意将 SQL 集中到⼀处进⾏管理,⽽不是分散在各个项⽬中。
2)应⽤分布式部署之后,就不单单是单⼀部署在应⽤启动的之前直接执⾏⼀次 migration 脚本那么简单了,你要执⾏多次,虽然
migration ⽅案都有版本控制,变更应该最终状态都是⼀样的,但这多个部署节点上都执⾏同⼀逻辑显然是多余的。
更复杂⼀点⼉,多个应⽤可能同时使⽤同⼀个数据库的情况,⼀个项⽬的数据库 migration 操作跟另⼀个项⽬的数据库 migration 操作会不会在互不知晓的情况下产⽣冲突和破坏?
所以,数据库 migration 的思路和实践很好,但不能照搬(任何事情其实皆如此),不过,我们可以结合现有的⼀些数据库 migration ⽅案,⽐如 flyway 或者 liquibase,我们可以对这些数据库 migration 的基础设施和⽀持外部化(Externalize),⼀个可能的架构如图 1 所⽰。
图 1 集中管控的数据库 Migration 架构⽰意图
在这个架构中,数据库 migration 的版本化管理剥离到了单独的管理系统,单⼀项⽬中不再保存完整历史的 migration 记录,⽽只需要提供当次发布要牵扯的数据库变更 SQL。
在项⽬发布的时候,由 DBA 进⾏统⼀的审查并纳⼊单独的数据库 migration 管理系统,由单独的数据库 migration 管理系统来管理完整的数据库 migration 记录,可以根据数据库的粒度进⾏管理和状态同步,从⽽既可以在开发阶段让开发⼈员可以集中管理数据库 SQL,⼜能在发布期间审查 SQL 并同步 migration 状态和完整的历史记录管理。
当然,这⼀切可以实现的前提是有⼀套完整的软件交付链路⽀撑平台,能够从流程上,软件⽣命周期管理上进⾏统⼀的治理和规范,后⾯教程中会跟⼤家做进⼀步深⼊的探讨。
不管怎么样,SpringBoot 还是为⼤家提供了针对 Flyway 和 Liquibase 的⾃动配置功能
(org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration 和
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration),对于单⼀开发和部署的应⽤来说,还是可以考虑的。
我是⼀个勤劳的⼩编,如果您觉得有帮助,请帮忙点赞+关注+转发吧~
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论