1. 개요
이 튜토리얼에서는 Spring JDBC 모듈의 실제 사용 사례를 살펴볼 것입니다.
Spring JDBC의 모든 클래스는 4 개의 개별 패키지로 나뉩니다.
- core — JDBC의 핵심 기능. 이 패키지의 중요한 클래스에는 JdbcTemplate , SimpleJdbcInsert , SimpleJdbcCall 및 NamedParameterJdbcTemplate이 있습니다.
- datasource — 데이터 소스에 액세스하기위한 유틸리티 클래스입니다. 또한 Jakarta EE 컨테이너 외부에서 JDBC 코드를 테스트하기위한 다양한 데이터 소스 구현이 있습니다.
- object — 객체 지향 방식의 DB 액세스. 쿼리를 실행하고 결과를 비즈니스 개체로 반환 할 수 있습니다. 또한 비즈니스 개체의 열과 속성간에 쿼리 결과를 매핑합니다.
- 지원 — 코어 및 객체 패키지아래의 클래스에 대한 지원 클래스 (예 : SQLException 변환 기능 제공)
2. 구성
데이터 소스의 간단한 구성부터 시작하겠습니다.
MySQL 데이터베이스를 사용합니다.
@Configuration
@ComponentScan("com.baeldung.jdbc")
public class SpringJdbcConfig {
@Bean
public DataSource mysqlDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/springjdbc");
dataSource.setUsername("guest_user");
dataSource.setPassword("guest_password");
return dataSource;
}
}
또는 개발 또는 테스트를 위해 임베디드 데이터베이스를 잘 활용할 수도 있습니다.
다음은 H2 임베디드 데이터베이스의 인스턴스를 만들고 간단한 SQL 스크립트로 미리 채우는 빠른 구성입니다.
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("classpath:jdbc/schema.sql")
.addScript("classpath:jdbc/test-data.sql").build();
}
마지막으로 데이터 소스에 대한 XML 구성을 사용하여 동일한 작업을 수행 할 수 있습니다 .
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/springjdbc"/>
<property name="username" value="guest_user"/>
<property name="password" value="guest_password"/>
</bean>
3. JdbcTemplate 및 쿼리 실행
3.1. 기본 쿼리
JDBC 템플릿은 관심있는 대부분의 기능에 액세스 할 수있는 주요 API입니다.
- 연결 생성 및 종료
- 문 및 저장 프로 시저 호출 실행
- ResultSet 반복 및 결과 반환
먼저 JdbcTemplate 이 무엇을 할 수 있는지 알아보기 위해 간단한 예제로 시작해 보겠습니다 .
int result = jdbcTemplate.queryForObject(
"SELECT COUNT(*) FROM EMPLOYEE", Integer.class);
다음은 간단한 INSERT입니다.
public int addEmplyee(int id) {
return jdbcTemplate.update(
"INSERT INTO EMPLOYEE VALUES (?, ?, ?, ?)", id, "Bill", "Gates", "USA");
}
?를 사용하여 매개 변수를 제공하는 표준 구문에 주목하십시오 . 캐릭터.
다음으로이 구문의 대안을 살펴 보겠습니다.
3.2. 명명 된 매개 변수가있는 쿼리
명명 된 매개 변수에 대한 지원 을 얻기 위해 프레임 워크에서 제공하는 다른 JDBC 템플릿 인 NamedParameterJdbcTemplate을 사용 합니다.
또한 이것은 JbdcTemplate을 래핑하고 ?를 사용하는 기존 구문에 대한 대안을 제공합니다. 매개 변수를 지정합니다.
내부적으로는 명명 된 매개 변수를 JDBC ? 쿼리를 실행 하기 위해 래핑 된 JDCTemplate 에 대한 자리 표시 자 및 위임 :
SqlParameterSource namedParameters = new MapSqlParameterSource().addValue("id", 1);
return namedParameterJdbcTemplate.queryForObject(
"SELECT FIRST_NAME FROM EMPLOYEE WHERE ID = :id", namedParameters, String.class);
MapSqlParameterSource 를 사용 하여 명명 된 매개 변수의 값을 제공하는 방법을 확인하십시오.
명명 된 매개 변수를 결정하기 위해 Bean의 속성을 사용하는 방법을 살펴 보겠습니다.
Employee employee = new Employee();
employee.setFirstName("James");
String SELECT_BY_ID = "SELECT COUNT(*) FROM EMPLOYEE WHERE FIRST_NAME = :firstName";
SqlParameterSource namedParameters = new BeanPropertySqlParameterSource(employee);
return namedParameterJdbcTemplate.queryForObject(
SELECT_BY_ID, namedParameters, Integer.class);
이전과 같이 수동으로 명명 된 매개 변수를 지정하는 대신 BeanPropertySqlParameterSource 구현을 사용하는 방법에 유의하십시오 .
3.3. 쿼리 결과를 Java 개체에 매핑
또 다른 매우 유용한 기능은 RowMapper 인터페이스 를 구현하여 쿼리 결과를 Java 개체에 매핑하는 기능 입니다.
예를 들어, 쿼리에서 반환 된 모든 행에 대해 Spring은 행 매퍼를 사용하여 Java Bean을 채 웁니다.
public class EmployeeRowMapper implements RowMapper<Employee> {
@Override
public Employee mapRow(ResultSet rs, int rowNum) throws SQLException {
Employee employee = new Employee();
employee.setId(rs.getInt("ID"));
employee.setFirstName(rs.getString("FIRST_NAME"));
employee.setLastName(rs.getString("LAST_NAME"));
employee.setAddress(rs.getString("ADDRESS"));
return employee;
}
}
그 후, 이제 행 매퍼를 쿼리 API에 전달하고 완전히 채워진 Java 객체를 가져올 수 있습니다.
String query = "SELECT * FROM EMPLOYEE WHERE ID = ?";
Employee employee = jdbcTemplate.queryForObject(
query, new Object[] { id }, new EmployeeRowMapper());
4. 예외 번역
Spring은 기본적 으로 DataAccessException 을 루트 예외로 사용하는 자체 데이터 예외 계층 구조와 함께 제공되며 모든 기본 원시 예외를 여기로 변환합니다.
따라서 우리는 저수준 지속성 예외를 처리하지 않음으로써 온 전성을 유지합니다. 또한 Spring이 DataAccessException 또는 하위 클래스 중 하나 에서 저수준 예외를 래핑한다는 사실로부터 이익을 얻습니다 .
이것은 또한 우리가 사용하는 기본 데이터베이스와 독립적 인 예외 처리 메커니즘을 유지합니다.
기본 SQLErrorCodeSQLExceptionTranslator 외에도 SQLExceptionTranslator 의 자체 구현을 제공 할 수도 있습니다 .
다음은 사용자 지정 구현의 간단한 예입니다. 중복 키 위반이있을 때 오류 메시지를 사용자 지정 하여 H2를 사용할 때 오류 코드 23505 가 발생합니다 .
public class CustomSQLErrorCodeTranslator extends SQLErrorCodeSQLExceptionTranslator {
@Override
protected DataAccessException
customTranslate(String task, String sql, SQLException sqlException) {
if (sqlException.getErrorCode() == 23505) {
return new DuplicateKeyException(
"Custom Exception translator - Integrity constraint violation.", sqlException);
}
return null;
}
}
이 사용자 정의 예외 변환기를 사용하려면 setExceptionTranslator () 메서드를 호출 하여 JdbcTemplate 에 전달해야합니다 .
CustomSQLErrorCodeTranslator customSQLErrorCodeTranslator =
new CustomSQLErrorCodeTranslator();
jdbcTemplate.setExceptionTranslator(customSQLErrorCodeTranslator);
5. SimpleJdbc 클래스를 사용한 JDBC 작업
SimpleJdbc 클래스는 SQL 문을 구성하고 실행하는 쉬운 방법을 제공합니다. 이러한 클래스는 데이터베이스 메타 데이터를 사용하여 기본 쿼리를 작성합니다. 따라서 SimpleJdbcInsert 및 SimpleJdbcCall 클래스는 삽입 및 저장 프로 시저 호출을 실행하는 더 쉬운 방법을 제공합니다.
5.1. SimpleJdbcInsert
최소한의 구성으로 간단한 삽입 문을 실행하는 방법을 살펴 보겠습니다.
INSERT 문은 SimpleJdbcInsert 구성을 기반으로 생성됩니다 . 테이블 이름, 열 이름 및 값을 제공하기 만하면됩니다.
먼저 SimpleJdbcInsert를 만들어 보겠습니다 .
SimpleJdbcInsert simpleJdbcInsert =
new SimpleJdbcInsert(dataSource).withTableName("EMPLOYEE");
다음으로 열 이름과 값을 제공하고 작업을 실행 해 보겠습니다.
public int addEmplyee(Employee emp) {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("ID", emp.getId());
parameters.put("FIRST_NAME", emp.getFirstName());
parameters.put("LAST_NAME", emp.getLastName());
parameters.put("ADDRESS", emp.getAddress());
return simpleJdbcInsert.execute(parameters);
}
또한 executeAndReturnKey () API를 사용하여 데이터베이스가 기본 키를 생성 할 수 있습니다. 또한 실제 자동 생성 된 열을 구성해야합니다.
SimpleJdbcInsert simpleJdbcInsert = new SimpleJdbcInsert(dataSource)
.withTableName("EMPLOYEE")
.usingGeneratedKeyColumns("ID");
Number id = simpleJdbcInsert.executeAndReturnKey(parameters);
System.out.println("Generated id - " + id.longValue());
마지막으로 BeanPropertySqlParameterSource 및 MapSqlParameterSource를 사용하여이 데이터를 전달할 수도 있습니다 .
5.2. SimpleJdbcCall을 사용한 저장 프로 시저
저장 프로 시저 실행도 살펴 보겠습니다.
SimpleJdbcCall 추상화를 사용할 것입니다 .
SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(dataSource)
.withProcedureName("READ_EMPLOYEE");
public Employee getEmployeeUsingSimpleJdbcCall(int id) {
SqlParameterSource in = new MapSqlParameterSource().addValue("in_id", id);
Map<String, Object> out = simpleJdbcCall.execute(in);
Employee emp = new Employee();
emp.setFirstName((String) out.get("FIRST_NAME"));
emp.setLastName((String) out.get("LAST_NAME"));
return emp;
}
6. 배치 작업
또 다른 간단한 사용 사례는 여러 작업을 일괄 처리하는 것입니다.
6.1. JdbcTemplate을 사용한 기본 배치 작업
사용 JdbcTemplate을 , 일괄 작업은 비아 실행할 수 의 batchUpdate () API.
여기서 흥미로운 부분은 간결하지만 매우 유용한 BatchPreparedStatementSetter 구현입니다.
public int[] batchUpdateUsingJdbcTemplate(List<Employee> employees) {
return jdbcTemplate.batchUpdate("INSERT INTO EMPLOYEE VALUES (?, ?, ?, ?)",
new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
ps.setInt(1, employees.get(i).getId());
ps.setString(2, employees.get(i).getFirstName());
ps.setString(3, employees.get(i).getLastName());
ps.setString(4, employees.get(i).getAddress();
}
@Override
public int getBatchSize() {
return 50;
}
});
}
6.2. NamedParameterJdbcTemplate을 사용한 일괄 작업
NamedParameterJdbcTemplate – batchUpdate () API를 사용하여 작업을 일괄 처리하는 옵션도 있습니다 .
이 API는 이전 API보다 간단합니다. 따라서 매개 변수 값을 설정하기위한 내부 준비된 명령문 setter가 있으므로 매개 변수를 설정하기 위해 추가 인터페이스를 구현할 필요가 없습니다.
대신 매개 변수 값 을 SqlParameterSource 배열로 batchUpdate () 메서드에 전달할 수 있습니다 .
SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch(employees.toArray());
int[] updateCounts = namedParameterJdbcTemplate.batchUpdate(
"INSERT INTO EMPLOYEE VALUES (:id, :firstName, :lastName, :address)", batch);
return updateCounts;
7. 스프링 부트를 사용한 스프링 JDBC
Spring Boot는 관계형 데이터베이스와 함께 JDBC를 사용하기위한 스타터 spring-boot-starter-jdbc 를 제공합니다.
모든 Spring Boot 스타터와 마찬가지로 이것은 우리가 애플리케이션을 빠르게 시작하고 실행하는 데 도움이됩니다.
7.1. Maven 의존성
우리는해야합니다 스프링 부팅 스타터 JDBC 기본 하나 같은 의존성을. 또한 사용할 데이터베이스에 대한 의존성도 필요합니다. 우리의 경우 이것은 MySQL입니다 .
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
7.2. 구성
Spring Boot는 데이터 소스를 자동으로 구성합니다. 속성 파일에 속성을 제공하면 됩니다.
spring.datasource.url=jdbc:mysql://localhost:3306/springjdbc
spring.datasource.username=guest_user
spring.datasource.password=guest_password
그리고 그게 다야. 우리의 응용 프로그램은 이러한 구성 만 수행하여 실행됩니다. 이제 다른 데이터베이스 작업에 사용할 수 있습니다.
표준 Spring 애플리케이션에 대해 이전 섹션에서 본 명시 적 구성이 이제 Spring Boot 자동 구성의 일부로 포함됩니다.
8. 결론
이 기사에서 우리는 Spring Framework의 JDBC 추상화를 살펴 보았다. Spring JDBC에서 제공하는 다양한 기능을 실제 예제와 함께 다루었습니다.
또한 Spring Boot JDBC 스타터를 사용하여 Spring JDBC를 빠르게 시작하는 방법도 살펴 보았습니다.
- https://docs.spring.io/spring-framework/docs/current/reference/html
- https://www.baeldung.com/spring-jdbc-jdbctemplate
'Java' 카테고리의 다른 글
Java 8 forEach 사용방법 (0) | 2021.03.08 |
---|---|
JPA의 다 대다 관계 (0) | 2021.03.08 |
Java 경고 "Unchecked Cast" (0) | 2021.03.07 |
Spring Redirects 사용방법 (0) | 2021.03.07 |
Spring을 사용한 REST 오류 처리 (0) | 2021.03.07 |