가수면
H2, JDBC, JPA, Hibernate 본문
H2
인메모리 데이터베이스
1. H2 콘솔 사용 설정
// application.properties
spring.h2.console.enabled=true // H2 콘솔 사용 활성화
spring.datasource.url=jdbc:h2:mem:testdb // 고정된 url 생성
이후 http://localhost:8080/h2-console 접속 가능
JDBC URL에 콘솔에 있는 url을 입력한 뒤 연결
2-1. H2 테이블 생성
Spring Data JPA Starter를 활용할 때마다 가져올 schema.sql 만들기
sql에서는 큰 따옴표(")대신 작은 따옴표(')를 써야함
// src/main/resources/schema.sql
create table course
(
id bigint not null, // H2 콘솔에서 long 타입은 bigint 타입으로 매핑 됨. not null = null이 되면 안 된다.
name varchar(255) not null, // 데이터베이스에서 가변 가능한 문자열은 varchar(길이)로 표현
author varchar(255) not null,
primary key (id)
);
2-2. Entity 테이블에 sql로 초기 데이터 추가
sql은 Entity 테이블이 생성되기 전에 실행되기 때문에 설정을 해줘야 함
// application.properties
spring.jpa.defer-datasource-initialization=true
Spring JDBC를 활용해 데이터베이스 조작하기
JDBC - SQL쿼리를 사용하여 데이터베이스 테이블의 데이터를 조작하기 위한 것
JDBC vs Spring JDBC
JDBC - SQL 쿼리 많이 작성, Java 코드도 많이 작성
Spring JDBC - SQL 쿼리 많이 작성, Java 코드는 적게 작성
JDBC보다 Spring JDBC가 작성해야하는 코드가 훨씬 적어 개발 생산성을 높여줌
데이터 추가
1. 데이터 추가할 쿼리 작성
package com.in28minutes.springboot.learnjpaandhibernate.course.jdbc;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class CourseJdbcRepository {
@Autowired
private JdbcTemplate springJdbcTemplate; // Spring JDBC를 사용해 쿼리를 실행할 때 필요
private static String INSERT_QUERY =
// 하드 코딩
// """
// insert into course (id, name, author)
// values(1, 'Learn AWS', 'in28minutes');
// """;
"""
insert into course (id, name, author)
values(?, ?, ?);
""";
// 하드 코딩
// public void insert() {
// springJdbcTemplate.update(INSERT_QUERY);
// }
public void insert(Course course) {
springJdbcTemplate.update(INSERT_QUERY, course.getId(), course.getName(), course.getAuthor());
}
}
2. 게터 클래스 추가
3. 쿼리 실행시킬 클래스 추가
CommandLineRunner가 시작할 때 클래스를 실행하게 해줌
package com.in28minutes.springboot.learnjpaandhibernate.course.jdbc;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
// CourseJdbcRepository에서 설정한 쿼리를 실행시키기 위한 클래스
@Component
public class CourseJdbcCommandLineRunner implements CommandLineRunner {
@Autowired
private CourseJdbcRepository repository;
@Override
public void run(String... args) throws Exception {
// 하드 코딩일 때
// repository.insert();
repository.insert(new Course(1, "Learn AWS", "in28minutes"));
}
}
데이터 삭제
1. 데이터 삭제할 쿼리 작성
// CourseJdbcRepository
private static String DELETE_QUERY =
"""
delete from course
where id = ?
""";
public void deleteById(long id) {
springJdbcTemplate.update(DELETE_QUERY, id);
}
2. 쿼리 실행시킬 메소드 추가
// CourseJdbcCommandLineRunner
repository.insert(new Course(1, "Learn AWS", "in28minutes"));
repository.insert(new Course(2, "Learn Spring", "in28minutes"));
repository.insert(new Course(3, "Learn JAVA", "in28minutes"));
repository.deleteById(1);
데이터 불러오기
1. 데이터 불러올 쿼리 작성
queryForObject(sql 쿼리, Bean으로 매핑 ,인자) => 특정 객체를 생성
// CourseJdbcRepository
private static String SELECT_QUERY =
"""
select * from course
where id = ?
""";
public Course findById(long id) {
// queryForObject(sql 쿼리, Bean으로 매핑 ,인자) - 특정 객체를 생성
return springJdbcTemplate.queryForObject(SELECT_QUERY, new BeanPropertyRowMapper<>(Course.class), id);
}
2. 쿼리 실행시킬 메소드 추가
// CourseJdbcCommandLineRunner
repository.insert(new Course(1, "Learn AWS", "in28minutes"));
repository.insert(new Course(2, "Learn Spring", "in28minutes"));
repository.insert(new Course(3, "Learn JAVA", "in28minutes"));
repository.deleteById(1);
System.out.println(repository.findById(2));
System.out.println(repository.findById(3));
3. 세터 추가
불러오려면 게터에 추가로 세터가 필요함
JPA
JDBC처럼 쿼리를 사용하게 되면 Java코드는 적게 작성하지만 sql 때문에 코드가 길어짐
JPA를 사용하면 더 간결하게 데이터를 조작할 수 있음
1. Course 클래스 생성
JDBC 방식에서 @Entity추가와 @Id가 추가됨
Course Entity를 데이터베이스에 있는 Course 테이블로 매핑하는 방식
@Entity // @Entity(name="바꾸고 싶은 이름으로 테이블 이름 변경")도 가능
public class Course {
@Id
@GeneratedValue
private long id;
// @Column(name="name") 이처럼 이름이 테이블에 있는 것과 동일하다면 @Column 생략 가능
private String name;
// @Column(name="author") 즉, 속성은 @Column이 생략 가능함
private String author;
// 생성자
public Course() {
}
public Course(long id, String name, String author) {
super();
this.id = id;
this.name = name;
this.author = author;
}
// 게터, 세터
// toString
2. Entity 관리하는 Repository 생성
package com.in28minutes.springboot.learnjpaandhibernate.course.jpa;
import org.springframework.stereotype.Repository;
import com.in28minutes.springboot.learnjpaandhibernate.course.Course;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.transaction.Transactional;
@Repository
@Transactional // JPA로 쿼리를 실행하려고 할 때 필요
public class CourseJpaRepository {
@PersistenceContext // EntityManager에서 @Autowired역할을 하는 보다 구체적인 어노테이션
private EntityManager entityManager;
public void insert(Course course) {
entityManager.merge(course); // merge => 행을 삽입
}
public void deleteById(long id) {
Course course = entityManager.find(Course.class, id);
entityManager.remove(course);
}
public Course findById(long id) {
return entityManager.find(Course.class, id);
}
}
3. 쿼리 실행시킬 클래스 추가
package com.in28minutes.springboot.learnjpaandhibernate.course;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import com.in28minutes.springboot.learnjpaandhibernate.course.jdbc.CourseJdbcRepository;
import com.in28minutes.springboot.learnjpaandhibernate.course.jpa.CourseJpaRepository;
@Component
public class CourseCommandLineRunner implements CommandLineRunner {
@Autowired
private CourseJpaRepository repository;
@Override
public void run(String... args) throws Exception {
repository.insert(new Course(1, "Learn AWS", "in28minutes"));
repository.insert(new Course(2, "Learn Spring", "in28minutes"));
repository.insert(new Course(3, "Learn JAVA", "in28minutes"));
repository.deleteById(1);
System.out.println(repository.findById(2));
System.out.println(repository.findById(3));
}
}
4. JPA에서 실행되는 SQL 쿼리를 확인할 수 있는 설정 추가 (선택)
// application.properties
spring.jpa.show-sql=true // 생성된 SQL을 확인하기 위한 설정
Spring Data JPA
JPA보다 더 간결해짐;
1. 인터페이스 생성
말 그대로 생성만 하면 됨
필요 시 커스텀 메소드 추가할 수 있음
// JpaRepository<관리할 Entity, Id 타입>
public interface CourseSpringDataJpaRepository extends JpaRepository<Course, Long>{
// 커스텀 메소드 추가 가능
List<Course> findByAuthor(String author);
List<Course> findByName(String name);
}
2. Course 클래스 생성
JPA와 동일
3. 실행 코드 작성
package com.in28minutes.springboot.learnjpaandhibernate.course;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import com.in28minutes.springboot.learnjpaandhibernate.course.jdbc.CourseJdbcRepository;
import com.in28minutes.springboot.learnjpaandhibernate.course.jpa.CourseJpaRepository;
import com.in28minutes.springboot.learnjpaandhibernate.course.springdatajpa.CourseSpringDataJpaRepository;
@Component
public class CourseCommandLineRunner implements CommandLineRunner {
@Autowired
private CourseSpringDataJpaRepository repository;
@Override
public void run(String... args) throws Exception {
// Spring Data JPA에선 insert 대신 save를 사용. 삽입, 업데이트 둘 다 가능함
repository.save(new Course(1, "Learn AWS", "in28minutes"));
repository.save(new Course(2, "Learn Spring", "in28minutes"));
repository.save(new Course(3, "Learn JAVA", "in28minutes"));
repository.deleteById(1l); // 숫자 + l => long 타입
System.out.println(repository.findById(2l));
System.out.println(repository.findById(3l));
System.out.println(repository.findByAuthor("in28minutes"));
System.out.println(repository.findByName("Learn AWS"));
}
}
Hibernate
JPA - 객체를 테이블로 매핑하는 방식을 정의 (API)
Hibernate - JPA 코드를 구현하는 구현체
'Java' 카테고리의 다른 글
JSP (0) | 2023.12.02 |
---|---|
어노테이션 정리 (0) | 2023.12.02 |
[Spring Boot] 기본 (0) | 2023.12.01 |
[Spring] 심화 (0) | 2023.11.30 |
[Spring] 기본 (0) | 2023.11.29 |