java同时配置多个数据库的完整步骤
作者:广煜永不挂科
环境:springboot(没有mybatis,有其实也无所谓。)
1、链接数据库的配置
首先是,在只配置一个数据库,我们需要在springboot的application.properties进行如下配置
# 数据源配置 spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver spring.datasource.url=jdbc:sqlserver://目标IP:1433;databaseName=ZCFW-SC;encrypt=false;trustServerCertificate=true spring.datasource.username=用户名 spring.datasource.password=密码
当运行时,springboot会以spring.datasource为根去寻找数据库链接所需的地址,用户名和密码。因为只有一个数据库,我们不需要为“连接配置”额外命名。
2、链接多个数据库——命名
当只有一个数据库,我们不需要为“连接配置”额外命名,而当数据库变多时,我们就需要为不同的“连接配置”额外命名了。
好比是家里有个一个孩子,吃饭时只需要“孩儿,过来吃饭了”
但是有两个孩子,就需要“大娃二娃过来吃饭了”
所以有一下:
# 数据源1配置 spring.datasource.db1.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver spring.datasource.db1.jdbc-url=jdbc:sqlserver://目标IP:1433;databaseName=ZCFW-SC; spring.datasource.db1.username=sa spring.datasource.db1.password=12345678 # 其他配置... # 数据源2配置 spring.datasource.db2.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver spring.datasource.db2.jdbc-url=jdbc:sqlserver://目标IP:3306;databaseName=pdmvpdb; spring.datasource.db2.username=newuser spring.datasource.db2.password=123123 # 其他配置...
其中db1和db2就是我们为区分不同数据库连接配置进行的命名。
当只连接一个数据库的时候,我们写的是“spring.datasource.url”其实他真正的写法应该是spring.datasource.*.url,其中的* 就是系统自动给数据库连接分配的默认名,这个默认名在我们需要链接多个数据库时就不能用了,因为不知道你叫的谁。
3、链接多个数据库——识别
我们知道db1和db2是我们为区分不同数据库连接配置而进行的命名,但是别人不知道。
就好像我们知道“大娃二娃”是我们的孩子,但是邻居不知道哪个是大娃哪个是二娃,我们就需要和他们解释。红肚兜的是大娃,绿肚兜的时二娃。
所以还需要让代码在运行时可以识别区分不同的数据库连接。
我们需要一个java配置文件,来让系统知道我们说的db1和db2是谁。
①、命名
我们为数据源命名的这个方法共分为三部分:
其中的 @ConfigurationProperties(prefix = "spring.datasource.db1") 是告诉程序,我们要给db1这个链接命名,
@Bean(name = "db1DataSource")还给db1起了一个大名db1DataSource,从此以后你叫db1DataSource,大家就都知道你要找db1这个数据库了。
下边的方法主体是告诉程序,我们的db1是一个数据库连接,请以一个数据库连接的标准对待他
public DataSource firstDataSource() { return DataSourceBuilder.create().build(); }
②、绑定JDBC
除此之外,我们还要绑定JDBC,然后用JDBC访问数据库
// 绑定 db1 的 JdbcTemplate @Bean(name = "db1JdbcTemplate") public JdbcTemplate db1JdbcTemplate( @Qualifier("db1DataSource") DataSource dataSource) { // 通过 @Qualifier 指定数据源 return new JdbcTemplate(dataSource); }
完整代码如下:
package com.example.demo; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import javax.sql.DataSource; @Configuration public class MultiDataSourceConfig { // 主数据源(必须指定@Primary,否则会冲突) @Primary @Bean(name = "db1DataSource") @ConfigurationProperties(prefix = "spring.datasource.db1") // 绑定第一个数据源的属性 public DataSource firstDataSource() { return DataSourceBuilder.create().build(); } // 第二个数据源 @Bean(name = "db2DataSource") @ConfigurationProperties(prefix = "spring.datasource.db2") // 绑定第二个数据源的属性 public DataSource secondDataSource() { return DataSourceBuilder.create().build(); } // 绑定 db1 的 JdbcTemplate @Bean(name = "db1JdbcTemplate") public JdbcTemplate db1JdbcTemplate( @Qualifier("db1DataSource") DataSource dataSource) { // 通过 @Qualifier 指定数据源 return new JdbcTemplate(dataSource); } // 绑定 db2 的 JdbcTemplate @Bean(name = "db2JdbcTemplate") public JdbcTemplate db2JdbcTemplate( @Qualifier("db2DataSource") DataSource dataSource) { return new JdbcTemplate(dataSource); } }
4、链接多个数据库——取消默认
只是命名还没用,此时如果你来到application.properties的页面,你会发现提示无法解析配置属性。这是当然的,因为正如我们之前所说,系统会默认给你的数据库命名为*,所以你以为你写的是spring.datasource.db1,其实在系统看来你写的是spring.datasource.*.db1 现在你就要告诉系统不要自作主张给我的数据库命名了。
找到你的主程序,大概率是 项目名称+application,然后把@SpringBootApplication改成@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) // 排除默认数据源自动配置 public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); System.out.println("Ciallo~(∠・ω< )⌒★start \n"); } }
然后问题就解决了。
5、使用
如下,我为我数据库中一个名叫test的表写了一个Model类和对应的数据库增删改查类:
model类:
package com.example.sqlServerConnect.model; public class testModel { // 自增主键(假设 autonum 是自增列,插入时无需手动赋值) private Integer autonum; private Integer id; // 列名:ID private Integer fh; // 列名:fh(非空) private Integer qishi; // 列名:qishi(允许空) private Integer zhongzhi; // 列名:zhongzhi(允许空) private Integer qishim; // 列名:qishim(允许空) private Integer zhongzhim; // 列名:zhongzhim(允许空) private String xuhao; // 列名:xuhao(nvarchar(50),允许空) private String miaoshu; // 列名:miaoshu(varchar(MAX),允许空) private String juanhao; // 列名:juanhao(varchar(50),允许空) private String jiluren; // 列名:jiluren(nchar(10),允许空) private String tbbarcodeS; // 列名:tbbarcode_s(nvarchar(50),允许空) private String tbbarcodeE; // 列名:tbbarcode_e(nvarchar(50),允许空) private String zuofeizhonglei; // 列名:zuofeizhonglei(nvarchar(50),允许空) private String zhengfu; // 列名:zhengfu(nchar(10),允许空) private Integer deleteLength; // 列名:DeleteLength(int,允许空) // --- autonum 的 Getter 和 Setter --- public Integer getAutonum() { return autonum; } public void setAutonum(Integer autonum) { this.autonum = autonum; } // --- id 的 Getter 和 Setter --- public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } // --- fh 的 Getter 和 Setter --- public Integer getFh() { return fh; } public void setFh(Integer fh) { this.fh = fh; } // --- qishi 的 Getter 和 Setter --- public Integer getQishi() { return qishi; } public void setQishi(Integer qishi) { this.qishi = qishi; } // --- zhongzhi 的 Getter 和 Setter --- public Integer getZhongzhi() { return zhongzhi; } public void setZhongzhi(Integer zhongzhi) { this.zhongzhi = zhongzhi; } // --- qishim 的 Getter 和 Setter --- public Integer getQishim() { return qishim; } public void setQishim(Integer qishim) { this.qishim = qishim; } public Integer getZhongzhim() { return zhongzhim; } public void setZhongzhim(Integer zhongzhim) { this.zhongzhim = zhongzhim; } public String getXuhao() { return xuhao; } public void setXuhao(String xuhao) { this.xuhao = xuhao; } public String getMiaoshu() { return miaoshu; } public void setMiaoshu(String miaoshu) { this.miaoshu = miaoshu; } public String getJuanhao() { return juanhao; } public void setJuanhao(String juanhao) { this.juanhao = juanhao; } public String getJiluren() { return jiluren; } public void setJiluren(String jiluren) { this.jiluren = jiluren; } public String getTbbarcodeS() { return tbbarcodeS; } public void setTbbarcodeS(String tbbarcodeS) { this.tbbarcodeS = tbbarcodeS; } public String getTbbarcodeE() { return tbbarcodeE; } public void setTbbarcodeE(String tbbarcodeE) { this.tbbarcodeE = tbbarcodeE; } public String getZuofeizhonglei() { return zuofeizhonglei; } public void setZuofeizhonglei(String zuofeizhonglei) { this.zuofeizhonglei = zuofeizhonglei; } public String getZhengfu() { return zhengfu; } public void setZhengfu(String zhengfu) { this.zhengfu = zhengfu; } public Integer getDeleteLength() { return deleteLength; } public void setDeleteLength(Integer deleteLength) { this.deleteLength = deleteLength; } }
增删改查类:
package com.example.sqlServerConnect.controller; import com.example.sqlServerConnect.model.testModel; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; import java.util.List; @Repository public class testController { // 注入 JdbcTemplate(多数据源场景需通过 @Qualifier 指定 Bean 名称,如 "firstJdbcTemplate") @Autowired @Qualifier("db1JdbcTemplate") // 替换为实际配置的 JdbcTemplate Bean 名称 private JdbcTemplate jdbcTemplate; // 1. 插入数据(autonum 若为自增,无需传入) public int insert(testModel entity) { String sql = "INSERT INTO test (ID, fh, qishi, zhongzhi, qishim, zhongzhim, xuhao, miaoshu, juanhao, jiluren, tbbarcode_s, tbbarcode_e, zuofeizhonglei, zhengfu, DeleteLength) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; return jdbcTemplate.update(sql, entity.getId(), entity.getFh(), entity.getQishi(), entity.getZhongzhi(), entity.getQishim(), entity.getZhongzhim(), entity.getXuhao(), entity.getMiaoshu(), entity.getJuanhao(), entity.getJiluren(), entity.getTbbarcodeS(), entity.getTbbarcodeE(), entity.getZuofeizhonglei(), entity.getZhengfu(), entity.getDeleteLength()); } // 2. 根据 autonum 删除数据 public int deleteByAutonum(Integer autonum) { String sql = "DELETE FROM test WHERE autonum = ?"; return jdbcTemplate.update(sql, autonum); } // 3. 更新数据(根据 autonum) public int update(testModel entity) { String sql = "UPDATE test SET ID=?, fh=?, qishi=?, zhongzhi=?, qishim=?, zhongzhim=?, xuhao=?, miaoshu=?, juanhao=?, jiluren=?, tbbarcode_s=?, tbbarcode_e=?, zuofeizhonglei=?, zhengfu=?, DeleteLength=? " + "WHERE autonum=?"; return jdbcTemplate.update(sql, entity.getId(), entity.getFh(), entity.getQishi(), entity.getZhongzhi(), entity.getQishim(), entity.getZhongzhim(), entity.getXuhao(), entity.getMiaoshu(), entity.getJuanhao(), entity.getJiluren(), entity.getTbbarcodeS(), entity.getTbbarcodeE(), entity.getZuofeizhonglei(), entity.getZhengfu(), entity.getDeleteLength(), entity.getAutonum()); } // 4. 根据 autonum 查询单条数据 public testModel findByAutonum(Integer autonum) { String sql = "SELECT * FROM test WHERE autonum = ?"; // BeanPropertyRowMapper 自动将查询结果映射为 test 对象(需列名与属性名匹配,或通过别名适配) return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(testModel.class), autonum); } // 5. 查询所有数据 public List<testModel> findAll() { String sql = "SELECT * FROM test"; return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(testModel.class)); } }
注:报错:db1JdbcTemplate为null
报错的同时也会提示:@Autowired提示:不建议使用字段注入
原因:字段注入存在一些潜在问题,Spring 官方和行业最佳实践更推荐构造器注入或setter 注入。
字段注入:
@Autowired @Qualifier("db1JdbcTemplate") // 替换为实际配置的 JdbcTemplate Bean 名称 private JdbcTemplate jdbcTemplate;
构造函数注入:
public JdbcTemplate jdbcTemplate; // 构造器注入(推荐,避免 null 问题) @Autowired public Feigen821Controller(@Qualifier("db1JdbcTemplate") JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; // 直接赋值,不会为 null }
Setter 注入(适合可选依赖):
就是利用get/set函数实现依赖的注入
// Setter 注入 @Autowired public void setUserDao(UserDao userDao) { this.userDao = userDao; }
三种注入方法比较:
字段注入并不推荐、构造函数注入安全性可靠性最高、setter注入为手动注入方法,可以自选依赖。
总结
到此这篇关于java同时配置多个数据库的文章就介绍到这了,更多相关java同时配置多个数据库内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!