- 커넥션이 미리 저장되어있는 풀에서 DataSource가 커넥션을 가져와서 시작
- 커넥션 사용 후 커넥션을 제거하는 것이 아니라, 다시 풀에 반환
// DI
private final DataSource dataSource;
try (
var connection = dataSource.getConnection();
var statement = connection.createStatement();
var resultSet = statement.executeQuery("select * from customers");
) {
implementation "org.springframework.boot:spring-boot-starter-jdbc"
@SpringJUnitConfig
class CustomerJdbcRepositoryTest {
@Configuration
@ComponentScan(
basePackages = {"com.devcourse.springorder.customer"}
)
static class Config {
@Bean
public DataSource dataSource() {
var dataSource = DataSourceBuilder.create()
.url("jdbc:mysql://localhost/order_mgmt")
.username("root")
.password("root1234!")
.type(HikariDataSource.class)
.build();
// HikariCP가 풀에 커넥션(스레드)를 100개 만들어두고 시작한다는 것을 확인하기 위한 코드
// Customer show status '%Threads%' 쿼리랑 함께 써서 확인할 수 있다.
dataSource.setMaximumPoolSize(1000);
dataSource.setMinimumIdle(100);
return dataSource;
}
}
// 위에 Configuration으로 등록해놨으므로 이제 Autowired 사용 가능 -> ComponentScan을 해주기 때문
@Autowired
CustomerJdbcRepository customerJdbcRepository;
@Autowired
DataSource dataSource;
}
@Override
public Optional<Customer> findByName(String name) {
List<Customer> list = new ArrayList<>();
try (
var connection = dataSource.getConnection();
var statement = connection.prepareStatement(쿼리);
) {
...
} catch (SQLException throwable) {
logger.error("Got error", e);
throw new RuntimeError(e);
}
}
→ 이 공통부분을 템플릿이 제공
private final DataSource dataSource;
private final JdbcTemplate jdbcTemplate;
private static final RowMapper<Customer> customerRowMapper = (resultSet, rowNum) -> {
var customerId = toUUID(resultSet.getBytes("customer_id"));
var customerName = resultSet.getString("name");
var email = resultSet.getString("email");
var lastLoginAt = resultSet.getTimestamp("last_login_at") != null ?
resultSet.getTimestamp("last_login_at").toLocalDateTime() : null;
var createdAt = resultSet.getTimestamp("created_at").toLocalDateTime();
return new Customer(customerId, customerName, email, lastLoginAt, createdAt);
};
public CustomerJdbcRepository(DataSource dataSource, JdbcTemplate jdbcTemplate) {
this.dataSource = dataSource;
this.jdbcTemplate = jdbcTemplate;
}
@Override
public List<Customer> findAll() {
return jdbcTemplate.query(SELECT_ALL_SQL, customerRowMapper);
}
이건 JdbcTemplate 이용해서 만든 DML
@Override
public Customer insert(Customer customer) {
var update = jdbcTemplate.update(INSERT_SQL,
customer.getCustomerId().toString().getBytes(),
customer.getName(),
customer.getEmail(),
Timestamp.valueOf(customer.getCreateAt())
);
if (update != 1) {
throw new RuntimeException("Nothing was inserted");
}
return customer;
}
@Override
public Customer update(Customer customer) {
var update = jdbcTemplate.update(UPDATE_NAME_BY_ID,
customer.getName(),
customer.getEmail(),
customer.getLastLoginAt() != null ? Timestamp.valueOf(customer.getLastLoginAt()) : null,
customer.getCustomerId().toString().getBytes()
);
if (update != 1) {
throw new RuntimeException("Nothing was updated");
}
return customer;
}
@Override
public List<Customer> findAll() {
return jdbcTemplate.query(SELECT_ALL_SQL, customerRowMapper);
}
@Override
public Optional<Customer> findById(UUID customerId) {
try {
return Optional.ofNullable(jdbcTemplate.queryForObject(SELECT_BY_ID_SQL, customerRowMapper, customerId.toString()));
} catch (EmptyResultDataAccessException e) {
logger.error("Got empty result", e);
return Optional.empty();
}
}
@Override
public Optional<Customer> findByName(String name) {
try {
return Optional.ofNullable(jdbcTemplate.queryForObject(SELECT_BY_NAME_SQL, customerRowMapper, name));
} catch (EmptyResultDataAccessException e) {
logger.error("Got empty result", e);
return Optional.empty();
}
}
@Override
public Optional<Customer> findByEmail(String email) {
try {
return Optional.ofNullable(jdbcTemplate.queryForObject(SELECT_BY_EMAIL_SQL, customerRowMapper, email));
} catch (EmptyResultDataAccessException e) {
logger.error("Got empty result", e);
return Optional.empty();
}
}
@Override
public void deleteAll() {
jdbcTemplate.update(DELETE_ALL_SQL);
}
@Override
public int count() {
return jdbcTemplate.queryForObject(SELECT_COUNT_ALL, Integer.class);
}
@Configuration
@ComponentScan(
basePackages = {"com.devcourse.springorder.customer"}
)
static class Config {
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}