Spring 之 JDBC
Spring 之 JDBC
JDBC 是 Java 语言中用来规范客户端程序如何访问数据库的应用程序接口,提供了增、删、改、查数据库的方法。
JDBC 入门示例
JDBC 的工作步骤大致如下:
- 创建实体类。
- 声明数据库读写接口的 DAO 接口。定义 DAO 的好处在于对于数据层上层的业务,调用 DAO 时仅关注对外暴露的读写方法,而不考虑底层的具体持久化方式。这样,便于替换持久化方式。
- 创建一个 DAO 接口的实现类,使用 Spring 的 JDBC 模板去实现接口。
- 最后,定义一个 DAO 接口的实现类的 JavaBean,并将数据源注入进去。
假设,我们要通过 Spring + JDBC 访问一张 Mysql 数据表 user
,user
表的数据结构如下:
-- 创建用户表
CREATE TABLE `user` (
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID',
`name` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '用户名',
`age` INT(3) NOT NULL DEFAULT 0 COMMENT '年龄',
`address` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '地址',
`email` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '邮件',
PRIMARY KEY (`id`),
UNIQUE (`name`)
) COMMENT = '用户表';
INSERT INTO `user` (`name`, `age`, `address`, `email`)
VALUES ('张三', 18, '北京', '[email protected]');
INSERT INTO `user` (`name`, `age`, `address`, `email`)
VALUES ('李四', 19, '上海', '[email protected]');
定义实体
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.util.Objects;
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Long id;
private String name;
private Integer age;
private String address;
private String email;
}
定义 DAO 接口
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;
/**
* user 表 Dao 接口
*
* @author <a href="mailto:[email protected]">Zhang Peng</a>
* @since 2019-11-18
*/
public interface UserDao {
// DML
// -------------------------------------------------------------------
void insert(User user);
void batchInsert(List<User> users);
void deleteByName(String name);
void deleteAll();
void update(User user);
Integer count();
List<User> list();
User queryByName(String name);
JdbcTemplate getJdbcTemplate();
// DDL
// -------------------------------------------------------------------
void truncate();
void recreateTable();
}
定义 DAO 实现类
通过 JdbcTemplate
执行对应数据源符合语法的 SQL,即可完成各种数据库访问。
package io.github.dunwu.springboot.core.data.jdbc;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
/**
* user 表 Dao 接口实现类
*
* @author <a href="mailto:[email protected]">Zhang Peng</a>
* @since 2019-11-18
*/
@Repository
public class UserDaoImpl implements UserDao {
private JdbcTemplate jdbcTemplate;
public UserDaoImpl(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Override
public void insert(User user) {
jdbcTemplate.update("INSERT INTO user(name, age, address, email) VALUES(?, ?, ?, ?)",
user.getName(), user.getAge(), user.getAddress(), user.getEmail());
}
@Override
@Transactional(rollbackFor = Exception.class)
public void batchInsert(List<User> users) {
String sql = "INSERT INTO user(name, age, address, email) VALUES(?, ?, ?, ?)";
List<Object[]> params = new ArrayList<>();
users.forEach(user -> {
params.add(new Object[] { user.getName(), user.getAge(), user.getAddress(), user.getEmail() });
});
jdbcTemplate.batchUpdate(sql, params);
}
@Override
public void deleteByName(String name) {
jdbcTemplate.update("DELETE FROM user WHERE name = ?", name);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteAll() {
jdbcTemplate.execute("DELETE FROM user");
}
@Override
public void update(User user) {
jdbcTemplate.update("UPDATE user SET name=?, age=?, address=?, email=? WHERE id=?",
user.getName(), user.getAge(), user.getAddress(), user.getEmail(), user.getId());
}
@Override
public Integer count() {
try {
return jdbcTemplate.queryForObject("SELECT COUNT(*) FROM user", Integer.class);
} catch (EmptyResultDataAccessException e) {
return null;
}
}
@Override
public List<User> list() {
return jdbcTemplate.query("SELECT * FROM user", new BeanPropertyRowMapper<>(User.class));
}
@Override
public User queryByName(String name) {
try {
return jdbcTemplate.queryForObject("SELECT * FROM user WHERE name = ?",
new BeanPropertyRowMapper<>(User.class), name);
} catch (EmptyResultDataAccessException e) {
return null;
}
}
@Override
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
@Override
public void truncate() {
jdbcTemplate.execute("TRUNCATE TABLE user");
}
@Override
public void recreateTable() {
jdbcTemplate.execute("DROP TABLE IF EXISTS user");
String sqlStatement =
"CREATE TABLE IF NOT EXISTS user (\n"
+ " id BIGINT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'Id',\n"
+ " name VARCHAR(255) NOT NULL DEFAULT '' COMMENT '用户名',\n"
+ " age INT(3) NOT NULL DEFAULT 0 COMMENT '年龄',\n"
+ " address VARCHAR(255) NOT NULL DEFAULT '' COMMENT '地址',\n"
+ " email VARCHAR(255) NOT NULL DEFAULT '' COMMENT '邮件',\n"
+ " PRIMARY KEY (id)\n"
+ ") COMMENT = '用户表';";
jdbcTemplate.execute(sqlStatement);
}
}
测试类
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import java.util.ArrayList;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
@Slf4j
@Rollback
@SpringBootTest(classes = { SpringBootDataJdbcApplication.class })
public class DataJdbcMysqlDataSourceTest {
@Autowired
private UserDao userDAO;
@BeforeEach
public void before() {
userDAO.truncate();
}
@Test
public void insert() {
userDAO.insert(new User("张三", 18, "北京", "[email protected]"));
User linda = userDAO.queryByName("张三");
assertThat(linda).isNotNull();
}
@Test
public void batchInsert() {
List<User> users = new ArrayList<>();
users.add(new User("张三", 18, "北京", "[email protected]"));
users.add(new User("李四", 19, "上海", "[email protected]"));
users.add(new User("王五", 18, "南京", "[email protected]"));
users.add(new User("赵六", 20, "武汉", "[email protected]"));
userDAO.batchInsert(users);
int count = userDAO.count();
assertThat(count).isEqualTo(4);
List<User> list = userDAO.list();
assertThat(list).isNotEmpty().hasSize(4);
list.forEach(user -> {
log.info(user.toString());
});
}
@Test
public void delete() {
List<User> users = new ArrayList<>();
users.add(new User("张三", 18, "北京", "[email protected]"));
users.add(new User("李四", 19, "上海", "[email protected]"));
users.add(new User("王五", 18, "南京", "[email protected]"));
users.add(new User("赵六", 20, "武汉", "[email protected]"));
userDAO.batchInsert(users);
userDAO.deleteByName("张三");
User user = userDAO.queryByName("张三");
assertThat(user).isNull();
userDAO.deleteAll();
List<User> list = userDAO.list();
assertThat(list).isEmpty();
}
@Test
public void update() {
userDAO.insert(new User("张三", 18, "北京", "[email protected]"));
User oldUser = userDAO.queryByName("张三");
oldUser.setName("张三丰");
userDAO.update(oldUser);
User newUser = userDAO.queryByName("张三丰");
assertThat(newUser).isNotNull();
}
}
Spring Boot JDBC
引入 Spring Boot 依赖
你可以通过 Spring Boot 官方的初始化器(Spring Initializr)选择需要的组件来创建一个 Spring Boot 工程。或者,直接在 pom.xml 中引入所需要的依赖:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.7</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
配置数据源
引入依赖后,需要在 application.properties
或 application.yml
文件中指定数据源配置。
下面是一个最基本的数据源配置示例:
spring.datasource.url = jdbc:mysql://localhost:3306/spring_tutorial?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8
spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver
spring.datasource.username = root
spring.datasource.password = root
需要根据实际情况,替换 url
、username
、password
。
测试
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.jdbc.core.JdbcTemplate;
import java.sql.Connection;
import javax.sql.DataSource;
@Slf4j
@SpringBootApplication
public class SpringBootDataJdbcApplication implements CommandLineRunner {
private final JdbcTemplate jdbcTemplate;
public SpringBootDataJdbcApplication(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public static void main(String[] args) {
SpringApplication.run(SpringBootDataJdbcApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
DataSource dataSource = jdbcTemplate.getDataSource();
Connection connection;
if (dataSource != null) {
connection = dataSource.getConnection();
} else {
log.error("连接数据源失败!");
return;
}
if (connection != null) {
log.info("数据源 Url: {}", connection.getMetaData().getURL());
} else {
log.error("连接数据源失败!");
}
}
}
运行 main
方法后,控制台会输出以下内容,表示数据源连接成功:
20:50:18.449 [main] [INFO ] i.g.d.s.d.SpringBootDataJdbcApplication.run - 数据源 Url: jdbc:mysql://localhost:3306/spring_tutorial?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8
Spring JDBC
完整示例:spring-data-jdbc
spring-boot-starter-data-jdbc
引入了 spring-jdbc
,其 JDBC 特性就是基于 spring-jdbc
。
引入 Spring 依赖
在 pom.xml 中引入所需要的依赖:
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
</dependencies>
</project>
基于 JDBC 驱动的数据源配置
下面是一个 mysql 的 JDBC 数据源配置实例:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">
<!-- 引入配置文件 -->
<context:property-placeholder location="classpath:properties/mysql.properties" />
<!-- 使用JDBC驱动的数据源 -->
<!-- (1)在每个连接请求时都会返回一个新建的连接。性能不高 -->
<bean id="dataSource1" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- (2)在每个连接请求时都会返回同一个连接。不适用于多线程 -->
<bean id="dataSource2" class="org.springframework.jdbc.datasource.SingleConnectionDataSource">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- JDBC模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="dataSource1" />
</bean>
<bean id="userDao" class="io.github.dunwu.springboot.data.jdbc.UserDaoImpl">
<constructor-arg ref="jdbcTemplate" />
</bean>
<!-- 初始化数据表结构 -->
<jdbc:initialize-database data-source="dataSource1" ignore-failures="ALL">
<jdbc:script location="classpath:sql/schema.sql" />
<jdbc:script location="classpath:sql/data.sql" />
</jdbc:initialize-database>
</beans>
测试
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.io.IOException;
import java.sql.SQLException;
@SuppressWarnings("all")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:data/spring-mysql.xml" })
public class MysqlJdbcTest {
@Autowired
private ApplicationContext ctx;
@Before
public void before() {
ctx = JdbcDemo.getMysqlApplicationContext();
}
@Test
public void testExecJdbcOper() throws SQLException, IOException {
UserDao userDao = (UserDaoImpl) ctx.getBean("userDao");
JdbcDemo.execJdbcOper(userDao);
}
@After
public void after() {
((ClassPathXmlApplicationContext) ctx).close();
}
}
JdbcTemplate API
Spring 将数据访问的样板式代码提取到模板类中。Spring 提供了 3 个 JDBC 模板类:
JdbcTemplate
:最基本的 Spring JDBC 模板,这个模板支持最简单的 JDBC 数据库访问功能以及简单的索引参数查询。SimpleJdbcTemplate
:改模板类利用 Java 5 的一些特性,如自动装箱、泛型以及可变参数列表来简化 JDBC 模板的使用。NamedParameterJdbcTemplate
:使用该模板类执行查询时,可以将查询值以命名参数的形式绑定到 SQL 中,而不是使用简单的索引参数。
spring-jdbc
最核心的 API 无疑就是 JdbcTemplate
,可以说所有的 JDBC 数据访问,几乎都是围绕着这个类去工作的。Spring 对数据库的操作在 Jdbc 层面做了深层次的封装,利用依赖注入,把数据源配置装配到 JdbcTemplate
中,再由 JdbcTemplate
负责具体的数据访问。
JdbcTemplate
主要提供以下几类方法:
execute
方法:可以用于执行任何 SQL 语句,一般用于执行 DDL 语句;update
方法及batchUpdate
方法:update
方法用于执行新增、修改、删除等语句;batchUpdate
方法用于执行批处理相关语句;query
方法及queryForXXX
方法:用于执行查询相关语句;call
方法:用于执行存储过程、函数相关语句。
为了方便演示,以下增删改查操作都围绕一个名为 user 的表(该表的主键 id 是自增序列)进行,该表的数据实体如下:
public class User {
private Integer id;
private String name;
private Integer age;
// 省略 getter/setter
}
数据实体只要是一个纯粹的 Java Bean 即可,无需任何注解修饰。
execute 方法
使用 execute 执行 DDL 语句,创建一个名为 test 的数据库,并在此数据库下新建一个名为 user 的表。
public void recreateTable() {
jdbcTemplate.execute("DROP DATABASE IF EXISTS test");
jdbcTemplate.execute("CREATE DATABASE test");
jdbcTemplate.execute("USE test");
jdbcTemplate.execute("DROP TABLE if EXISTS user");
jdbcTemplate.execute("DROP TABLE if EXISTS user");
// @formatter:off
StringBuilder sb = new StringBuilder();
sb.append("CREATE TABLE user (id int (10) unsigned NOT NULL AUTO_INCREMENT,\n")
.append("name varchar (64) NOT NULL DEFAULT '',\n")
.append("age tinyint (3) NOT NULL DEFAULT 0,\n")
.append("PRIMARY KEY (ID));\n");
// @formatter:on
jdbcTemplate.execute(sb.toString());
}
update 方法
新增数据
public void insert(String name, Integer age) {
jdbcTemplate.update("INSERT INTO user(name, age) VALUES(?, ?)", name, age);
}
删除数据
public void delete(String name) {
jdbcTemplate.update("DELETE FROM user WHERE name = ?", name);
}
修改数据
public void update(User user) {
jdbcTemplate.update("UPDATE USER SET name=?, age=? WHERE id=?", user.getName(), user.getAge(), user.getId());
}
批处理
public void batchInsert(List<User> users) {
String sql = "INSERT INTO user(name, age) VALUES(?, ?)";
List<Object[]> params = new ArrayList<>();
users.forEach(item -> {
params.add(new Object[] {item.getName(), item.getAge()});
});
jdbcTemplate.batchUpdate(sql, params);
}
query 方法
查单个对象
public User queryByName(String name) {
try {
return jdbcTemplate
.queryForObject("SELECT * FROM user WHERE name = ?", new BeanPropertyRowMapper<>(User.class), name);
} catch (EmptyResultDataAccessException e) {
return null;
}
}
查多个对象
public List<User> list() {
return jdbcTemplate.query("select * from USER", new BeanPropertyRowMapper(User.class));
}
获取某个记录某列或者 count、avg、sum 等函数返回唯一值
public Integer count() {
try {
return jdbcTemplate.queryForObject("SELECT COUNT(*) FROM user", Integer.class);
} catch (EmptyResultDataAccessException e) {
return null;
}
}
SpringBoot JDBC 配置
JdbcTemplateAutoConfiguration 类
JdbcTemplateAutoConfiguration
是 JdbcTemplate
自动配置类,它负责实例化 JdbcTemplate
。
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ DataSource.class, JdbcTemplate.class })
@ConditionalOnSingleCandidate(DataSource.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
@EnableConfigurationProperties(JdbcProperties.class)
@Import({ JdbcTemplateConfiguration.class, NamedParameterJdbcTemplateConfiguration.class })
public class JdbcTemplateAutoConfiguration {
}
JdbcTemplateAutoConfiguration
类的源码解读:
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
表明JdbcTemplateAutoConfiguration
必须在DataSourceAutoConfiguration
执行完之后才开始工作,这意味着:JdbcTemplate
的初始化必须在DataSource
初始化之后。JdbcProperties
是JdbcTemplateAutoConfiguration
的配置选项类,允许使用者通过设置选项控制JdbcTemplate
初始化行为。@Import({ JdbcTemplateConfiguration.class, NamedParameterJdbcTemplateConfiguration.class })
表明引入JdbcTemplateConfiguration
、NamedParameterJdbcTemplateConfiguration
两个配置类,具体的实例化JdbcTemplate
的工作也是放在这两个配置中完成。
JdbcTemplateConfiguration 类
JdbcTemplateConfiguration
源码如下:
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(JdbcOperations.class)
class JdbcTemplateConfiguration {
@Bean
@Primary
JdbcTemplate jdbcTemplate(DataSource dataSource, JdbcProperties properties) {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
JdbcProperties.Template template = properties.getTemplate();
jdbcTemplate.setFetchSize(template.getFetchSize());
jdbcTemplate.setMaxRows(template.getMaxRows());
if (template.getQueryTimeout() != null) {
jdbcTemplate.setQueryTimeout((int) template.getQueryTimeout().getSeconds());
}
return jdbcTemplate;
}
}
JdbcTemplateConfiguration
源码解读:JdbcTemplateConfiguration
中根据 DataSource
和 JdbcProperties
实例化了一个 JdbcTemplate
。
NamedParameterJdbcTemplateConfiguration 类
NamedParameterJdbcTemplateConfiguration
源码如下:
@Configuration(proxyBeanMethods = false)
@ConditionalOnSingleCandidate(JdbcTemplate.class)
@ConditionalOnMissingBean(NamedParameterJdbcOperations.class)
class NamedParameterJdbcTemplateConfiguration {
@Bean
@Primary
NamedParameterJdbcTemplate namedParameterJdbcTemplate(JdbcTemplate jdbcTemplate) {
return new NamedParameterJdbcTemplate(jdbcTemplate);
}
}
NamedParameterJdbcTemplateConfiguration
源码解读:NamedParameterJdbcTemplateConfiguration
中根据 JdbcTemplate
实例化了一个 NamedParameterJdbcTemplate
。
spring-data-jdbc
Spring Data 项目包含了对 JDBC 的存储库支持,并将自动为 CrudRepository
上的方法生成 SQL。对于更高级的查询,提供了 @Query
注解。
当 classpath 上存在必要的依赖项时,Spring Boot 将自动配置 Spring Data 的 JDBC 存储库。它们可以通过 spring-boot-starter-data-jdbc
的单一依赖项添加到项目中。如有必要,可以通过将 @EnableJdbcRepositories
批注或 JdbcConfiguration
子类添加到应用程序来控制 Spring Data JDBC 的配置。
更多 Spring Data JDBC 细节,可以参考 Spring Data JDBC 官方文档。
解决 Could not autowire. No beans of 'JdbcTemplate' type found
解决 jdbcTemplate 红色下划线问题,会提示 Could not autowire. No beans of 'JdbcTemplate' type found
.
解决方法:
Configuration.java
@Component
public class Configuration {
@Resource
private Environment env;
@Bean
public DataSource dataSource() {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl(env.getProperty("spring.datasource.url"));
dataSource.setUsername(env.getProperty("spring.datasource.username"));
dataSource.setPassword(env.getProperty("spring.datasource.password"));
dataSource.setDriverClassName(env.getProperty("spring.datasource.driver-class-name"));
dataSource.setPoolName(env.getProperty("spring.datasource.hikari.pool-name"));
dataSource.setMaximumPoolSize(Integer.parseInt(Objects.requireNonNull(env.getProperty("spring.datasource.hikari.maximum-pool-size"))));
dataSource.setMinimumIdle(Integer.parseInt(Objects.requireNonNull(env.getProperty("spring.datasource.hikari.minimum-idle"))));
dataSource.setConnectionTimeout(Long.parseLong(Objects.requireNonNull(env.getProperty("spring.datasource.hikari.connection-timeout"))));
dataSource.setIdleTimeout(Long.parseLong(Objects.requireNonNull(env.getProperty("spring.datasource.hikari.idle-timeout"))));
dataSource.setMaxLifetime(Long.parseLong(Objects.requireNonNull(env.getProperty("spring.datasource.hikari.max-lifetime"))));
return dataSource;
}
@Bean
public JdbcTemplate getJdbcTemplate(DataSource dataSource){
return new JdbcTemplate(dataSource);
}
}