JPA이전엔 JDBC, Spring JDBC를 주로 사용했습니다.
간단한 프로젝트를 생성하면서 JPA와 Hibernate의 필요성에 대한 고찰을 하겠습니다.
과정은 아래와 같습니다.
1. Spring Boot H2 Project 만들기
2. Spring JDBC 사용하기
3. JPA, Hibernate 사용해서 동일한 작업 하면서 차이점 알아보기
1. Spring Boot H2 Project 만들기
먼저, Spring 프로젝트를 생성합니다.
https://ride-dev.tistory.com/26
Spring Web, Spring JDBC, Spring JPA, H2 의존성을 추가합니다.
pom.xml에서 의존성을 확인할 수 있습니다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
이제 H2를 사용해보겠습니다.
H2 콘솔을 사용하거나 DB로 접근하기 위해 application.properties에 프로퍼티를 설정합니다.
spring.h2.console.enabled=true
프로젝트 시작 후,
localhost:8080/h2-console에 접속합니다.
h2 jdbc url에 대한 프로퍼티를 설정하지 않았기 때문에,
프로젝트를 실행할 때마다 동적으로 생성됩니다.
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.2.1)
2023-12-22T19:59:53.186+09:00 INFO 7730 --- [ main] c.s.s.l.LearnJpaAndHibernateApplication : Starting LearnJpaAndHibernateApplication using Java 17.0.6
2023-12-22T19:59:53.194+09:00 INFO 7730 --- [ main] c.s.s.l.LearnJpaAndHibernateApplication : No active profile set, falling back to 1 default profile: "default"
2023-12-22T19:59:54.126+09:00 INFO 7730 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode
2023-12-22T19:59:54.128+09:00 INFO 7730 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JDBC repositories in DEFAULT mode.
2023-12-22T19:59:54.148+09:00 INFO 7730 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 17 ms. Found 0 JDBC repository interfaces.
2023-12-22T19:59:54.169+09:00 INFO 7730 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode
2023-12-22T19:59:54.170+09:00 INFO 7730 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2023-12-22T19:59:54.174+09:00 INFO 7730 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 1 ms. Found 0 JPA repository interfaces.
2023-12-22T19:59:54.854+09:00 INFO 7730 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http)
2023-12-22T19:59:54.869+09:00 INFO 7730 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2023-12-22T19:59:54.870+09:00 INFO 7730 --- [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.17]
2023-12-22T19:59:54.926+09:00 INFO 7730 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2023-12-22T19:59:54.928+09:00 INFO 7730 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1633 ms
2023-12-22T19:59:54.972+09:00 INFO 7730 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2023-12-22T19:59:55.128+09:00 INFO 7730 --- [ main] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Added connection conn0: url=jdbc:h2:mem:f5d23b74-d5dc-4b11-a081-e010973ddbe0 user=SA
2023-12-22T19:59:55.130+09:00 INFO 7730 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2023-12-22T19:59:55.150+09:00 INFO 7730 --- [ main] o.s.b.a.h2.H2ConsoleAutoConfiguration : H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:f5d23b74-d5dc-4b11-a081-e010973ddbe0'
프로젝트를 실행할 때마다 동적인 jdbc url을 찾기에 번거로울 수 있습니다.
따라서 application.properties에 프로퍼티를 설정하여, url을 정적으로 만듭니다.
spring.datasource.url=jdbc:h2:mem:testdb
다시 로그인을 합니다.
정적 url로 액세스 할 수 있는 것을 확인했습니다.
2. Table 생성하기
src/main/resources 디렉토리에 schema.sql 파일을 생성합니다.
create table course
(
id bigint not null,
name varchar(255) not null,
author varchar(255) not null,
primary key (id)
);
이제, Spring Data JPA Starter를 활용할 때마다 자동으로 schema.sql 파일을 가져온 뒤 테이블을 생성하게 되었습니다.
H2-console에서 확인해보겠습니다.
테이블이 생성되었음을 확인할 수 있습니다.
3. Spring JDBC 사용하기
Spring JDBC를 사용해서 데이터를 삽입하고 COURSE Table에 있는 데이터를 삭제할 수 있습니다.
insert into course (id, name, author)
values(1, 'Learn Spring', 'ride');
select * from course;
delete from course where id=1;
JDBC와 Spring JDBC를 사용할 때 SQL 쿼리를 활용합니다.
public void deleteTodo(int id) {
PreparedStatement st = null;
try {
st = db.conn.prepareStatement("delete from todo where id=?");
st.setInt(1, id);
st.execute();
} catch (SQLException e) {
logger.fatal("Query Failed : ", e);
} finally {
if (st != null) {
try {st.close();}
catch (SQLException e) {}
}
}
}
Spring JDBC는 JDBC에 비해 상대적으로 적은 량의 Java 코드를 작성합니다.
public void deleteTodo(int id) {
jdbcTemplate.update("delete from todo where id=?", id);
}
4. Spring JDBC를 사용하여 데이터 삽입하기
삽입에 사용할 entity 클래스를 생성합니다.
public class Course {
private long id;
private String name;
private String author;
// constructor, getter and setter, toString
}
데이터 입력을 위한 Repository 클래스를 생성합니다.
그리고 삽입 및 삭제, 조회 쿼리를 작성합니다.
@Repository
public class CourseJdbcRepository {
@Autowired
private JdbcTemplate springJdbcTemplate;
private static String INSERT_QUERY =
"""
insert into course (id, name, author)
values(?, ?, ?);
""";
private static String DELETE_QUERY =
"""
delete from course
where id = ?;
""";
private static String SELECT_QUERY =
"""
select * from course
where id = ?;
""";
public void insert(Course course) {
springJdbcTemplate.update(INSERT_QUERY,
course.getId(), course.getName(), course.getAuthor());
}
public void delete(long id) {
springJdbcTemplate.update(DELETE_QUERY,
id);
}
public Course findById(long id) {
return springJdbcTemplate.queryForObject(SELECT_QUERY,
new BeanPropertyRowMapper<>(Course.class), id);
//ResultSet -> Bean 에 => Row Mapper =>
//id
}
}
쿼리문에 매개변수 값을 사용하기 위해 쿼리문의 값을 ?로 저정합니다.
쿼리의 반환값이 있는 경우, queryForObject 메서드를 사용하여
특정 객체를 생성합니다.
매개변수는 (쿼리문, 반환값을 매핑할 Bean, 쿼리의 매개변수)입니다.
애플리케이션이 실행될 때 쿼리를 실행하기 위해 CommandLineRunner를 활용합니다.
(Spring 애플리케이션 시작 시, 실행할 로직이 있다면 CommandLineRunner을 활용합니다)
CommandLineRunner를 활용할 수 있도록 구현 클래스를 생성하고,
@Component
public class CourseJdbcCommandLineRunner implements CommandLineRunner {
@Autowired
private CourseJdbcRepository repository;
@Override
public void run(String... args) throws Exception {
repository.insert(new Course(1, "Learn Spring", "ride"));
repository.insert(new Course(2, "Learn Spring JDBC", "ride"));
repository.insert(new Course(3, "Learn Spring JPA", "ride"));
repository.deleteById(1);
System.out.println(repository.findById(2));
System.out.println(repository.findById(3));
}
}
애플리케이션을 실행하여 아래와 같은 결과를 확인할 수 있습니다.
(상단에 있는 명령문에 먼저 실행됩니다)
Select문의 출력값은 아래와 같습니다.
Course{id=2, name='Learn Spring JDBC', author='ride'}
Course{id=3, name='Learn Spring JPA', author='ride'}
Spring JDBC를 활용하여 DB에 액세스해봤습니다.
'Java' 카테고리의 다른 글
[JPA, Hibernate] 시작하기 -3, JPA 와 Hibernate (0) | 2023.12.23 |
---|---|
[JPA, Hibernate] 시작하기 -2, JPA 및 Spring Data JPA 사용하기 (0) | 2023.12.23 |
[SpringBoot] Spring Boot vs. Spring vs. Spring MVC (0) | 2023.12.22 |
[SpringBoot] 프로덕션 환경 배포 준비하기(로깅, 모니터링, 구성관리) (0) | 2023.12.22 |
[SpringBoot] Spring Boot 목적, 프로젝트 생성(spring.io) (0) | 2023.12.21 |