지금까지는 JDBC를 활용하여 DAO 클래스에서 SQL쿼리를 통해 DB 작업을 하였는데요.
//sql을 통한 회원가입 처리
@Repository
public class UserDAO {
@Autowired
JdbcTemplate jdbcTemplate;
// todo 회원가입
public int signUp(UserRequest userRequest) {
String sql = "INSERT INTO `user` (email,password,nickname)\n" +
"values (?,?,?);";
System.out.println("UserDAO signUp");
return jdbcTemplate.update(sql, userRequest.email, userRequest.password, userRequest.nickname);
}
}
JPA을 이용하면 SQL 쿼리 대신, 자바 객체를 이용해 데이터 처리가 가능합니다.
JPA란?
Java Persistence API (자바 영속성 API)
Persistence - 영속성, 지속성
데이터를 생성한 프로그램이 종료되어도 사라지지 않는다는 뜻 = 메모리가 아닌, DB에 저장됨
즉 자바를 통해 데이터를 관계형 데이터베이스에 저장, 검색, 업데이트 및 삭제 관리하는 API 입니다.
JPA 의 특징
- 객체-관계 매핑 (ORM-Object Relational Mapping)
JPA는 자바 객체와 데이터베이스 테이블 간의 매핑을 자동으로 처리합니다. 이를 통해 개발자는 복잡한 SQL 쿼리 대신 자바 객체를 통해 데이터를 조작할 수 있습니다. - 생산성 향상
JPA를 사용하면 CRUD(Create, Read, Update, Delete) 작업을 간편하게 수행할 수 있습니다. 메서드 이름만으로 필요한 쿼리를 자동 생성하므로, 개발자는 SQL 작성에 시간을 들이지 않아도 됩니다. - 유지보수성 개선
객체 지향적인 코드 작성이 가능해져 애플리케이션의 유지보수가 더욱 용이해집니다. - 데이터베이스 독립성
특정 데이터베이스에 종속되지 않는 코드 작성이 가능합니다. - 객체 지향 프로그래밍 지원
JPA 활용을 통해 다형성, 상속등의 OOP특성을 이용하여 유연하고 확장가능한 애플리케이션 개발이 가능합니다.
JPA의 한계
복잡한 쿼리 처리의 불편함
조인 연산이 많을 경우 성능 저하가 발생할 수 있습니다.
JPA 사용 예시
메모를 저장할 수 있는 간단한 JPA를 만들어보겠습니다.
application.yml 설정하기
spring:
datasource:
url:
username:
password:
jpa:
show-sql: true
hibernate:
ddl-auto: update
properties:
hibernate:
format_sql: true
jdbc:
time_zone: UTC
ddl-auto: update = DB에 데이터 추가
JPA 의존성 추가
Spring Data JDBC대신 Spring Data JPA를 추가합니다.
데이터 유효성을 검사하는 Validation 의존성도 추가하였습니다.
entity 패키지에 Memo 엔티티클래스 만들기
@Entity
@Table(name = "memo")
//DB에 저장될 테이블명을 memo 로 설정
public class Memo {
@Id
@GeneratedValue(generator = "increment")
public Long id;
// @Id 는 기본키를 나타내는 어노테이션 Pk 와 같음
// @GeneratedValue 는 기본키의 값을 자동으로 생성하는 어노테이션 (generator = "increment")
@Column(length = 200, nullable = false)
public String content;
// length 는 최대 길이를 나타냄 varchar(200) 과 같음
@Column(nullable = false)
public Instant createdAt;
// Instant 는 날짜와 시간을 나타내는 클래스
@PrePersist
public void prePersist() {
createdAt = Instant.now();
// Instant.now() 는 현재 시간을 나타내는 객체를 반환
}
}
entity 패키지의 클래스들은 DB의 테이블과 컬럼 역할을 수행합니다.
DB 컬럼에서 적용했었던 Primery key와 auto increment , not null, default값 now() 등 도 자바로 설정이 가능합니다.
@Column(
name = "user_name", // 컬럼 이름
length = 100, // 문자 길이
nullable = false, // NULL 허용 여부
unique = true, // 유니크 제약조건
updatable = false, // 수정 가능 여부
columnDefinition = "TEXT" // 컬럼 정의
)
private String name;
@Entity 클래스는 기본 생성자가 필수 (JPA 규약) 니 잊지 맙시다.
repository 패키지에 MemoRepository클래스 만들기
JDBC에서는 DAO 클래스의 sql문을 통해 DB와 상호작용하였었죠.
JPA에서는 JpaRepository 인터페이스를 상속받는 Resporitory 클래스를 통해 DB와 상호작용 합니다.
상속받은 메서드를 통해 CRUD 작업이 가능합니다.
@Repository
public interface MemoRepository extends JpaRepository<Memo, Long> {
// <테이블 클래스, Id 컬럼의 타입>
// JpaRepository 를 상속받으면 CRUD 가 가능해짐
}
상속으로 사용가능한 JPA 제공 메서드들
Create 메서드 사용해보기
postman으로
{
"content" : "안녕하세요."
}
리퀘스트를 담아올 DTO 클래스 준비
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MemoRequest {
public String content;
}
서비스클래스
@Service
public class MemoService {
@Autowired
MemoRepository memoRepository;
public void createMemo(MemoRequest memoRequest){
// DTO 를 Entity 로 변환
Memo memo = new Memo();
memo.content = memoRequest.content;
// JDBC에서는 DAO를 통해 DB에 저장하는 SQL쿼리가 필요했지만,
// JPA에서는 상속된 JpaRepository.save 메서드를 통해 객체를 데이터베이스에 저장할 수 있다.
memoRepository.save(memo);
}
}
MemoRepository클래스에 상속된 JpaRepository.save 메서드를 통해 메모 객체를 저장합니다.
컨트롤러 클래스
@RestController
public class MemoController {
@Autowired
MemoService memoService;
@PostMapping("/memo")
public ResponseEntity<Void>createMemo(@RequestBody MemoRequest memoRequest) {
memoService.createMemo(memoRequest);
return ResponseEntity.status(201).build();
}
}
결과를 클라이언트에게 반환합니다. (저장 성공시 201)
JPA와 JDBC의 비교
JPA (Java Persistence API):
- 상속 및 메서드 호출: JPA는 JpaRepository와 같은 인터페이스를 통해 데이터베이스와 상호작용합니다. 개발자는 SQL 쿼리를 직접 작성할 필요 없이 메서드 호출만으로 CRUD 작업을 수행할 수 있습니다.
- ORM: JPA는 객체 관계 매핑(ORM) 기술로, 객체와 데이터베이스 간의 매핑을 자동으로 처리합니다. 이를 통해 객체 지향적인 접근 방식으로 데이터베이스 작업을 수행할 수 있습니다.
- JDBC 사용: JPA는 내부적으로 JDBC를 사용하여 데이터베이스와 상호작용하며, SQL 쿼리를 생성하고 실행하는 과정을 자동으로 처리합니다.
JDBC (Java Database Connectivity):
- SQL 직접 작성: JDBC는 개발자가 SQL 쿼리를 직접 작성해야 하며, 데이터베이스와의 연결 및 트랜잭션 관리를 수동으로 수행해야 합니다.
- 저수준 API: JDBC는 저수준의 데이터베이스 접근을 제공하므로, SQL에 대한 이해가 필요하며 코드가 복잡해질 수 있습니다.
JpaRepository 기본 제공 메서드
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
// 기본 제공되는 메서드들
// 저장 & 수정
User save(User user); // 엔티티 저장 또는 수정
List<User> saveAll(List<User> users); // 여러 엔티티 저장
// 조회
Optional<User> findById(Long id); // ID로 조회
List<User> findAll(); // 전체 조회
List<User> findAllById(List<Long> ids); // 여러 ID로 조회
// 삭제
void delete(User user); // 엔티티 삭제
void deleteById(Long id); // ID로 삭제
void deleteAll(); // 전체 삭제
// 기타
long count(); // 전체 개수 조회
boolean existsById(Long id); // ID 존재 여부 확인
}