摘要 
看完本文你将掌握如下知识点:
Spring Boot对JDBC的支持 
Spring Boot项目多数据源的配置 
Spring Boot的事务管理 
Spring Boot项目多数据源的事务管理 
Spring Boot项目中使用Hibernate4的方法 
Spring Boot项目中使用Mybatis的方法 
 
SpringBoot系列 :Spring Boot学习笔记 
前言 
Spring Boot针对企业开发场景提供了各种『开箱即用』的spring-boot-starter-xxx 自动配置依赖模块,这就使得我们开发Spring应用更加快速和高效。比如我们前面创建web项目时使用到的spring-boot-starter-web 。
这些spring-boot-starter-xxx 不但包含了对该功能的全部依赖包,同时也提供了该功能的自动配置类。我们本节要讨论的『数据访问』就是基于这些spring-boot-starter-xxx 的自动配置依赖模块。
环境准备 
jdk版本 :java version “1.8.0_31”数据库 :10.1.16-MariaDB脚本 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 # 创建库1  CREATE  SCHEMA `springboot1` DEFAULT  CHARACTER  SET  utf8 ;CREATE  TABLE  `springboot1`.`person` (  `p_id` INT  NOT  NULL  AUTO_INCREMENT COMMENT '主键' ,   `p_name` VARCHAR (45 ) NULL  COMMENT '姓名' ,   `p_age` INT  NULL  COMMENT '年龄' ,   PRIMARY  KEY (`p_id`)) ENGINE =  InnoDB COMMENT =  '人员信息表' ; INSERT  INTO  `springboot1`.`person` (`p_id`, `p_name`, `p_age`) VALUES  ('1' , '张三' , '20' );INSERT  INTO  `springboot1`.`person` (`p_id`, `p_name`, `p_age`) VALUES  ('2' , '李四' , '25' );# 创建库2  CREATE  SCHEMA `springboot2` DEFAULT  CHARACTER  SET  utf8 ;CREATE  TABLE  `springboot2`.`person` (  `p_id` INT  NOT  NULL  AUTO_INCREMENT COMMENT '主键' ,   `p_name` VARCHAR (45 ) NULL  COMMENT '姓名' ,   `p_age` INT  NULL  COMMENT '年龄' ,   PRIMARY  KEY (`p_id`)) ENGINE =  InnoDB COMMENT =  '人员信息表' ; INSERT  INTO  `springboot2`.`person` (`p_id`, `p_name`, `p_age`) VALUES  ('1' , '张三' , '20' );INSERT  INTO  `springboot2`.`person` (`p_id`, `p_name`, `p_age`) VALUES  ('2' , '李四' , '25' );
Spring Boot对JDBC的支持 
创建项目 
新建一个springboot项目,依赖选择web和jdbc
项目创建成功后查看pom,会看到添加了spring-boot-starter-jdbc 的依赖
1 2 3 4 <dependency >     <groupId > org.springframework.boot</groupId >      <artifactId > spring-boot-starter-jdbc</artifactId >  </dependency > 
配置项目 
在pom中增加MySQL依赖
1 2 3 4 5 <dependency >     <groupId > mysql</groupId >      <artifactId > mysql-connector-java</artifactId >      <version > 5.1.37</version >  </dependency > 
在application.properties 中添加数据源配置信息
1 2 3 4 5 spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/springboot1?useUnicode=true&characterEncoding=utf-8 spring.datasource.username=root spring.datasource.password=newpwd 
项目代码 
本例只做简单演示,所以只创建如下3个类,并用一个单元测试类进行测试Person 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public  class  Person  implements  Serializable  {    private  static  final  long  serialVersionUID  =  -1L ;     private  Long id;     private  String name;     private  Integer age;          @Override      public  String toString ()  {         return  "Person{"  +                 "id="  + id +                 ", name='"  + name + '\''  +                 ", age="  + age +                 '}' ;     } } 
Dao:PersonDao 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 @Repository public  class  PersonDao  {    @Autowired      private  JdbcTemplate jdbcTemplate;     public  int  savePerson (Person person) {         String  sql  =  "INSERT INTO `springboot1`.`person` (`p_name`, `p_age`) VALUES (?, ?)" ;         int  result  =  jdbcTemplate.update(sql,new  Object []{person.getName(),person.getAge()});         return  result;     }     public  List<Person> getAllPersonList () {         String  sql  =  "select * from person s" ;         List<Person> list = jdbcTemplate.query(sql,new  PersonMapper ());         return  list;     }     class  PersonMapper  implements  RowMapper <Person>{         @Override          public  Person mapRow (ResultSet resultSet, int  i)  throws  SQLException {             Person  person  =  new  Person ();             person.setId(resultSet.getLong("p_id" ));             person.setName(resultSet.getString("p_name" ));             person.setAge(resultSet.getInt("p_age" ));             return  person;         }     } } 
Service:PersonService 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Service public  class  PersonService  {    @Autowired      private  PersonDao personDao;     public  int  savePserson (Person person) {        return  personDao.savePerson(person);     }     public  List<Person> getAllPersonList () {         return  personDao.getAllPersonList();     } } 
单元测试:SpringbootjdbcdemoApplicationTests 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @RunWith(SpringRunner.class) @SpringBootTest public  class  SpringbootjdbcdemoApplicationTests  {    @Autowired      private  PersonService personService;     @Test      public  void  savePerson () {         Person  person  =  new  Person ();         person.setName("王五" );         person.setAge(18 );         int  result  =  personService.savePserson(person);         Assert.assertEquals(1 ,result);     }     @Test      public  void  getAllPersonList () {         List<Person> list = personService.getAllPersonList();         System.out.println(list.size());         for (Person person : list){             System.out.println(person);         }     } } 
说明 spring-boot-starter-jdbc 的依赖后,即可在项目代码中通过@Autowired自动注入JdbcTemplate。而数据源的配置则在application.properties 中进行配置。
如果不想使用spring-boot-starter-jdbc 带来的默认依赖和自动配置,那么采用如下的方式,效果是一样的。
使用自定义的DataSourceConfig 
修改pom中的依赖,去掉对spring-boot-starter-jdbc 的依赖,并加入对spring-jdbc 的依赖,这样我们就失去了对JDBC的自动配置功能了。
1 2 3 4 5 6 7 8 9 10 11 12 <dependency >     <groupId > org.springframework</groupId >      <artifactId > spring-jdbc</artifactId >      <version > 4.3.4.RELEASE</version >  </dependency > 
启动类中去掉对DataSourceAutoConfiguration 的自动配置支持
1 2 3 4 5 6 7 @SpringBootApplication(exclude={DataSourceAutoConfiguration.class}) public  class  SpringbootjdbcdemoApplication  {    public  static  void  main (String[] args)  {         SpringApplication.run(SpringbootjdbcdemoApplication.class, args);     } } 
创建DataSourceConfig 配置类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 @Configuration public  class  DataSourceConfig  {    @Value("${spring.datasource.driver-class-name}")      String driverClass;     @Value("${spring.datasource.url}")      String url;     @Value("${spring.datasource.username}")      String userName;     @Value("${spring.datasource.password}")      String passWord;     @Bean(name = "dataSource")      public  DataSource dataSource ()  {         DriverManagerDataSource  dataSource  =  new  DriverManagerDataSource ();         dataSource.setDriverClassName(driverClass);         dataSource.setUrl(url);         dataSource.setUsername(userName);         dataSource.setPassword(passWord);         return  dataSource;     }     @Bean(name = "jdbcTemplate")      public  JdbcTemplate jdbcTemplate () {         JdbcTemplate  jdbcTemplate  =  new  JdbcTemplate (dataSource());         return  jdbcTemplate;     } } 
其它代码不需要任何修改,运行效果一致。
说明 spring-boot-starter-jdbc 的自动配置解决方案,我们还要自己配置呢,这是因为自动配置并不是那么的强大,spring-boot-starter-jdbc 只能支持单一的数据源配置,如果项目中需要关联多个数据源,就需要我们自己处理了。
比如我们在环境准备中创建了两个数据库,接下来我们在项目中增加多数据源的配置。
在application.properties 中添加数据源配置信息
1 2 3 4 5 spring.datasource.driver-class-name2=com.mysql.jdbc.Driver spring.datasource.url2=jdbc:mysql://localhost:3306/springboot2?useUnicode=true&characterEncoding=utf-8 spring.datasource.username2=root spring.datasource.password2=newpwd 
然后在DataSourceConfig 配置类中增加如下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Value("${spring.datasource.driver-class-name2}") String driverClass2; @Value("${spring.datasource.url2}") String url2; @Value("${spring.datasource.username2}") String userName2; @Value("${spring.datasource.password2}") String passWord2; @Bean(name = "dataSource2") public  DataSource dataSource2 ()  {    DriverManagerDataSource  dataSource  =  new  DriverManagerDataSource ();     dataSource.setDriverClassName(driverClass2);     dataSource.setUrl(url2);     dataSource.setUsername(userName2);     dataSource.setPassword(passWord2);     return  dataSource; } @Bean(name = "jdbcTemplate2") public  JdbcTemplate jdbcTemplate2 () {    JdbcTemplate  jdbcTemplate  =  new  JdbcTemplate (dataSource2());     return  jdbcTemplate; } 
此时需要在Dao中将@Autowired注解替换成@Resource(name = "jdbcTemplate"),来明确指定要使用哪一个jdbcTemplate对象。
说明 SpringMVC4零配置 
Spring Boot的事务管理 
JDBC事务管理 
如果我们项目中使用的是JDBC的数据访问方案,并且容器中只注册了一个DataSource ,那么SpringBoot就会为我们开启DataSourceTransactionManagerAutoConfiguration 的自动配置类,其会在容器中注册一个DataSourceTransactionManager 事务管理器,同时会开启对注解式事务**@Transactional的支持。感兴趣的可以看一下 DataSourceTransactionManagerAutoConfiguration**的源码。
@Transactional 是Spring框架提供的,配置方法参考下面的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = { Exception.class }) public  class  PersonService {              @Transactional(readOnly = true)      public  List<Person> getAllPersonList () {              }          public  int  savePserson (Person person) {              } } 
如果在测试类上声明**@Transactional**,则会开启自动回滚,不会产生脏数据
1 2 3 4 @RunWith(SpringRunner.class) @SpringBootTest @Transactional public  class  SpringbootjdbcdemoApplicationTests  {…………}
如果希望自己配置事务,可以在配置类中增加事务管理器的配置,比如,我们在DataSourceConfig 中增加如下配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 @Configuration @EnableTransactionManagement(proxyTargetClass = true) public  class  DataSourceConfig  {    @Value("${spring.datasource.driver-class-name}")      String driverClass;     @Value("${spring.datasource.url}")      String url;     @Value("${spring.datasource.username}")      String userName;     @Value("${spring.datasource.password}")      String passWord;     @Bean(name = "dataSource")      public  DataSource dataSource ()  {         DriverManagerDataSource  dataSource  =  new  DriverManagerDataSource ();         dataSource.setDriverClassName(driverClass);         dataSource.setUrl(url);         dataSource.setUsername(userName);         dataSource.setPassword(passWord);         return  dataSource;     }     @Bean(name = "jdbcTemplate")      public  JdbcTemplate jdbcTemplate () {         JdbcTemplate  jdbcTemplate  =  new  JdbcTemplate (dataSource());         return  jdbcTemplate;     }     @Bean      public  DataSourceTransactionManager transactionManager ()  {         return  new  DataSourceTransactionManager (dataSource());     } } 
说明 
我们上文讲到了可以在项目中通过配置类,自己配置多个数据源,并通过DataSourceConfig 进行了演示,接下来我们添加多个事务管理器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 @Configuration @EnableTransactionManagement(proxyTargetClass = true) public  class  DataSourceConfig  {    @Value("${spring.datasource.driver-class-name}")      String driverClass;     @Value("${spring.datasource.url}")      String url;     @Value("${spring.datasource.username}")      String userName;     @Value("${spring.datasource.password}")      String passWord;     @Value("${spring.datasource.driver-class-name2}")      String driverClass2;     @Value("${spring.datasource.url2}")      String url2;     @Value("${spring.datasource.username2}")      String userName2;     @Value("${spring.datasource.password2}")      String passWord2;     @Bean(name = "dataSource")      public  DataSource dataSource ()  {         DriverManagerDataSource  dataSource  =  new  DriverManagerDataSource ();         dataSource.setDriverClassName(driverClass);         dataSource.setUrl(url);         dataSource.setUsername(userName);         dataSource.setPassword(passWord);         return  dataSource;     }     @Bean(name = "jdbcTemplate")      public  JdbcTemplate jdbcTemplate () {         JdbcTemplate  jdbcTemplate  =  new  JdbcTemplate (dataSource());         return  jdbcTemplate;     }     @Bean(name = "transactionManager")      public  DataSourceTransactionManager transactionManager ()  {         return  new  DataSourceTransactionManager (dataSource());     }     @Bean(name = "dataSource2")      public  DataSource dataSource2 ()  {         DriverManagerDataSource  dataSource  =  new  DriverManagerDataSource ();         dataSource.setDriverClassName(driverClass2);         dataSource.setUrl(url2);         dataSource.setUsername(userName2);         dataSource.setPassword(passWord2);         System.out.println(url2);         return  dataSource;     }     @Bean(name = "jdbcTemplate2")      public  JdbcTemplate jdbcTemplate2 () {         JdbcTemplate  jdbcTemplate  =  new  JdbcTemplate (dataSource2());         return  jdbcTemplate;     }     @Bean(name = "transactionManager2")      public  DataSourceTransactionManager transactionManager2 ()  {         return  new  DataSourceTransactionManager (dataSource2());     } } 
这时,我们必须在**@Transactional**注解中指定要使用哪一个事务管理器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @Service @Transactional(transactionManager = "transactionManager",propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = { Exception.class }) public  class  PersonService  {    @Autowired      private  PersonDao personDao;     public  int  savePserson (Person person) {         return  personDao.savePerson(person);     }     @Transactional(transactionManager = "transactionManager",readOnly = true)      public  List<Person> getAllPersonList () {         return  personDao.getAllPersonList();     }     @Transactional(transactionManager = "transactionManager2",propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = { Exception.class })      public  int  savePserson2 (Person person) {         return  personDao.savePerson2(person);     }     @Transactional(transactionManager = "transactionManager2",readOnly = true)      public  List<Person> getAllPersonList2 () {         return  personDao.getAllPersonList2();     } } 
说明 
那要怎么做呢,我们接着往下看。
多数据源事务管理 
这里推荐使用**Atomikos **,Atomikos支持Mysql、Oracle等多种数据库,可与多种ORM框架集成,如MyBatis、JPA、Hibernate等等,同时支持各种容器下JNDI的多数据源管理。Atomikos官网提供了各种情况下使用Atomikos的Example,本文只对使用JDBC时的情况进行说明。
目前maven中央仓库的最新版本是4.0.4,使用Atomikos,需要在项目中加入如下依赖:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <dependency >     <groupId > com.atomikos</groupId >      <artifactId > transactions-jdbc</artifactId >      <version > 4.0.4</version >  </dependency > <dependency >     <groupId > com.atomikos</groupId >      <artifactId > transactions-jta</artifactId >      <version > 4.0.4</version >  </dependency > <dependency >     <groupId > com.atomikos</groupId >      <artifactId > transactions</artifactId >      <version > 4.0.4</version >  </dependency > <dependency >     <groupId > com.atomikos</groupId >      <artifactId > atomikos-util</artifactId >      <version > 4.0.4</version >  </dependency >  <dependency >      <groupId > javax.transaction</groupId >      <artifactId > jta</artifactId >      <version > 1.1</version >  </dependency > 
对DataSourceConfig 进行改造:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 package  com.example;import  com.atomikos.icatch.jta.UserTransactionImp;import  com.atomikos.icatch.jta.UserTransactionManager;import  com.atomikos.jdbc.AtomikosDataSourceBean;import  com.mysql.jdbc.jdbc2.optional.MysqlXADataSource;import  org.springframework.beans.factory.annotation.Value;import  org.springframework.context.annotation.Bean;import  org.springframework.context.annotation.Configuration;import  org.springframework.context.annotation.DependsOn;import  org.springframework.jdbc.core.JdbcTemplate;import  org.springframework.transaction.PlatformTransactionManager;import  org.springframework.transaction.annotation.EnableTransactionManagement;import  org.springframework.transaction.jta.JtaTransactionManager;import  javax.sql.DataSource;import  javax.transaction.TransactionManager;import  javax.transaction.UserTransaction;@Configuration @EnableTransactionManagement(proxyTargetClass = true) public  class  DataSourceConfig  {    @Value("${spring.datasource.driver-class-name}")      String driverClass;     @Value("${spring.datasource.url}")      String url;     @Value("${spring.datasource.username}")      String userName;     @Value("${spring.datasource.password}")      String passWord;     @Value("${spring.datasource.driver-class-name2}")      String driverClass2;     @Value("${spring.datasource.url2}")      String url2;     @Value("${spring.datasource.username2}")      String userName2;     @Value("${spring.datasource.password2}")      String passWord2;     @Bean(name = "userTransaction")      public  UserTransaction userTransaction ()  throws  Throwable {         UserTransactionImp  userTransactionImp  =  new  UserTransactionImp ();         userTransactionImp.setTransactionTimeout(300 );         return  userTransactionImp;     }     @Bean(name = "atomikosTransactionManager", initMethod = "init", destroyMethod = "close")      public  TransactionManager atomikosTransactionManager ()  throws  Throwable {         UserTransactionManager  userTransactionManager  =  new  UserTransactionManager ();         userTransactionManager.setForceShutdown(true );         return  userTransactionManager;     }     @Bean(name = "transactionManager")      @DependsOn({ "userTransaction", "atomikosTransactionManager" })      public  PlatformTransactionManager transactionManager ()  throws  Throwable {         UserTransaction  userTransaction  =  userTransaction();         TransactionManager  atomikosTransactionManager  =  atomikosTransactionManager();         JtaTransactionManager  jtaTransactionManager  =  new  JtaTransactionManager (userTransaction, atomikosTransactionManager);         jtaTransactionManager.setAllowCustomIsolationLevels(true );         return  jtaTransactionManager;     }     @Bean(name = "dataSource", initMethod = "init", destroyMethod = "close")      public  DataSource dataSource ()  {         System.out.println("dataSource init" );                                    MysqlXADataSource  mysqlXaDataSource  =  new  MysqlXADataSource ();         mysqlXaDataSource.setUrl(url);         mysqlXaDataSource.setPassword(passWord);         mysqlXaDataSource.setUser(userName);         mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true );         AtomikosDataSourceBean  xaDataSource  =  new  AtomikosDataSourceBean ();         xaDataSource.setXaDataSource(mysqlXaDataSource);         xaDataSource.setUniqueResourceName("dataSource" );         xaDataSource.setMinPoolSize(10 );         xaDataSource.setPoolSize(10 );         xaDataSource.setMaxPoolSize(30 );         xaDataSource.setBorrowConnectionTimeout(60 );         xaDataSource.setReapTimeout(20 );         xaDataSource.setMaxIdleTime(60 );         xaDataSource.setMaintenanceInterval(60 );         return  xaDataSource;     }     @Bean(name = "dataSource2", initMethod = "init", destroyMethod = "close")      public  DataSource dataSource2 ()  {         System.out.println("dataSource2 init" );         MysqlXADataSource  mysqlXaDataSource  =  new  MysqlXADataSource ();         mysqlXaDataSource.setUrl(url2);         mysqlXaDataSource.setPassword(passWord2);         mysqlXaDataSource.setUser(userName2);         mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true );         AtomikosDataSourceBean  xaDataSource  =  new  AtomikosDataSourceBean ();         xaDataSource.setXaDataSource(mysqlXaDataSource);         xaDataSource.setUniqueResourceName("dataSource2" );         xaDataSource.setMinPoolSize(10 );         xaDataSource.setPoolSize(10 );         xaDataSource.setMaxPoolSize(30 );         xaDataSource.setBorrowConnectionTimeout(60 );         xaDataSource.setReapTimeout(20 );         xaDataSource.setMaxIdleTime(60 );         xaDataSource.setMaintenanceInterval(60 );         return  xaDataSource;     }     @Bean(name = "jdbcTemplate")      public  JdbcTemplate jdbcTemplate () {         JdbcTemplate  jdbcTemplate  =  new  JdbcTemplate (dataSource());         return  jdbcTemplate;     }     @Bean(name = "jdbcTemplate2")      public  JdbcTemplate jdbcTemplate2 () {         JdbcTemplate  jdbcTemplate  =  new  JdbcTemplate (dataSource2());         return  jdbcTemplate;     } } 
项目编译路径下可以创建一个jta.properties 文件,用于对Atomikos的相关属性进行配置,不过也可以不加这个文件,因为所有的属性都有默认值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 com.atomikos.icatch.enable_logging=true com.atomikos.icatch.force_shutdown_on_vm_exit=false com.atomikos.icatch.automatic_resource_registration=true com.atomikos.icatch.checkpoint_interval=500 com.atomikos.icatch.serial_jta_transactions=true com.atomikos.icatch.default_jta_timeout=10000 com.atomikos.icatch.max_timeout=300000 com.atomikos.icatch.log_base_dir=./ com.atomikos.icatch.threaded_2pc=false com.atomikos.icatch.max_actives=50 com.atomikos.icatch.log_base_name=tmlog java.naming.factory.initial=com.sun.jndi.rmi.registry.RegistryContextFactory com.atomikos.icatch.client_demarcation=false java.naming.provider.url=rmi://localhost:1099 com.atomikos.icatch.rmi_export_class=none com.atomikos.icatch.trust_client_tm=false com.atomikos.icatch.forget_orphaned_log_entries_delay=86400000 com.atomikos.icatch.recovery_delay=${com.atomikos.icatch.default_jta_timeout} com.atomikos.icatch.oltp_max_retries=5 com.atomikos.icatch.oltp_retry_interval=10000 com.atomikos.icatch.allow_subtransactions=true 
Spring Boot中Atomikos与Hibernate4多数据源集成方法 
Atomikos与Hibernate4集成方法与JDBC类似,我们在pom中加入hibernate的依赖,并对DataSourceConfig 进行改造pom 
1 2 3 4 5 <dependency >     <groupId > org.hibernate</groupId >      <artifactId > hibernate-core</artifactId >      <version > 4.3.5.Final</version >  </dependency > 
DataSourceConfig 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 package  com.example;import  com.atomikos.icatch.jta.UserTransactionImp;import  com.atomikos.icatch.jta.UserTransactionManager;import  com.atomikos.jdbc.AtomikosDataSourceBean;import  com.example.hibernate.CP_HibernateDAO;import  com.example.hibernate.impl.CP_Hibernate4DAOImpl;import  com.mysql.jdbc.jdbc2.optional.MysqlXADataSource;import  org.springframework.beans.factory.annotation.Value;import  org.springframework.context.annotation.Bean;import  org.springframework.context.annotation.Configuration;import  org.springframework.context.annotation.DependsOn;import  org.springframework.orm.hibernate4.LocalSessionFactoryBean;import  org.springframework.transaction.PlatformTransactionManager;import  org.springframework.transaction.annotation.EnableTransactionManagement;import  org.springframework.transaction.jta.JtaTransactionManager;import  javax.sql.DataSource;import  javax.transaction.TransactionManager;import  javax.transaction.UserTransaction;import  java.util.Properties;@Configuration @EnableTransactionManagement(proxyTargetClass = true) public  class  DataSourceConfig  {    @Value("${spring.datasource.driver-class-name}")      String driverClass;     @Value("${spring.datasource.url}")      String url;     @Value("${spring.datasource.username}")      String userName;     @Value("${spring.datasource.password}")      String passWord;     @Value("${spring.datasource.driver-class-name2}")      String driverClass2;     @Value("${spring.datasource.url2}")      String url2;     @Value("${spring.datasource.username2}")      String userName2;     @Value("${spring.datasource.password2}")      String passWord2;     @Bean(name = "userTransaction")      public  UserTransaction userTransaction ()  throws  Throwable {         UserTransactionImp  userTransactionImp  =  new  UserTransactionImp ();         userTransactionImp.setTransactionTimeout(10000 );         return  userTransactionImp;     }     @Bean(name = "atomikosTransactionManager", initMethod = "init", destroyMethod = "close")      public  TransactionManager atomikosTransactionManager ()  throws  Throwable {         UserTransactionManager  userTransactionManager  =  new  UserTransactionManager ();         userTransactionManager.setForceShutdown(true );         return  userTransactionManager;     }     @Bean(name = "transactionManager")      @DependsOn({ "userTransaction", "atomikosTransactionManager" })      public  PlatformTransactionManager transactionManager ()  throws  Throwable {         System.out.println();         UserTransaction  userTransaction  =  userTransaction();         TransactionManager  atomikosTransactionManager  =  atomikosTransactionManager();         JtaTransactionManager  jtaTransactionManager  =  new  JtaTransactionManager (userTransaction, atomikosTransactionManager);         jtaTransactionManager.setAllowCustomIsolationLevels(true );         return  jtaTransactionManager;     }     @Bean(name = "dataSource", initMethod = "init", destroyMethod = "close")      public  DataSource dataSource ()  {         System.out.println();         MysqlXADataSource  mysqlXaDataSource  =  new  MysqlXADataSource ();         mysqlXaDataSource.setUrl(url);         mysqlXaDataSource.setPassword(passWord);         mysqlXaDataSource.setUser(userName);         mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true );         AtomikosDataSourceBean  xaDataSource  =  new  AtomikosDataSourceBean ();         xaDataSource.setXaDataSource(mysqlXaDataSource);         xaDataSource.setUniqueResourceName("dataSource" );         xaDataSource.setMinPoolSize(10 );         xaDataSource.setPoolSize(10 );         xaDataSource.setMaxPoolSize(30 );         xaDataSource.setBorrowConnectionTimeout(60 );         xaDataSource.setReapTimeout(20 );         xaDataSource.setMaxIdleTime(60 );         xaDataSource.setMaintenanceInterval(60 );         return  xaDataSource;     }     @Bean(name = "dataSource2", initMethod = "init", destroyMethod = "close")      public  DataSource dataSource2 ()  {         System.out.println();         MysqlXADataSource  mysqlXaDataSource  =  new  MysqlXADataSource ();         mysqlXaDataSource.setUrl(url2);         mysqlXaDataSource.setPassword(passWord2);         mysqlXaDataSource.setUser(userName2);         mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true );         AtomikosDataSourceBean  xaDataSource  =  new  AtomikosDataSourceBean ();         xaDataSource.setXaDataSource(mysqlXaDataSource);         xaDataSource.setUniqueResourceName("dataSource2" );         xaDataSource.setMinPoolSize(10 );         xaDataSource.setPoolSize(10 );         xaDataSource.setMaxPoolSize(30 );         xaDataSource.setBorrowConnectionTimeout(60 );         xaDataSource.setReapTimeout(20 );         xaDataSource.setMaxIdleTime(60 );         xaDataSource.setMaintenanceInterval(60 );         return  xaDataSource;     }     @Bean(name = "sessionFactory")      public  LocalSessionFactoryBean localSessionFactoryBean ()  {         System.out.println("sessionFactory" );         LocalSessionFactoryBean  sessionFactory  =  new  LocalSessionFactoryBean ();         sessionFactory.setDataSource(dataSource());                  String[] packagesToScan = new  String [] { "com.example.model.ds1"  };         sessionFactory.setPackagesToScan(packagesToScan);         Properties  hibernateProperties  =  new  Properties ();         hibernateProperties.setProperty("hibernate.dialect" , "org.hibernate.dialect.MySQLDialect" );         hibernateProperties.setProperty("hibernate.show_sql" , "true" );                  hibernateProperties.setProperty("hibernate.current_session_context_class" , "jta" );         hibernateProperties.setProperty("hibernate.transaction.factory_class" , "org.hibernate.transaction.JTATransactionFactory" );         sessionFactory.setHibernateProperties(hibernateProperties);         return  sessionFactory;     }     @Bean(name = "sessionFactory2")      public  LocalSessionFactoryBean localSessionFactoryBean2 ()  {         System.out.println("sessionFactory2" );         LocalSessionFactoryBean  sessionFactory  =  new  LocalSessionFactoryBean ();         sessionFactory.setDataSource(dataSource2());                  String[] packagesToScan = new  String [] { "com.example.model.ds2"  };         sessionFactory.setPackagesToScan(packagesToScan);         Properties  hibernateProperties  =  new  Properties ();         hibernateProperties.setProperty("hibernate.dialect" , "org.hibernate.dialect.MySQLDialect" );         hibernateProperties.setProperty("hibernate.show_sql" , "true" );                  hibernateProperties.setProperty("hibernate.current_session_context_class" , "jta" );         hibernateProperties.setProperty("hibernate.transaction.factory_class" , "org.hibernate.transaction.JTATransactionFactory" );         sessionFactory.setHibernateProperties(hibernateProperties);         return  sessionFactory;     }     @Bean(name = "hibernateDAO")      public  CP_HibernateDAO hibernate4Dao ()  {         System.out.println("hibernateDAO" );         CP_Hibernate4DAOImpl  dao  =  new  CP_Hibernate4DAOImpl ();                  dao.setSessionFactory(localSessionFactoryBean().getObject());         return  dao;     }     @Bean(name = "hibernateDAO2")      public  CP_HibernateDAO hibernate4Dao2 ()  {         System.out.println("hibernateDAO2" );         CP_Hibernate4DAOImpl  dao  =  new  CP_Hibernate4DAOImpl ();                  dao.setSessionFactory(localSessionFactoryBean2().getObject());         return  dao;     } } 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Entity @Table(name = "person") public  class  Person  implements  Serializable  {    private  static  final  long  serialVersionUID  =  -1L ;     @Id      @GeneratedValue(strategy = GenerationType.AUTO)      @Column(name = "p_id")      private  Long id;     @Column(name = "p_name")      private  String name;     @Column(name = "p_age")      private  Integer age;      } 
CP_HibernateDAO 是我们自定义的Hibernate的通用Dao接口,其定义的方法和和实现类CP_Hibernate4DAOImpl 代码如下:
1 2 3 4 5 6 7 8 9 10 11 package  com.example.hibernate;import  java.util.List;public  interface  CP_HibernateDAO  {    public  List<?> findAll(Class<?> entityClazz, String... str);     public  void  save (Object entity) ; } 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 package  com.example.hibernate.impl;import  com.example.hibernate.CP_HibernateDAO;import  org.hibernate.Criteria;import  org.hibernate.Session;import  org.hibernate.SessionFactory;import  org.hibernate.criterion.DetachedCriteria;import  java.util.List;public  class  CP_Hibernate4DAOImpl  implements  CP_HibernateDAO  {    private  SessionFactory sessionFactory;     public  SessionFactory getSessionFactory ()  {         return  sessionFactory;     }          public  void  setSessionFactory (SessionFactory sessionFactory)  {         this .sessionFactory = sessionFactory;     }     private  Session getHibernateSession ()  {         Session  session  =  sessionFactory.openSession();         return  session;     }          @Override      public  List<?> findAll(Class<?> entityClazz, String... str) {         DetachedCriteria  dc  =  DetachedCriteria.forClass(entityClazz);         List<?> list = findAllByCriteria(dc);         return  list;     }          @Override      public  void  save (Object entity)  {         getHibernateSession().save(entity);                  getHibernateSession().flush();     }     public  List<?> findAllByCriteria(DetachedCriteria detachedCriteria) {                  Criteria  criteria  =  detachedCriteria                 .getExecutableCriteria(getHibernateSession());         return  criteria.list();     } } 
说明 
session必须使用sessionFactory.openSession()的方式获得,不能使用sessionFactory.getCurrentSession()。
 
更新操作必须调用session.flush()方法。
 
 
Spring配置文件的方式,可以参考:Spring4+Hibernate4+Atomikos3.3多数据源事务管理 
Spring Boot中Mybitas的使用 
创建项目时,我们可以选择mybatis-spring-boot-starter 依赖,这样可以激活SpringBoot对Mybatis的自动配置类。
pom 中添加依赖
1 2 3 4 5 <dependency >     <groupId > org.mybatis.spring.boot</groupId >      <artifactId > mybatis-spring-boot-starter</artifactId >      <version > 1.1.1</version >  </dependency > 
application.properties 中添加mybaits的自动配置属性,可以查看MybatisProperties 了解可以配置哪些属性
1 2 mybatis.mapper-locations=classpath:mapper/*.xml 
Mapper接口上要配置**@Mapper注解,因为 mybatis-spring-boot-starter的自动配置会扫描 @Mapper**注解来注册Mapper接口。
1 2 3 4 @Mapper public  interface  PersonMapper  {     } 
此时同样可以使用**@Transactional**注解
说明 maven插件–MyBatis自动生成代码 
mybatis-spring-boot-starter 不利于扩展,所以还是我们自己实现个mybitas的配置类吧。
pom 中去掉mybatis-spring-boot-starter 的依赖,增加mybatis的依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <dependency >     <groupId > org.mybatis</groupId >      <artifactId > mybatis</artifactId >      <version > 3.4.0</version >  </dependency > <dependency >     <groupId > org.mybatis</groupId >      <artifactId > mybatis-spring</artifactId >      <version > 1.3.0</version >  </dependency > <dependency >     <groupId > org.springframework</groupId >      <artifactId > spring-jdbc</artifactId >      <version > 4.3.4.RELEASE</version >  </dependency > 
创建MyBatisConfig 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 @Configuration @EnableTransactionManagement(proxyTargetClass = true) public  class  MyBatisConfig  {    @Value("${spring.datasource.driver-class-name}")      String driverClass;     @Value("${spring.datasource.url}")      String url;     @Value("${spring.datasource.username}")      String userName;     @Value("${spring.datasource.password}")      String passWord;     @Bean(name = "dataSource")      public  DataSource dataSource ()  {         DriverManagerDataSource  dataSource  =  new  DriverManagerDataSource ();         dataSource.setDriverClassName(driverClass);         dataSource.setUrl(url);         dataSource.setUsername(userName);         dataSource.setPassword(passWord);         return  dataSource;     }     @Bean(name = "sqlSessionFactory")      public  SqlSessionFactory sqlSessionFactoryBean ()  {         SqlSessionFactoryBean  bean  =  new  SqlSessionFactoryBean ();         bean.setDataSource(dataSource());                  ResourcePatternResolver  resolver  =  new  PathMatchingResourcePatternResolver ();         try  {             bean.setMapperLocations(resolver.getResources("classpath:mapper/*.xml" ));             return  bean.getObject();         } catch  (Exception e) {             e.printStackTrace();             throw  new  RuntimeException (e);         }     }     @Bean      public  SqlSessionTemplate sqlSessionTemplate (SqlSessionFactory sqlSessionFactory)  {         return  new  SqlSessionTemplate (sqlSessionFactory);     }     @Bean      public  PlatformTransactionManager annotationDrivenTransactionManager ()  {         return  new  DataSourceTransactionManager (dataSource());     } } 
MyBatisMapperScannerConfig ,基于包扫描Mapper,此时不需要配置**@Mapper**注解
1 2 3 4 5 6 7 8 9 10 11 12 @Configuration @AutoConfigureAfter(MyBatisConfig.class) public  class  MyBatisMapperScannerConfig  {    @Bean      public  MapperScannerConfigurer mapperScannerConfigurer ()  {         MapperScannerConfigurer  mapperScannerConfigurer  =  new  MapperScannerConfigurer ();         mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory" );         mapperScannerConfigurer.setBasePackage("com.example.mapper" );         return  mapperScannerConfigurer;     } } 
关闭DataSourceAutoConfiguration ,因为这里我们配置了数据源,所以需要关闭该自动配置,另外,MybatisAutoConfiguration 也是基于DataSourceAutoConfiguration 的,所以关闭了DataSourceAutoConfiguration 也就同时关闭了MybatisAutoConfiguration 。
Spring Boot中Atomikos与Mybatis多数据源集成方法 
pom 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 <dependency >     <groupId > org.springframework</groupId >      <artifactId > spring-jdbc</artifactId >      <version > 4.3.4.RELEASE</version >  </dependency > <dependency >     <groupId > org.mybatis</groupId >      <artifactId > mybatis</artifactId >      <version > 3.4.0</version >  </dependency > <dependency >     <groupId > org.mybatis</groupId >      <artifactId > mybatis-spring</artifactId >      <version > 1.3.0</version >  </dependency > <dependency >     <groupId > com.atomikos</groupId >      <artifactId > transactions-jdbc</artifactId >      <version > 4.0.4</version >  </dependency > <dependency >     <groupId > com.atomikos</groupId >      <artifactId > transactions-jta</artifactId >      <version > 4.0.4</version >  </dependency > <dependency >     <groupId > com.atomikos</groupId >      <artifactId > transactions</artifactId >      <version > 4.0.4</version >  </dependency > <dependency >     <groupId > com.atomikos</groupId >      <artifactId > atomikos-util</artifactId >      <version > 4.0.4</version >  </dependency > <dependency >     <groupId > javax.transaction</groupId >      <artifactId > jta</artifactId >      <version > 1.1</version >  </dependency > <dependency >     <groupId > mysql</groupId >      <artifactId > mysql-connector-java</artifactId >      <version > 5.1.37</version >  </dependency > 
MyBatisConfig 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 @Configuration @EnableTransactionManagement(proxyTargetClass = true) public  class  MyBatisConfig  {    @Value("${spring.datasource.driver-class-name}")      String driverClass;     @Value("${spring.datasource.url}")      String url;     @Value("${spring.datasource.username}")      String userName;     @Value("${spring.datasource.password}")      String passWord;     @Value("${spring.datasource.driver-class-name2}")      String driverClass2;     @Value("${spring.datasource.url2}")      String url2;     @Value("${spring.datasource.username2}")      String userName2;     @Value("${spring.datasource.password2}")      String passWord2;     @Bean(name = "userTransaction")      public  UserTransaction userTransaction ()  throws  Throwable {         UserTransactionImp  userTransactionImp  =  new  UserTransactionImp ();         userTransactionImp.setTransactionTimeout(10000 );         return  userTransactionImp;     }     @Bean(name = "atomikosTransactionManager", initMethod = "init", destroyMethod = "close")      public  TransactionManager atomikosTransactionManager ()  throws  Throwable {         UserTransactionManager  userTransactionManager  =  new  UserTransactionManager ();         userTransactionManager.setForceShutdown(true );         return  userTransactionManager;     }     @Bean(name = "transactionManager")      @DependsOn({ "userTransaction", "atomikosTransactionManager" })      public  PlatformTransactionManager transactionManager ()  throws  Throwable {         UserTransaction  userTransaction  =  userTransaction();         TransactionManager  atomikosTransactionManager  =  atomikosTransactionManager();         JtaTransactionManager  jtaTransactionManager  =  new  JtaTransactionManager (userTransaction, atomikosTransactionManager);         jtaTransactionManager.setAllowCustomIsolationLevels(true );         return  jtaTransactionManager;     }     @Bean(name = "dataSource", initMethod = "init", destroyMethod = "close")      public  DataSource dataSource ()  {         System.out.println("dataSource init" );         MysqlXADataSource  mysqlXaDataSource  =  new  MysqlXADataSource ();         mysqlXaDataSource.setUrl(url);         mysqlXaDataSource.setPassword(passWord);         mysqlXaDataSource.setUser(userName);         mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true );         AtomikosDataSourceBean  xaDataSource  =  new  AtomikosDataSourceBean ();         xaDataSource.setXaDataSource(mysqlXaDataSource);         xaDataSource.setUniqueResourceName("dataSource" );         xaDataSource.setMinPoolSize(10 );         xaDataSource.setPoolSize(10 );         xaDataSource.setMaxPoolSize(30 );         xaDataSource.setBorrowConnectionTimeout(60 );         xaDataSource.setReapTimeout(20 );         xaDataSource.setMaxIdleTime(60 );         xaDataSource.setMaintenanceInterval(60 );         return  xaDataSource;     }     @Bean(name = "dataSource2", initMethod = "init", destroyMethod = "close")      public  DataSource dataSource2 ()  {         System.out.println("dataSource2 init" );         MysqlXADataSource  mysqlXaDataSource  =  new  MysqlXADataSource ();         mysqlXaDataSource.setUrl(url2);         mysqlXaDataSource.setPassword(passWord2);         mysqlXaDataSource.setUser(userName2);         mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true );         AtomikosDataSourceBean  xaDataSource  =  new  AtomikosDataSourceBean ();         xaDataSource.setXaDataSource(mysqlXaDataSource);         xaDataSource.setUniqueResourceName("dataSource2" );         xaDataSource.setMinPoolSize(10 );         xaDataSource.setPoolSize(10 );         xaDataSource.setMaxPoolSize(30 );         xaDataSource.setBorrowConnectionTimeout(60 );         xaDataSource.setReapTimeout(20 );         xaDataSource.setMaxIdleTime(60 );         xaDataSource.setMaintenanceInterval(60 );         return  xaDataSource;     }          @Bean(name = "sqlSessionFactory")      public  SqlSessionFactory sqlSessionFactoryBean ()  {         SqlSessionFactoryBean  bean  =  new  SqlSessionFactoryBean ();         bean.setDataSource(dataSource());                  ResourcePatternResolver  resolver  =  new  PathMatchingResourcePatternResolver ();         try  {             bean.setMapperLocations(resolver.getResources("classpath:mapper/ds1/*.xml" ));             return  bean.getObject();         } catch  (Exception e) {             e.printStackTrace();             throw  new  RuntimeException (e);         }     }     @Bean(name = "sqlSessionTemplate")      public  SqlSessionTemplate sqlSessionTemplate ()  {         return  new  SqlSessionTemplate (sqlSessionFactoryBean());     }          @Bean(name = "sqlSessionFactory2")      public  SqlSessionFactory sqlSessionFactoryBean2 ()  {         SqlSessionFactoryBean  bean  =  new  SqlSessionFactoryBean ();         bean.setDataSource(dataSource2());         try  {             return  bean.getObject();         } catch  (Exception e) {             e.printStackTrace();             throw  new  RuntimeException (e);         }     }     @Bean(name = "sqlSessionTemplate2")      public  SqlSessionTemplate sqlSessionTemplate2 ()  {         return  new  SqlSessionTemplate (sqlSessionFactoryBean2());     } } 
MyBatisMapperScannerConfig 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Configuration @AutoConfigureAfter(MyBatisConfig.class) public  class  MyBatisMapperScannerConfig  {    @Bean      public  MapperScannerConfigurer mapperScannerConfigurer ()  {         MapperScannerConfigurer  mapperScannerConfigurer  =  new  MapperScannerConfigurer ();                  mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory" );                  mapperScannerConfigurer.setBasePackage("com.example.mapper.ds1" );         return  mapperScannerConfigurer;     }     @Bean      public  MapperScannerConfigurer mapperScannerConfigurer2 ()  {         MapperScannerConfigurer  mapperScannerConfigurer  =  new  MapperScannerConfigurer ();                  mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory2" );                  mapperScannerConfigurer.setBasePackage("com.example.mapper.ds2" );         return  mapperScannerConfigurer;     } } 
这里要说明的是,如果两个数据源下的Mapper起了相同的类名,虽然他们在不同的包路径下,启动也会报错了,因为默认注册Mapper时使用的是类名称(不含包名),此时可以在Mapper上加上**@Component(“personMapper”)**注解
写在后面的话 
Spring Boot为我们提供了大量的spring-boot-starter-xxx 来加快我们的开发流程,创建项目时就可以看到可供选择的各种spring-boot-starter-xxx ,那么这么多的spring-boot-starter-xxx ,我们是否都需要了解呢,如果项目中需要用到某一个功能,是否就应该加入这个spring-boot-starter-xxx 呢?
笔者人为,spring-boot-starter-xxx 提供的完整jar包依赖和自动配置固然很好,但是当我们要在项目中加入某一个功能时,作为开发人员,是应该清楚的知道该功能的依赖关系和配置逻辑的,所以并不一定需要引入SpringBoot的spring-boot-starter-xxx ,而且SpringBoot对这些spring-boot-starter-xxx 做的自动配置,如果我们并不熟悉和十分清楚,往往会给我们开发人员造成不明所以的困扰,所以,笔者建议,在对SpringBoot提供的某一个spring-boot-starter-xxx 所提供的功能并不十分清楚时,还是使用配置类的方式吧。
还有,由于某些自动配置类的激活是根据项目中是否包含某个class或容器中是否注册了某个bean,所以笔者建议,如果项目中引入了新的jar包,或者手工注册了某个bean,都要通过debug的方式查看是否开启了某个自动配置。
另外,本文代码只是为了辅助说明,比如DriverManagerDataSource 正式环境不建议使用,请更换为其它数据源,比如BasicDataSource 。
本文示例代码下载地址:https://github.com/hanqunfeng/SpringBootStudy