org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is java.sql.SQLException: url not set
- 该问题是出现在使用spring将数据源配置文件引入到配置类里面的时候
spring将数据源配置文件引入到配置类的两种方式
方式一
- 方式一:创建一个数据源配置类,引入spring的配置类(不会出现数据无法注入的问题)
方式二
- 方式二:在spring的配置类里面,直接引入外部的数据源配置文件,如果在成员变量上进行注入,会出现无法注入的情况。
错误的原因分析
方式一
- import方式导入数据源配置类DataSourceConfig2,spring容器在初始化会创建DataSourceConfig2对象,也会初始化DataSourceConfig2类里面成员变量,就会通过spel表达式注入数据源文件的key对应的值。同时将配置了@Bean注解的返回对象存到容器里面
@PropertySource("classpath:db.properties") public class DataSourceConfig2 { @Value("${jdbc.driverClassName}") private String driverClassName; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String username; @Value("${jdbc.password}") private String password; @Bean("dataSource") public DataSource getDruidDataSource(){ DruidDataSource ds = new DruidDataSource(); ds.setDriverClassName(driverClassName); ds.setUrl(url); ds.setUsername(username); ds.setPassword(password); return ds; } } @Import({DataSourceConfig2.class}) @Configuration //spring的配置类里面引入DataSourceConfig2.class public class SpringConfigHand2 { }
方式二
- 原因:SpringConfigHand是一个配置类,spring容器不会创建SpringConfigHand对象,也就意味着不会对类中的成员变量进行赋值
- 解决方案:将通过@Value注入的数据配置到带@Bean注解的方法里面。
- 原因: spring容器会管理@Bean注解的方法的返回对象.
@Configuration @ComponentScan("com.hand.service") //导入外部配置文件 @Import(DataSourceConfig.class) public class SpringConfigHand2 { @Value("${jdbc.driver}") * String driver; @Value("${jdbc.url}") String url; @Value("${jdbc.username}") String username; @Value("${jdbc.password}") String password; /** * 通过@Bean将第三方的类初始化到容器中 * 通过@Value从外部配置文件中通过key获取的值赋值给属性 * @return 连接池对象 */ @Bean public DataSource getDataSource(){ //创建连接池对象 DruidDataSource dataSource = new DruidDataSource(); //给连接池对象的四个基本参数赋值 dataSource.setDriverClassName(driver); dataSource.setUsername(username); dataSource.setUrl(url); dataSource.setPassword(password); return dataSource; } @Bean public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){ SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean(); //设置模型类的别名扫描 ssfb.setTypeAliasesPackage("com.hand.entity"); //设置数据源:mybatis框架使用第三方的数据库连接池 ssfb.setDataSource(dataSource); return ssfb; } @Bean public MapperScannerConfigurer mapperScannerConfigurer(){ MapperScannerConfigurer msc = new MapperScannerConfigurer(); msc.setBasePackage("com.hand.dao"); return msc; } @Bean public PlatformTransactionManager createTransactionManager(DataSource dataSource){ DataSourceTransactionManager pt = new DataSourceTransactionManager(); pt.setDataSource(dataSource);//事务管理依赖底层的Connection. 从数据库连接池去connection return pt; } }
- 上述代码存在的问题就是在加载配置类的时候不会对成员变量进行赋值,所以就会出现url not set的错误。事实上,driver、url、username、password都没有set
- 解决办法:将通过@Value注入的数据配置到带@Bean注解的方法里面。即将代码上述代码的成员变量通过参数传递的方式传递给方法。
@Configuration @ComponentScan("com.hand.service") //导入外部配置文件 @Import(DataSourceConfig.class) public class SpringConfigHand2 { /** * 通过@Bean将第三方的类初始化到容器中 * 通过@Value从外部配置文件中通过key获取的值赋值给属性 * @return 连接池对象 */ @Bean public DataSource getDataSource(@Value("${jdbc.driver}") String driver, @Value("${jdbc.url}") String url, @Value("${jdbc.username}") String username, @Value("${jdbc.password}") String password){ //创建连接池对象 DruidDataSource dataSource = new DruidDataSource(); //给连接池对象的四个基本参数赋值 dataSource.setDriverClassName(driver); dataSource.setUsername(username); dataSource.setUrl(url); dataSource.setPassword(password); return dataSource; } @Bean public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){ SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean(); //设置模型类的别名扫描 ssfb.setTypeAliasesPackage("com.hand.entity"); //设置数据源:mybatis框架使用第三方的数据库连接池 ssfb.setDataSource(dataSource); return ssfb; } @Bean public MapperScannerConfigurer mapperScannerConfigurer(){ MapperScannerConfigurer msc = new MapperScannerConfigurer(); msc.setBasePackage("com.hand.dao"); return msc; } @Bean public PlatformTransactionManager createTransactionManager(DataSource dataSource){ DataSourceTransactionManager pt = new DataSourceTransactionManager(); pt.setDataSource(dataSource);//事务管理依赖底层的Connection. 从数据库连接池去connection return pt; } }
版权声明:本文为qq_63863019原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。