article thumbnail image
Published 2022. 8. 4. 15:50
반응형

springboot 개발을 할 때 늘 mybatis를 사용하여 mapper.xml에 SQL쿼리를 작성해 database 로직을 구현했었다.

언제부턴가 JPA라는 말이 자주 들려오고 있는데, 이제야 테스트를 해본다.

 

JPA(Java Persistence API)와 mybatis와 비교하자면

 

먼저 Mybatis 는 SQL자체로 xml 파일을 분리할 수 있으며, 복잡한 쿼리 작성의 장점이 있지만,

간단한 쿼리들을 많이 작성하여 코드가 길어지는 단점이 있다.

 

JPA 는 CRUD 메소드가 이미 정의되어있어 sql을 직접 구현할 필요가 없기 때문에 소스코드의 양이 적어지는 점, 또 database 와 연결되어 table 생성을 자동으로 할 수도 있다.

하지만, 복잡한 쿼리의 사용은 JPQL 또는 Query dsl 을 사용하여야 하기때문에 불편할 수 있다.

 

기존에 사용하던 mybatis의 style은 app과 db가 따로 작성되는 불편함?이 있었다 볼 수 있고

JPA 방식을 사용하면 app과 db가 서로 연결되어 app에서 테이블 정의, 컬럼 정의 등 많은 부분을 구현할 수 있어 좋다.

그렇다고 JPA 방식만 써야하는 건 아니고, 비즈니스 로직에 복잡한 쿼리가 많다면 mybatis를 쓰는게 좋다고한다.

 

그럼 JPA를 적용해보자.

 

POM.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

 

application.properties

필자는 local 에 postgreSQL db를 올렸다.

# postgres db setting
spring.datasource.url: jdbc:postgresql://localhost:5432/yehan
spring.datasource.username: postgres
spring.datasource.password: joon1234!@#$
spring.datasource.show-sql: true
spring.jpa.properties.hibernate.dialect: org.hibernate.dialect.PostgreSQLDialect

spring.jpa.hibernate.ddl-auto: create
spring.jpa.generate-ddl: true
spring.jpa.properties.hibernate.show_sql: true #콘솔에 SQL을 띄울 것인지
spring.jpa.properties.hibernate.format_sql: true #콘솔에 SQL을 보기 좋게 띄울 것인지
logging.level.org.hibernate.SQL: debug
logging.level.org.hibernate.type: trace

 

Entity 정의

테스트용 테이블은 간단히 User 정보를 담는다.

  table name : user_tbl

  Long Id(PK), email, password

컬럼을 가지도록 정의했다.

@Getter
@Entity(name = "user_tbl") // 사용할 테이블명
@NoArgsConstructor // 생성자 자동 완성(Lombok필요)
@AllArgsConstructor
public class User {
    
    @Id // PK를 가지는 변수를 뜻함 필수
    @GeneratedValue(strategy = GenerationType.IDENTITY) // Id 값을 어떻게 생성할지 전략을 지정 AUTO 도 있음
    private Long id;

    @Column(length = 100, nullable = false, unique = true) // @Column : 선택형 선언, DB컬럼명과 현재변수명을 다르게 할 때 사용
    private String email;

    @Column(length = 300, nullable = false)
    private String password;
}

 

JpaRepository 정의

기본이 되는 사항(CRUD)은 자동으로 생성되어 있으며,

추가로 커스텀 쿼리를 생성해본다.(ex: Email 데이터를 검색하는 쿼리)

@Repository
public interface UserRepository extends JpaRepository<User, Long>{

    // 커스텀 쿼리 사용방법
    @Query(value = "select * from user_tbl where email = :email", nativeQuery=true)
    List<User> searchEmail(@Param("email") String email);
}

 

Service 정의

@Service
public class UserService {
    
    @Autowired
    private UserRepository userRepository;
    
    public List<User> getUsers() {
      return userRepository.findAll();
    }
    public List<User> getSearchEmail(String email) {
      return userRepository.searchEmail(email);
    }
    public User addUser(User user) {
    return userRepository.save(user);
  }
    public User updateUser(User user) {
     return userRepository.save(user);
  }
    public void deleteUser(Long id) {
      userRepository.deleteById(id);
   }
}

 

Controller 정의

@Slf4j
@RestController
@RequestMapping("/user")
public class UserController{
    
    @Autowired
    UserService userService;
    
    // 전체 조회
    @GetMapping
    public ResponseEntity<List<User>> index() {
        ResponseEntity<List<User>> res;
        res = new ResponseEntity<List<User>>(userService.getUsers(), HttpStatus.OK);
        return res;
    }
    
    // 단일 조회
    @GetMapping("/{email}")
    public ResponseEntity<List<User>> searchEmail(@PathVariable String email) throws Exception {
        ResponseEntity<List<User>> res;
        res = new ResponseEntity<List<User>>(userService.getSearchEmail(email), HttpStatus.OK);
        return res; 
    }
    
    // 등록
    @PostMapping
    public ResponseEntity<User> addUser(@RequestBody User user) throws Exception{
        ResponseEntity<User> res;
        res = new ResponseEntity<User>(userService.addUser(user), HttpStatus.OK);
        return res;
    }
        
    
    // 수정
    @PutMapping
    public ResponseEntity<User> updateUser(@RequestBody User user) throws Exception{
        ResponseEntity<User> res;
        res = new ResponseEntity<User>(userService.updateUser(user), HttpStatus.OK);
        return res;
    }
    
    
    // 삭제
    @DeleteMapping("/{id}")
    public ResponseEntity<ApiException> deleteUser(@PathVariable Long id) throws Exception{
        ResponseEntity<ApiException> res = new ResponseEntity<ApiException>(HttpStatus.OK);
        userService.deleteUser(id);
        return res;
    }
}

 

폴더구조

Entity :                           /com/mtp/auth/entity/User.java

JpaRepogitory :    /com/mtp/auth/repository/UserRepository.java

Service :                 /com/mtp/auth/service/UserService.java

Controller :          /com/mtp/auth/controller/UserController.java

 

나머지는 테스트하고 있는 부분이라 무시해라

 

테스트

유저등록

유저수정

유저목록

유저검색(email)

유저삭제

 

이렇게 JPA 테스트를 해보았다!

 

끝!

반응형
복사했습니다!