2025.02.10 작성
OS : Window
개발환경: IntelliJ IDEA
개발언어: Java
프레임워크: Spring Boot
객체(Object)와 관계형 데이터베이스(Relational Database) 간의 매핑을 자동화하는 기술.
✔ ORM이란?
데이터베이스의 테이블을 객체(Object)로 매핑하여 SQL 없이 자바 객체로 데이터를 다룰 수 있도록 해주는 기술.
JDBC + SQL을 직접 작성하는 것이 아니라, ORM을 사용하여 더 객체지향적으로 데이터베이스를 조작.
✔ ORM을 쓰면 좋은 점?
✅ SQL 의존성 감소 → 객체 중심의 코드 작성 가능.
✅ DB 변경 시 유지보수 쉬움 → 테이블 구조 변경 시 코드 변경 최소화.
✅ 생산성 향상 → SQL 작성 없이 save(), findById() 등의 메서드로 조작 가능.
자바에서 ORM을 사용하기 위한 표준 인터페이스.
✔ JPA란?
ORM을 구현하기 위한 자바 표준 API.
직접 SQL을 작성하는 것이 아니라, 객체와 관계형 데이터베이스를 자동으로 매핑.
Hibernate, EclipseLink, OpenJPA 같은 구현체들이 있음.
✔ JPA를 사용하면 좋은 점?
✅ SQL을 직접 쓰지 않아도 됨 → save(), findById() 같은 메서드 제공.
✅ DB 변경에 유연함 → SQL을 직접 수정할 필요 없음.
✅ JPQL 사용 가능 → 객체 중심의 쿼리 작성.
JPA의 대표적인 구현체(라이브러리).
✔ Hibernate란?
JPA를 구현한 가장 유명한 ORM 프레임워크.
SQL 대신 자바 객체로 DB를 조작할 수 있도록 지원.
JPA의 표준 API를 따르면서, 추가 기능도 제공함.
ORM은 객체와 DB를 매핑하는 개념 자체.
JPA는 ORM을 위한 자바 표준 API.
Hibernate는 JPA의 구현체 중 하나.
--> JPA는 ORM 기술을 제공하는 표준 인터페이스고, Hibernate는 이를 구현한 라이브러리!
@Entity
@Table(name = "tbl_memo")
@ToString
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Memo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long mno;
@Column(length = 200, nullable = false)
private String memoText;
}
@Entity: 해당 클래스가 JPA 엔티티(Entity, 즉 데이터베이스 테이블과 연결된 클래스)임을 선언.
데이터베이스의 테이블과 매핑됨.
@Table(name = "tbl_memo"): tbl_memo라는 이름의 테이블과 연결됨.
@ToString: toString() 메서드를 자동으로 생성해줌.
@Getter: 모든 필드에 대한 Getter 메서드를 자동으로 생성.
@Builder: Memo 객체를 빌더 패턴으로 생성할 수 있도록 지원.
@AllArgsConstructor: 모든 필드를 포함하는 생성자 자동 생성.
@NoArgsConstructor: 기본 생성자 자동 생성.
@Id: 기본 키(primary key) 지정.
@GeneratedValue(strategy = GenerationType.IDENTITY):
@Column(length = 200, nullable = false):
주입(Injection)이란?
"주입"이란 외부에서 객체를 자동으로 넣어주는 것(할당해주는 것).
스프링 프레임워크에서는 의존성 주입(Dependency Injection, DI)이라고도 부름.
👉 주입이 없으면? (직접 객체 생성)
보통 우리가 어떤 객체를 사용하려면 new 키워드로 직접 생성해야 함.
public class MemoService {
private MemoRepository memoRepository;
public MemoService() {
this.memoRepository = new MemoRepository(); // 직접 객체 생성
}
}
⛔ 문제점
이제 외부에서 객체를 넣어주는 방식(주입).
public class MemoService {
private MemoRepository memoRepository;
// 외부에서 MemoRepository를 주입받음 (생성자 주입)
public MemoService(MemoRepository memoRepository) {
this.memoRepository = memoRepository;
}
}
✅ 개선된 점
스프링에서는 @Autowired를 사용해서 객체를 자동으로 주입할 수 있음.
@Service
public class MemoService {
@Autowired // MemoRepository를 자동으로 주입
private MemoRepository memoRepository;
public void saveMemo() {
Memo memo = new Memo();
memo.setMemoText("스프링 주입 테스트");
memoRepository.save(memo);
}
}
🛠 동작 방식
@SpringBootTest
public class MemoRepositoryTests {
@Autowired
private MemoRepository memoRepository;
@Test
public void testClass() {
System.out.println(memoRepository.getClass().getName());
}
@Test
public void testInsertDummies() {
IntStream.rangeClosed(1, 100).forEach(i -> {
Memo memo = Memo.builder().memoText("Sample..." + i).build();
memoRepository.save(memo);
});
}
}
@SpringBootTest
Spring Boot의 테스트 환경을 제공하여 ApplicationContext를 로드함.
스프링 컨텍스트에서 MemoRepository를 자동으로 주입받을 수 있음.
@Autowired private MemoRepository memoRepository;
MemoRepository를 스프링이 자동으로 주입하여 사용할 수 있도록 함.
testClass()
@Test
public void testClass() {
System.out.println(memoRepository.getClass().getName());
}
testInsertDummies()
@Test
public void testInsertDummies() {
IntStream.rangeClosed(1, 100).forEach(i -> {
Memo memo = Memo.builder().memoText("Sample..." + i).build();
memoRepository.save(memo);
});
}
IntStream.rangeClosed(1, 100)을 사용하여 1부터 100까지 반복 실행.
Memo.builder().memoText("Sample..." + i).build();
- memoText 필드에 "Sample...1", "Sample...2", ..., "Sample...100" 값을 넣어 Memo 객체를 생성.
memoRepository.save(memo);
- 생성한 Memo 객체를 DB에 저장.
@Test
public void testSelect() {
Long mno = 99L; // 조회할 Memo의 ID 값 설정
Optional<Memo> result = memoRepository.findById(mno); // ID로 조회
System.out.println("----------------------");
if (result.isPresent()) { // 결과가 존재하면
Memo memo = result.get(); // Memo 객체 가져오기
System.out.println(memo); // Memo 객체 출력
}
}