가수면

H2, JDBC, JPA, Hibernate 본문

Java

H2, JDBC, JPA, Hibernate

니비앙 2023. 12. 2. 02:15

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
Comments