JPA(Java Persistence API)는 JAVA의 ORM(Object-Relational Mapping) 기술의 표준이다.
ORM은 객체과 관계형 데이터베이스의 매핑을 뜻하며 매핑을 통한 패러다임의 불일치를 개발자 대신 해결한다.
❗Mybatis를 사용하면서 작성했던 Mapper를 작성하지 않아도 SQL Query를 이용할 수 있다.
1. 새로운 프로젝트 생성 시 추가
새 프로젝트 생성 시 Depedency를 추가할 수 있다. JPA외에도 자주 사용되는 Thymeleaf
,Lombok
등의 추가도 가능하다.
2. build.gradle작성하기
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
1번과 같은 방법으로 dependency를 추가하면 build.gradle
파일에 자동으로 삽입되지만 설정하지 못했다면 직접 입력하여 추가할 수 있다.
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.url=jdbc:mariadb://localhost:포트번호/데이테베이스명
spring.datasource.username=****
spring.datasource.password=****
spring.jpa.show_sql = true
위에는 내가 사용하는 mariaDB연동을 위한 DB 접속 정보이며 spring.jpa.show_sql = true
를 추가로 작성하여 JPA 사용시 실행쿼리를 확인한다.
DTO
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
LomBok
을 사용하여 Annotation으로 DTO
를 편리하게 작성할 수 있다. 더 간편하게 작성하기 위해서는 @DATA
의 Annotiation도 있지만 명시적으로 작성하는 습관을 들이기는 것도 중요하다.
JPA를 연습하면서는 Entity -> DTO -> VO
의 변환과정을 연습하려 한다. 따라서 각 부분별 모델을 생성해주었다.
Entity
@AllArgsConstructor //lombok
@NoArgsConstructor //lombok
@Getter
@Setter
@Builder
@Entity
@Table(name="example")
public class Example {
@Id
@Column
@GeneratedValue(strategy= GenerationType.IDENTITY)
private long id;
@Column(name = "name", nullable=true,length=20)
private String name;
@Column(name = "price", nullable=false,length=20)
private int price;
}
Entity
에는 @Builder
와 @Table
이 추가 되었으며 @Id
로 Primary Key
를 명시할 수 있다.
@Repository
public interface ExampleRepository extends JpaRepository<Example,Long> {}
Repository
는 JpaRepository
를 상속받으며 Entity
와 Primary Key
의 타입형을 명시한다.
@Service
public class ExampleService {
@Autowired
ExampleRepository repo;
public ExampleResDTO merge(ExampleReqDTO req){
Example example = req.toEntity();
example = repo.save(example); //해당 PK가 테이블에 존재하면 UPDATE 수행, 테이블에 존재하지 않으면 INSERT 수행
return new ExampleResDTO(example.getName());
}
@Service
에서 SQL Query를 수행할 수 있는데 save()
메서드는 해당 PK가 테이블에 이미 존재하면 UPDATE를 수행하고, 해당 PK가 없다면 INSERT를 수행한다.
JPA를 사용하여 CRUD구현을 손쉽게 할 수 있다. Where절을 통한 검색
, WildCard 검색
, And,OR 연산
모두 가능하다.
🏃SELECT FROM TABLE WHERE NAME = ?
repository
public List<Example> findByName(String name); //where name = ?
service
public List<ExampleResDTO> selectByName(ExampleReqDTO req){
List<Example> result = repo.findByName(req.getName());
List<ExampleResDTO> resList = result.stream()
.map(example->new ExampleResDTO(example.getName()))
.collect(Collectors.toList());
return resList;
}
JPA에서는 생성자 생성보다는 builder 사용을 선호하고 반복문보다는 stream을 선호한다고 하니 Stream 연습을 해야겠다.
🏃SELECT FROM TABLE WHERE NAME LIKE 'x%'
public List<Example> findByNameStartingWith(String name);
🏃SELECT FROM TABLE WHERE PRICE < X
public List<Example> findByPriceLessThan(int price);
🏃SELECT FROM TABLE WHERE NAME = ? AND PRICE = ?
public List<Example> findByNameAndPrice(String name, int price);
마무리
MyBatis보다 간단한 CRUD 구현은 훨씬 쉬운 것 같기는 하지만 뭔가 재밌는 건 MyBatis가 재밌는 것 같다.
그래도 각자의 상황에서 각자의 장단점이 있겠지...?