spring boot 已经支持多数据源配置了,无需网上好多那些编写什么类的,特别麻烦,看看如下解决方案,官方的,放心!

1.首先定义数据源配置

#=====================multiple database config============================
#ds1
first.datasource.url=jdbc:mysql://localhost/test?characterEncoding=utf8&useSSL=true
first.datasource.username=root
first.datasource.password=123456
first.datasource.driver-class-name=com.mysql.jdbc.Driver
first.datasource.type=org.apache.tomcat.jdbc.pool.DataSource
first.datasource.max-wait=10000
first.datasource.max-active=200
first.datasource.test-on-borrow=true
first.datasource.initial-size=10 #ds2
second.datasource.url=jdbc:mysql://localhost/test2?characterEncoding=utf8&useSSL=true
second.datasource.username=root
second.datasource.password=123456
second.datasource.driver-class-name=com.mysql.jdbc.Driver
second.datasource.type=org.apache.tomcat.jdbc.pool.DataSource
second.datasource.max-wait=10000
second.datasource.max-active=200
second.datasource.test-on-borrow=true
second.datasource.initial-size=10
#=====================jpa config================================
#实体类维护数据库表结构的具体行为:update/create/create-drop/validate/none
spring.jpa.hibernate.ddl-auto=none
#打印sql语句
spring.jpa.show-sql=true #=============jackson serialize config =========================
#格式化输出的json字符串
spring.jackson.serialization.indent_output=true 2.配置ds1的相关注入对象和启用jpa支持
/**
* Created by hdwang on 2017-06-16.
* 第一个数据源配置
* If you are using Spring Data, you need to configure @EnableJpaRepositories
*/
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.hdwang.dao.datajpa.firstDs",entityManagerFactoryRef = "firstEntityManagerFactory",transactionManagerRef="firstTransactionManager")
public class FirstDsConfig { /**
* 数据源配置对象
* Primary 表示默认的对象,Autowire可注入,不是默认的得明确名称注入
* @return
*/
@Bean
@Primary
@ConfigurationProperties("first.datasource")
public DataSourceProperties firstDataSourceProperties() {
return new DataSourceProperties();
} /**
* 数据源对象
* @return
*/
@Bean
@Primary
@ConfigurationProperties("first.datasource")
public DataSource firstDataSource() {
return firstDataSourceProperties().initializeDataSourceBuilder().build();
} /**
* 实体管理对象
* @param builder 由spring注入这个对象,首先根据type注入(多个就取声明@Primary的对象),否则根据name注入
* @return
*/
@Bean
@Primary
public LocalContainerEntityManagerFactoryBean firstEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
return builder
.dataSource(firstDataSource())
.packages("com.hdwang.entity.dbFirst")
.persistenceUnit("firstDs")
.build();
} /**
* 事务管理对象
* @return
*/
@Bean(name = "firstTransactionManager")
@Primary
public PlatformTransactionManager transactionManager(EntityManagerFactory emf){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
} @Bean
@Primary
public JdbcTemplate jdbcTemplate(){
return new JdbcTemplate(firstDataSource());
} @Bean
@Primary
public TransactionTemplate transactionTemplate(PlatformTransactionManager platformTransactionManager){
return new TransactionTemplate(platformTransactionManager);
}
}
相关知识点:
1.使用@Bean可以创建一个bean对象交给spring容器管理
2.@Bean创建的bean对象的名称默认为方法名,也可以指定
3.@Bean方法参数表示,接收一个bean对象,默认按照type类型接收注入的对象,若要修改为byName方式,可以使用@Qualifier注解注入准确的对象
4.@Primary表示该bean为此类型的默认bean,在其他地方引用的时候用@Autowired即可按照类型注入,不受同类型多个对象影响
5.EnableJpaRepositories表示启用spring data jpa的支持,也就是jpa的新使用方式,注意basePackages指的是 @Repository接口的所在包位置,可配置多个
其他注解就不清楚了!
2.配置ds2的相关注入对象和启用jpa支持
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.hdwang.dao.datajpa.secondDs", entityManagerFactoryRef = "secondEntityManagerFactory",transactionManagerRef = "secondTransactionManager")
public class SecondDsConfig { @Bean
@ConfigurationProperties("second.datasource")
public DataSourceProperties secondDataSourceProperties() {
return new DataSourceProperties();
} @Bean
@ConfigurationProperties("second.datasource")
public DataSource secondDataSource() {
return secondDataSourceProperties().initializeDataSourceBuilder().build();
} /**
* 实体管理对象
* @param builder 由spring注入这个对象,首先根据type注入(多个就取声明@Primary的对象),否则根据name注入
* @return
*/
@Bean
public LocalContainerEntityManagerFactoryBean secondEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
return builder
.dataSource(secondDataSource())
.packages("com.hdwang.entity.dbSecond")
.persistenceUnit("secondDs")
.build();
} /**
* 事物管理对象
* @param secondEntityManagerFactory 实体管理工厂对象(按照名称注入)
* @return 平台事物管理器
*/
@Bean(name = "secondTransactionManager")
public PlatformTransactionManager transactionManager(@Qualifier("secondEntityManagerFactory")LocalContainerEntityManagerFactoryBean secondEntityManagerFactory){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(secondEntityManagerFactory.getObject());
return transactionManager;
} @Bean(name="jdbcTemplate2")
public JdbcTemplate jdbcTemplate(){
return new JdbcTemplate(secondDataSource());
} @Bean(name = "transactionTemplate2")
public TransactionTemplate transactionTemplate(@Qualifier("secondTransactionManager")PlatformTransactionManager transactionManager){
return new TransactionTemplate(transactionManager);
}
}

3.Repository数据持久层

package com.hdwang.dao.datajpa.firstDs;

@Repository
public interface UserRepository extends JpaRepository<User, Integer> {
/**
* spring data jpa 会自动注入实现(根据方法命名规范)
* @return
*/
User findByNumber(String number); @Modifying
@Query("delete from User u where u.id = :id")
void deleteUser(@Param("id")int id);
}
package com.hdwang.dao.datajpa.secondDs;

@Repository
public interface OrderRepository extends JpaRepository<Order, Integer> {
/**
* spring data jpa 会自动注入实现(根据方法命名规范)
* @return
*/
User findByNumber(String number); @Modifying
@Query("delete from Order o where o.id = :id")
void deleteUser(@Param("id") int id);
}
上面两个接口分属两个数据源,在@EnableJpaRepositories配置好后,这里就可以正确操作相应的数据源了

4.Service服务层,注意事物(接口我就不贴了)
@Service
@Transactional("firstTransactionManager")
public class UserServiceImpl implements UserService { @Autowired
private UserRepository userRepository; @Override
public User findById(int id) {
return this.userRepository.findOne(id);
} @Override
public User findByNumber(String number) {
return this.userRepository.findByNumber(number);
} @Override
public List<User> findAllUserByPage(int page,int size) {
Pageable pageable = new PageRequest(page, size);
Page<User> users = this.userRepository.findAll(pageable);
return users.getContent();
} @Override
public User updateUser(User user,boolean throwEx) {
User userNew = this.userRepository.save(user);
if(throwEx){
throw new RuntimeException("throw a ex");
}
return userNew;
} @Override
public void deleteUser(int id) {
this.userRepository.deleteUser(id);
}
}
@Service
@Transactional("secondTransactionManager")
public class OrderServiceImpl implements OrderService { @Autowired
private OrderRepository orderRepository; @Override
public Order findById(int id) {
return this.orderRepository.findOne(id);
} @Override
public Order updateOrder(Order order, boolean throwEx) {
Order orderNew = this.orderRepository.save(order);
if(throwEx){
throw new RuntimeException("throw a ex");
}
return orderNew;
}
}

知识扩展

1.如果采用传统jpa方式,@EnableJpaRepositories无需配置,配置了也无影响。实现方式如下:

ds1相关DaoImpl
@PersistenceContext
private EntityManager entityManager; ds2相关DaoImpl
@PersistenceContext(unitName = "secondDs")
private EntityManager entityManager; 因为ds1的entityManger声明了@Primary,所以无需指明unitName,ds2必须指明。注入了准确的entityManager,就可以直接拿来操作数据库了。service层和上面一样的,@Transactional("xxxManager")指明事物管理器即可! 2.采用jdbcTemplate方式,直接注入到Service层对象即可,so easy!
@Autowired
private JdbcTemplate jdbcTemplate; @Autowired
private TransactionTemplate transactionTemplate; @Resource(name="jdbcTemplate2")
private JdbcTemplate jdbcTemplate2; @Resource(name="transactionTemplate2")
private TransactionTemplate transactionTemplate2; 好了,spring boot 多数据源,完美解决! 而且三种数据库操作方法均支持,包括事物。已经经过实践证明了! 这是官方给出的最佳实践,只是官方文档没写细而已。 项目源码:https://github.com/hdwang123/springboottest

其它问题:
1. jpa配置无法生效,实体属性无法自动转换成数据库字段名,例如 userName -> user_name
解决办法:
entityManagerFactoryBuiler中指明jpa配置
builder.properties(new JpaProperties().getHibernateProperties(firstDataSource()))
												

最新文章

  1. js callee,caller学习
  2. Java设计模式之行为型模式
  3. http——tinyhttp分析
  4. vtk保存图像
  5. iOS 上架被拒原因保存
  6. 使用Apache的Hex类实现Hex(16进制字符串和)和字节数组的互转
  7. asp.net过滤数据中有异常数据字符串
  8. go语言中间的循环
  9. Ruby基础类型,动态特性,代码块
  10. Linux中find、grep命令详细用法
  11. ubuntu openStack icehouse dashboard theme自定义
  12. Codeforces 17D Notepad 简单的数论
  13. java线程池的创建使用
  14. jQuery 遍历 – 后代
  15. MOOS学习笔记1——HelloWorld
  16. 使用Docker在本地搭建Hadoop分布式集群
  17. Java执行JavaScript脚本破解encodeInp()加密
  18. myclipse里有感叹号的问题,希望可以帮到各位
  19. BZOJ 2277 Poi2011 Strongbox
  20. Docker环境安装与配置

热门文章

  1. excel实用技巧——vlookup函数
  2. 大数据入门第二十天——scala入门(二)scala基础01
  3. 20155222卢梓杰 实验一 逆向及Bof基础
  4. PHP 练习(租房子)
  5. 【LG3768】简单的数学题
  6. 学习JAVA第一章的心得
  7. 当系统扩展遇到违背OO的里氏原则(LSP)的时候怎么办 ?
  8. Markdown 入门指南
  9. onSaveInstanceState和onRestoreInstanceState触发的时机
  10. Windows Defender还原误删文件