Spring JdbcTemplate은 Spring JDBC 패키지에서 가장 중요한 클래스입니다.
Spring JdbcTemplate
- JDBC는 데이터베이스에 연결을 열고 닫는 등의 보일러 플레이트 코드를 많이 생성합니다. 이로 인해 코드가 극도로 번잡 스러워지고 읽기 어려워집니다.
- 스프링 프레임워크에서 JDBC를 구현하면 많은 저수준 작업(연결 열기/닫기, SQL 쿼리 실행 등)을 처리할 수 있습니다.Spring Framework
- 이 덕분에 스프링 프레임워크에서 데이터베이스 작업을 할 때 데이터베이스와의 연결 매개변수만 정의하고 SQL 쿼리를 등록하면 스프링이 대신 나머지 작업을 처리합니다.
- 스프링의 JDBC에는 데이터베이스와 상호 작용하기 위한 여러 클래스(여러 접근 방식)가 있습니다. 이 중 가장 일반적인 것은
JdbcTemplate
클래스를 사용하는 것입니다. 이 클래스는 모든 이벤트 및 데이터베이스 연결 처리를 관리하는 기본 클래스입니다. - JdbcTemplate 클래스는 SQL 쿼리를 실행하고
ResultSet
을 반복하며 호출된 값들을 검색하고 명령을 업데이트하고 프로시저 호출을 수행하며 예외를 “catch”하고org.springframwork.dao
패키지에서 정의된 예외로 변환합니다. - JdbcTemplate 클래스의 인스턴스는 스레드 안전합니다. 이는 JdbcTemplate 클래스의 단일 인스턴스를 구성함으로써 여러 개의 DAO 객체에서 사용할 수 있음을 의미합니다.
- JdbcTemplate을 사용할 때 대부분 Spring 구성 파일에서 구성됩니다. 그 후 DAO 클래스에서 빈으로 구현됩니다.
Spring JdbcTemplate 예제
Spring JdbcTemplate 예제 프로그램을 살펴보겠습니다. 여기에서는 Postgresql 데이터베이스를 사용하지만 MySQL이나 Oracle과 같은 다른 관계형 데이터베이스를 사용할 수도 있습니다. 데이터베이스 구성을 변경하면 작동할 수 있습니다. 먼저 작업할 샘플 데이터가 필요합니다. 아래 SQL 쿼리는 사용할 몇 가지 데이터로 테이블을 생성하고 채웁니다.
create table people (
id serial not null primary key,
first_name varchar(20) not null,
last_name varchar(20) not null,
age integer not null
);
insert into people (id, first_name, last_name, age) values
(1, 'Vlad', 'Boyarskiy', 21),
(2,'Oksi', ' Bahatskaya', 30),
(3,'Vadim', ' Vadimich', 32);
아래 이미지는 Eclipse에서 최종 프로젝트 구조를 보여줍니다.
Spring JDBC Maven 종속성
우리는 다음 종속성이 필요합니다 – spring-core
, spring-context
, spring-jdbc
, 그리고 postgresql
. 만약 MySQL과 같은 다른 관계형 데이터베이스를 사용 중이라면, 해당하는 자바 드라이버 종속성을 추가하세요. 다음은 우리의 최종 pom.xml 파일입니다.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.journaldev.spring</groupId>
<artifactId>JdbcTemplate</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<spring.framework>4.3.0.RELEASE</spring.framework>
<postgres.version>42.1.4</postgres.version>
</properties>
<dependencies>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgres.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.framework}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.framework}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.framework}</version>
</dependency>
</dependencies>
</project>
Spring DataSource 구성
다음 단계는 DataSource
빈을 정의하기 위해 스프링 구성 클래스를 생성하는 것입니다. 저는 자바 기반 구성을 사용하고 있지만, 스프링 빈 구성 XML 파일을 사용하여도 동일하게 할 수 있습니다.
package com.journaldev.spring.config;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
@Configuration
@ComponentScan("com.journaldev.spring")
@PropertySource("classpath:database.properties")
public class AppConfig {
@Autowired
Environment environment;
private final String URL = "url";
private final String USER = "dbuser";
private final String DRIVER = "driver";
private final String PASSWORD = "dbpassword";
@Bean
DataSource dataSource() {
DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
driverManagerDataSource.setUrl(environment.getProperty(URL));
driverManagerDataSource.setUsername(environment.getProperty(USER));
driverManagerDataSource.setPassword(environment.getProperty(PASSWORD));
driverManagerDataSource.setDriverClassName(environment.getProperty(DRIVER));
return driverManagerDataSource;
}
}
- @Configuration – 이 클래스는 스프링 컨텍스트를 위한 구성임을 나타냅니다.
- @ComponentScan(“com.journaldev.spring”)- 컴포넌트 클래스를 스캔할 패키지를 지정합니다.
- @PropertySource(“classpath:database.properties”)- 속성은 database.properties 파일에서 읽힐 것이라고 명시합니다.
database.properties
파일의 내용은 아래에 표시되어 있습니다.
driver=org.postgresql.Driver
url=jdbc:postgresql://127.0.0.1:5432/school
dbuser=postgres
dbpassword=postgres
만약 MySQL이나 다른 관계형 데이터베이스를 사용하고 있다면, 위의 구성을 그에 맞게 변경하세요.
Spring JDBC 모델 클래스
다음 단계는 데이터베이스 테이블을 매핑하는 모델 클래스를 생성하는 것입니다.
package com.journaldev.model;
public class Person {
private Long id;
private Integer age;
private String firstName;
private String lastName;
public Person() {
}
public Person(Long id, Integer age, String firstName, String lastName) {
this.id = id;
this.age = age;
this.firstName = firstName;
this.lastName = lastName;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Override
public String toString() {
return "Person{" + "id=" + id + ", age=" + age + ", firstName='" + firstName + '\'' + ", lastName='" + lastName
+ '\'' + '}';
}
}
데이터베이스에서 데이터를 가져 오려면 인터페이스 RowMapper
를 구현해야합니다. 이 인터페이스에는 하나의 메서드 mapRow(ResultSet resultSet, int i)
만 있으며 이 메서드는 모델 클래스의 인스턴스 하나를 반환합니다(예: Person).
package com.journaldev.model;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
public class PersonMapper implements RowMapper<Person> {
public Person mapRow(ResultSet resultSet, int i) throws SQLException {
Person person = new Person();
person.setId(resultSet.getLong("id"));
person.setFirstName(resultSet.getString("first_name"));
person.setLastName(resultSet.getString("last_name"));
person.setAge(resultSet.getInt("age"));
return person;
}
}
Spring JDBC DAO 클래스
마지막 단계는 SQL 쿼리를 사용하여 모델 클래스를 데이터베이스 테이블에 매핑하는 DAO 클래스를 생성하는 것입니다. 또한 @Autowired
주석을 사용하여 DataSource를 구성하고 일부 API를 노출합니다.
package com.journaldev.spring.dao;
import java.util.List;
import com.journaldev.model.Person;
public interface PersonDAO {
Person getPersonById(Long id);
List<Person> getAllPersons();
boolean deletePerson(Person person);
boolean updatePerson(Person person);
boolean createPerson(Person person);
}
package com.journaldev.spring.dao;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import com.journaldev.model.Person;
import com.journaldev.model.PersonMapper;
@Component
public class PersonDAOImpl implements PersonDAO {
JdbcTemplate jdbcTemplate;
private final String SQL_FIND_PERSON = "select * from people where id = ?";
private final String SQL_DELETE_PERSON = "delete from people where id = ?";
private final String SQL_UPDATE_PERSON = "update people set first_name = ?, last_name = ?, age = ? where id = ?";
private final String SQL_GET_ALL = "select * from people";
private final String SQL_INSERT_PERSON = "insert into people(id, first_name, last_name, age) values(?,?,?,?)";
@Autowired
public PersonDAOImpl(DataSource dataSource) {
jdbcTemplate = new JdbcTemplate(dataSource);
}
public Person getPersonById(Long id) {
return jdbcTemplate.queryForObject(SQL_FIND_PERSON, new Object[] { id }, new PersonMapper());
}
public List<Person> getAllPersons() {
return jdbcTemplate.query(SQL_GET_ALL, new PersonMapper());
}
public boolean deletePerson(Person person) {
return jdbcTemplate.update(SQL_DELETE_PERSON, person.getId()) > 0;
}
public boolean updatePerson(Person person) {
return jdbcTemplate.update(SQL_UPDATE_PERSON, person.getFirstName(), person.getLastName(), person.getAge(),
person.getId()) > 0;
}
public boolean createPerson(Person person) {
return jdbcTemplate.update(SQL_INSERT_PERSON, person.getId(), person.getFirstName(), person.getLastName(),
person.getAge()) > 0;
}
}
PersonDAOImpl
클래스는 @Component
주석으로 주석이 달려 있으며 이 클래스에는 JdbcTemplate
유형의 필드가 있습니다. 이 클래스의 생성자가 호출 될 때 DataSource의 인스턴스가 주입되고 JdbcTemplate의 인스턴스를 만들 수 있습니다. 그 후에 우리는 우리의 메서드에서 사용할 수 있습니다.
Spring JdbcTemplate 테스트 프로그램
저희 Spring JdbcTemplate 예제 프로젝트가 준비되었습니다. 이를 테스트 클래스로 테스트해 보겠습니다.
package com.journaldev;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.journaldev.model.Person;
import com.journaldev.spring.config.AppConfig;
import com.journaldev.spring.dao.PersonDAO;
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
PersonDAO personDAO = context.getBean(PersonDAO.class);
System.out.println("List of person is:");
for (Person p : personDAO.getAllPersons()) {
System.out.println(p);
}
System.out.println("\nGet person with ID 2");
Person personById = personDAO.getPersonById(2L);
System.out.println(personById);
System.out.println("\nCreating person: ");
Person person = new Person(4L, 36, "Sergey", "Emets");
System.out.println(person);
personDAO.createPerson(person);
System.out.println("\nList of person is:");
for (Person p : personDAO.getAllPersons()) {
System.out.println(p);
}
System.out.println("\nDeleting person with ID 2");
personDAO.deletePerson(personById);
System.out.println("\nUpdate person with ID 4");
Person pperson = personDAO.getPersonById(4L);
pperson.setLastName("CHANGED");
personDAO.updatePerson(pperson);
System.out.println("\nList of person is:");
for (Person p : personDAO.getAllPersons()) {
System.out.println(p);
}
context.close();
}
}
아래 이미지는 위 프로그램을 실행할 때 생성된 출력을 보여줍니다. 출력은 샘플 데이터에 따라 다르며 여러 번 실행할 때도 다를 수 있습니다. 여기서는 예제 프로그램을 통해 Spring JdbcTemplate을 사용하는 방법을 배우는 것입니다. 이것이 Spring JdbcTemplate에 관한 전부입니다. 최종 프로젝트는 아래 링크에서 다운로드할 수 있습니다.
Spring JdbcTemplate 예제 프로젝트 다운로드
참고: API 문서
Source:
https://www.digitalocean.com/community/tutorials/spring-jdbctemplate-example