JPA란? (feat. ORM)
by 볼빵빵오춘기JPA (Java Persistence API)
JPA는 자바 애플리케이션에서 데이터베이스와 상호작용하는 방식을 표준화한 것 이다.
이를 통해 개발자는 데이터베이스 테이블을 자바 객체에 매핑하고, 객체지향적으로 데이터베이스를 다룰 수 있다.
JPA는 인터페이스의 모음으로, JPA를 구현한 ORM 프레임워크 (예: Hibernate)를 사용하여 실제 동작을 수행한다.
ORM (Object-Relational Mapping)
ORM은 객체 지향 프로그래밍 언어의 객체를 관계형 데이터베이스의 테이블에 매핑하는 기술이다.
이를 통해 객체 지향 프로그래밍 패러다임을 유지하면서 데이터베이스 작업을 할 수 있다.
ORM은 데이터베이스의 구조와 객체 지향 언어의 구조 간의 불일치를 해결해주어, 개발자가 객체 모델을 통해 데이터베이스를 직관적으로 다룰 수 있게 한다.
ORM의 장점
객체 지향 프로그래밍
객체 모델을 사용하여 데이터베이스와 상호작용하므로, 객체 지향 프로그래밍 패러다임을 유지할 수 있다.
객체와 데이터베이스 간의 불일치를 해결하여, 개발자는 더 직관적이고 유지 보수가 쉬운 코드를 작성할 수 있다.
자동화된 매핑
- 엔티티 클래스를 데이터베이스 테이블에 자동으로 매핑하여, 수작업으로 SQL을 작성하는 번거로움을 줄여준다.
- 매핑 설정을 통해 객체와 데이터베이스 필드 간의 변환을 자동으로 처리한다.
데이터베이스 독립성
JPA를 사용하면 특정 데이터베이스에 종속되지 않고, 다른 데이터베이스로 쉽게 변경할 수 있다.
⇒ 애플리케이션 이식성이 높아진다.
생산성 향상
- CRUD(Create, Read, Update, Delete) 작업을 간편하게 처리할 수 있는 API를 제공하여, 개발 생산성을 크게 향상시킨다.
- 복잡한 쿼리도 메서드 이름만으로 생성할 수 있으며, 필요 시 JPQL(Java Persistence Query Language)을 사용하여 직접 작성할 수 있다.
트랜잭션 관리
JPA는 트랜잭션 관리를 자동으로 처리해주어, 일관성과 무결성을 유지하면서 데이터베이스 작업을 수행할 수 있다.
⇒ 개발자는 비즈니스 로직에 집중할 수 있다.
캐시 및 성능 최적화
- JPA는 1차 캐시(엔티티 매니저 레벨)와 2차 캐시(애플리케이션 레벨)를 제공하여 데이터베이스 액세스를 최소화하고 성능을 최적화한다.
- 지연 로딩(Lazy Loading)과 즉시 로딩(Eager Loading)을 통해 필요할 때만 데이터를 가져올 수 있다.
예시코드
User 엔티티를 정의하고, JPA를 통해 데이터베이스 작업을 수행한다.
JPA를 사용하기위해서는 JPA 의존성 추가를 해야하며, 데이터베이스 연결 설정을 해주어야 한다.
JPA 의존성 추가
- build.gradle (Gradle을 사용하는 경우)
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'com.h2database:h2' // H2 데이터베이스를 사용할 경우, 실제 사용하는 데이터베이스 드라이버로 변경
}
- pom.xml (Maven을 사용하는 경우)
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
엔티티 클래스
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
// Getters and Setters
}
리포지토리 인터페이스
리포지토리를 만들 때 JpaRepository를 상속 받아야한다.
타입을 적어주는 부분(<>)에 첫 번째 타입은 entity를 통해 만들어서 DB와 매핑되는 그 entity 클래스를 써주고, 두번째 타입에는 그 entity에 pk값을 넣어주어야한다.
public interface UserRepository extends JpaRepository<User, Long> {
}
서비스 클래스
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public List<User> getAllUsers() {
return userRepository.findAll();
}
public User getUserById(Long id) {
return userRepository.findById(id).orElse(null);
}
public User createUser(User user) {
return userRepository.save(user);
}
public User updateUser(Long id, User userDetails) {
User user = userRepository.findById(id).orElse(null);
if (user != null) {
user.setName(userDetails.getName());
user.setEmail(userDetails.getEmail());
return userRepository.save(user);
}
return null;
}
public void deleteUser(Long id) {
userRepository.deleteById(id);
}
}
컨트롤러 클래스
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping
public List<User> getAllUsers() {
return userService.getAllUsers();
}
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
User user = userService.getUserById(id);
if (user != null) {
return ResponseEntity.ok(user);
}
return ResponseEntity.notFound().build();
}
@PostMapping
public User createUser(@RequestBody User user) {
return userService.createUser(user);
}
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User userDetails) {
User updatedUser = userService.updateUser(id, userDetails);
if (updatedUser != null) {
return ResponseEntity.ok(updatedUser);
}
return ResponseEntity.notFound().build();
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
return ResponseEntity.noContent().build();
}
}
정리
위의 예시코드를 보면 JPA를 통해 데이터베이스 작업을 추상화하고, ORM의 장점을 살려 객체 지향적으로 데이터를 처리한다.
⇒ 개발자는 더 직관적이고 유지 보수하기 쉬운 코드를 작성할 수 있으며, 데이터베이스와의 상호작용을 보다 효율적으로 관리할 수 있다.
참고 링크
https://ccomccomhan.tistory.com/131
'👩🏻💻 About 프로그래밍 > spring' 카테고리의 다른 글
JPA 반환타입 (0) | 2024.07.18 |
---|---|
Spring Data Jpa 쿼리 메소드, 네이밍 규칙, 네이티브 쿼리 (0) | 2024.07.15 |
사용자가 로그인을 하지않아 Exception 발생 경우 처리 방법 (1) | 2024.07.12 |
권한 설정(feat. @PreAuthorize, @PostAuthorize) (0) | 2024.07.11 |
스프링 시큐리티 SecurityConfig 설정(스프링부트 2.x.x vs 3.x.x) (0) | 2024.07.10 |
블로그의 정보
Hello 춘기's world
볼빵빵오춘기