Spring Boot 之JDBCTemplate
describe
Spring's database operations are deeply encapsulated on jdbc. Using spring's injection function, DataSource can be registered in JdbcTemplate. JdbcTemplate provides a more abstract encapsulation based on the JDBC API and provides transaction management capabilities based on method annotations. By using the SpringBoot auto-configuration feature and auto-configuring beans instead of us. In maven, we need to add the spring-boot-starter-jdbc module
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
This module does the following for us
1. tomcat-jdbc-{version}.jar automatically configures DataSource for us.
2. If you do not define any DataSource, SpringBoot will automatically configure an in-memory database resource setting
3. If none of the beans are set, SpringBoot will automatically register it
4. Initialize the database
Connect Datasource, several key parameters
1. Database driver: spring.datasource.driverClassName=com.mysql.jdbc.Driver
2. The URL to connect to the database: spring.datasource.url=jdbc:mysql://office2.cherrypicks.com:18266/hsbc_payme_uat?
characterEncoding=UTF8
3. Connect to database userName: spring.datasource.username=root
4. Connect to the database Password: spring.datasource.pwd=577679F7D1DC6731FD4A38398FBF8F52
The process of connecting to Datasource and accessing the database
custom data source
First exclude the default configuration dataSource of tomcat-jdbc
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
</exclusion>
</exclusions>
</dependency>
Datasource configuration class
package com.cherrypicks.hsbcpayme.cs.config;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.cherrypicks.hsbcpayme.service.EncryptionService;
@Configuration
@EnableTransactionManagement
public class DataSourceConfig {
// read parameters from properties
@Value("${spring.datasource.driverClassName}")
private String driverClassName;
@Value("${spring.datasource.url}")
private String url;
@Value("${spring.datasource.username}")
private String userName;
@Value("${spring.datasource.pwd}")
private String pwd;
@Value("${srping.datasource.initialSize}")
private Integer initialSize;
@Value("${spring.datasource.maxActive}")
private Integer maxActive;
@Autowired
private EncryptionService encryptionService;
// system data source
@Bean
@Primary
public DataSource dataSource() throws Exception {
return tomcatPoolingDataSource();
}
@Bean
public JdbcTemplate jdbcTemplate() throws Exception {
return new JdbcTemplate(dataSource());
}
private DataSource tomcatPoolingDataSource() throws Exception {
final org.apache.tomcat.jdbc.pool.DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(userName);
dataSource.setPassword(encryptionService.cherrypicksDecryption(pwd));
dataSource.setInitialSize(initialSize); // The number of initial connections created when the connection pool starts (default value is 0)
dataSource.setMaxActive(maxActive); // The maximum number of simultaneous connections in the connection pool
dataSource.setMaxIdle(5); // The maximum number of idle connections in the connection pool, the excess idle connections will be released, if set to a negative number, it means unlimited
dataSource.setMinIdle(0); // The minimum number of idle connections in the connection pool, below this number a new connection will be created
dataSource.setMaxWait(60000); // Maximum waiting time. When there is no available connection, the connection pool will wait for the maximum time for connection release. If the time limit is exceeded, an exception will be thrown. If -1 is set, it means infinite waiting
dataSource.setRemoveAbandonedTimeout(180); // When the time limit is exceeded, useless (abandoned) connections are recycled
dataSource.setRemoveAbandoned(true); // Whether to recycle useless connections (abandoned) after removeAbandonedTimeout is exceeded
dataSource.setTestOnBorrow(true);
dataSource.setTestOnReturn (true);
dataSource.setTestWhileIdle(true);
dataSource.setValidationQuery("SELECT 1");
dataSource.setTimeBetweenEvictionRunsMillis(1000 * 60 * 30); // The interval for checking invalid connections is set to 30 minutes
return dataSource;
}
}
Spring Boot startup class
package com.cherrypicks.hsbcpayme.cs;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.annotation.Import;
import com.cherrypicks.hsbcpayme.cs.config.DataSourceConfig;
import com.cherrypicks.hsbcpayme.cs.config.WebConfig;
@SpringBootApplication
@Import({WebConfig.class, DataSourceConfig.class})
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(final SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(final String[] args) {
final SpringApplication app = new SpringApplication(Application.class);
// app.setBannerMode(Banner.Mode.OFF);
app.run(args);
}
}
@Import({WebConfig.class, DataSourceConfig.class})将Datasource配置加入进来
Model类
public class User
{
private Integer id;
private String name;
private String email;
public User()
{
}
public User(Integer id, String name, String email)
{
this.id = id;
this.name = name;
this.email = email;
}
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getEmail()
{
return email;
}
public void setEmail(String email)
{
this.email = email;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
'}';
}
}
持久层
package com.example.repositories;
import com.example.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.sql.*;
import java.util.List;
/**
* Created by tom on 2016/5/21.
*/
@Repository
public class UserRepository {
@Autowired
private JdbcTemplate jdbcTemplate;
@Transactional(readOnly = true)
public List<User> findAll() {
return jdbcTemplate.query("select * from users", new UserRowMapper());
}
@Transactional(readOnly = true)
public User findUserById(int id) {
return jdbcTemplate.queryForObject("select * from users where id=?", new Object[]{id}, new UserRowMapper());
}
public User create(final User user) {
final String sql = "insert into users(name,email) values(?,?)";
KeyHolder holder = new GeneratedKeyHolder();
jdbcTemplate.update(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection connection)
throws SQLException {
PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
ps.setString(1, user.getName());
ps.setString(2, user.getEmail());
return ps;
}
}, holder);
int newUserId = holder.getKey().intValue();
user.setId(newUserId);
return user;
}
public void delete(final Integer id) {
final String sql = "delete from users where id=?";
jdbcTemplate.update(sql,
new Object[]{id},
new int[]{java.sql.Types.INTEGER});
}
public void update(final User user) {
jdbcTemplate.update(
"update users set name=?,email=? where id=?",
new Object[]{user.getName(), user.getEmail(), user.getId()});
}
}
class UserRowMapper implements RowMapper<User> {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
user.setEmail(rs.getString("email"));
return user;
}
}
测试持久化类
import com.example.SpringBootJdbcDemoApplication;
import com.example.domain.User;
import com.example.repositories.UserRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
/**
* Created by tom on 2016/5/21.
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(SpringBootJdbcDemoApplication.class)
public class SpringBootJdbcDemoApplicationTests
{
Logger logger= LoggerFactory.getLogger(SpringBootJdbcDemoApplicationTests.class);
@Autowired
private UserRepository userRepository;
@Test public void testAll(){
findAllUsers();
findUserById();
createUser();
}
@Test
public void findAllUsers() {
List<User> users = userRepository.findAll();
assertNotNull(users);
assertTrue(!users.isEmpty());
}
@Test
public void findUserById() {
User user = userRepository.findUserById(1);
assertNotNull(user);
}
private void updateById(Integer id) {
User newUser = new User(id, "JackChen", "[email protected]");
userRepository.update(newUser);
User newUser2 = userRepository.findUserById(newUser.getId());
assertEquals(newUser.getName(), newUser2.getName());
assertEquals(newUser.getEmail(), newUser2.getEmail());
}
@Test
public void createUser() {
User user = new User(0, "tom", "[email protected]");
User savedUser = userRepository.create(user);
logger.debug("{}",savedUser);
User newUser = userRepository.findUserById(savedUser.getId());
assertEquals("tom", newUser.getName());
assertEquals("[email protected]", newUser.getEmail());
updateById(newUser.getId());
userRepository.delete(newUser.getId());
}
}