7. CRUD 애플리케이션 예제
스프링 부트와 마이바티스를 이용하여 실제로 CRUD 애플리케이션을 구현하는 방법에 대해 다룹니다. 이를 위해 사용자 정보를 관리하는 간단한 웹 애플리케이션을 구현하면서, 마이바티스를 이용하여 데이터베이스와 상호 작용하는 방법과 스프링 부트를 이용하여 웹 애플리케이션을 구축하는 방법 등을 다룹니다. 이를 통해 스프링 부트와 마이바티스를 활용하여 실제 웹 애플리케이션을 구축하는 방법을 익힐 수 있습니다. 또한, CRUD 애플리케이션을 구현하면서 데이터베이스와의 상호 작용에 대한 이해도를 높일 수 있습니다.
7.1. 도메인 모델 생성
7.1.1. 도메인 클래스 작성
도메인 클래스는 애플리케이션에서 사용하는 데이터를 표현하는 클래스입니다. 예를 들어, 회원 정보를 관리하는 애플리케이션의 경우, 회원 정보를 표현하는 User 클래스가 도메인 클래스가 됩니다.
public class User {
private Long id;
private String name;
private String email;
private LocalDate birthDate;
// Getter, Setter, 생성자, toString() 등의 메서드 생략
}
7.1.2. 도메인 클래스 테스트
도메인 클래스를 작성한 후, JUnit과 같은 테스트 프레임워크를 사용하여 도메인 클래스의 기능을 테스트합니다. 도메인 클래스는 보통 로직이 간단하므로, 테스트가 간단해질 수 있습니다.
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class UserTest {
@Test
void testUser() {
User user = new User(1L, "John Doe", "john.doe@example.com", LocalDate.of(1990, 1, 1));
assertEquals(1L, user.getId());
assertEquals("John Doe", user.getName());
assertEquals("john.doe@example.com", user.getEmail());
assertEquals(LocalDate.of(1990, 1, 1), user.getBirthDate());
}
}
도메인 클래스와 도메인 클래스의 테스트를 완료했습니다. 이를 기반으로 CRUD 기능을 구현하는 서비스, 레포지토리, 컨트롤러를 작성하고, 마이바티스와 스프링 부트를 연동해 간단한 CRUD 애플리케이션을 완성할 수 있습니다.
7.2. 컨트롤러, 서비스, 매퍼 작성
7.2.1. RESTful API 컨트롤러 작성
스프링 부트에서 RESTful API를 구현하기 위해 컨트롤러를 작성합니다. 이 예제에서는 User 도메인에 대한 CRUD 작업을 처리하는 UserController를 작성해 보겠습니다.
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping
public List<User> getAllUsers() {
return userService.findAll();
}
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
@PostMapping
public User createUser(@RequestBody User user) {
return userService.save(user);
}
@PutMapping("/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User user) {
user.setId(id);
return userService.update(user);
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable Long id) {
userService.deleteById(id);
}
}
7.2.2. 서비스 인터페이스 및 구현 클래스 작성
서비스 계층에서는 비즈니스 로직을 구현합니다. UserService 인터페이스와 구현 클래스를 작성합니다.
public interface UserService {
List<User> findAll();
User findById(Long id);
User save(User user);
User update(User user);
void deleteById(Long id);
}
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;
// 메서드 구현 생략
}
7.2.3. 매퍼 인터페이스 작성 및 SQL 매핑
마이바티스를 사용하면 매퍼 인터페이스와 SQL 매핑을 XML 또는 어노테이션으로 작성할 수 있습니다. UserRepository 인터페이스를 작성하고, XML 매핑 파일을 작성합니다.
public interface UserRepository {
List<User> findAll();
User findById(Long id);
void insert(User user);
void update(User user);
void deleteById(Long id);
}
<mapper namespace="com.example.repository.UserRepository">
<select id="findAll" resultType="User">
SELECT * FROM users
</select>
<select id="findById" resultType="User">
SELECT * FROM users WHERE id = #{id}
</select>
<insert id="insert">
INSERT INTO users (name, email, birth_date) VALUES (#{name}, #{email}, #{birthDate})
</insert>
<update id="update">
UPDATE users SET name = #{name}, email = #{email}, birth_date = #{birthDate} WHERE id = #{id}
</update>
<delete id="deleteById">
DELETE FROM users WHERE id = #{id}
</delete>
</mapper>
컨트롤러, 서비스, 매퍼를 작성하고 마이바티스와 연동하여 CRUD 애플리케이션을 완성할 수 있습니다.
7.3. 페이징 및 정렬 구현
7.3.1. 페이징 쿼리 작성
페이징을 위한 쿼리를 작성합니다. LIMIT와 OFFSET을 이용해 페이징 처리를 할 수 있습니다. UserRepository 매퍼 인터페이스에 페이징 쿼리 메서드를 추가하고, XML 매핑 파일에 쿼리를 작성합니다.
public interface UserRepository {
// 기존 메서드 생략
List<User> findAllWithPaging(int offset, int limit);
}
<mapper namespace="com.example.repository.UserRepository">
<!-- 기존 쿼리 생략 -->
<select id="findAllWithPaging" resultType="User">
SELECT * FROM users
ORDER BY id
LIMIT #{limit} OFFSET #{offset}
</select>
</mapper>
7.3.2. 정렬 쿼리 작성
정렬을 위한 쿼리를 작성합니다. ORDER BY를 이용해 정렬 처리를 할 수 있습니다. UserRepository 매퍼 인터페이스에 정렬 쿼리 메서드를 추가하고, XML 매핑 파일에 쿼리를 작성합니다.
public interface UserRepository {
// 기존 메서드 생략
List<User> findAllSortedBy(String orderBy);
}
<mapper namespace="com.example.repository.UserRepository">
<!-- 기존 쿼리 생략 -->
<select id="findAllSortedBy" resultType="User">
SELECT * FROM users
ORDER BY ${orderBy}
</select>
</mapper>
서비스와 컨트롤러에 페이징 및 정렬 기능을 추가합니다. UserService 인터페이스와 구현 클래스에 페이징 및 정렬 메서드를 추가하고, UserController에 새로운 엔드포인트를 생성합니다.
public interface UserService {
// 기존 메서드 생략
List<User> findAllWithPaging(int offset, int limit);
List<User> findAllSortedBy(String orderBy);
}
@RestController
@RequestMapping("/api/users")
public class UserController {
// 기존 메서드 생략
@GetMapping("/paged")
public List<User> getAllUsersWithPaging(
@RequestParam(value = "offset", defaultValue = "0") int offset,
@RequestParam(value = "limit", defaultValue = "10") int limit) {
return userService.findAllWithPaging(offset, limit);
}
@GetMapping("/sorted")
public List<User> getAllUsersSortedBy(
@RequestParam(value = "orderBy", defaultValue = "id") String orderBy) {
return userService.findAllSortedBy(orderBy);
}
}
페이징 및 정렬 기능을 포함한 CRUD 애플리케이션을 완성할 수 있습니다.
7.4. 검색 기능 구현
7.4.1. 검색 쿼리 작성
검색 기능을 위한 쿼리를 작성합니다. LIKE 연산자와 동적 쿼리를 이용해 검색 처리를 할 수 있습니다. UserRepository 매퍼 인터페이스에 검색 쿼리 메서드를 추가하고, XML 매핑 파일에 쿼리를 작성합니다.
public interface UserRepository {
// 기존 메서드 생략
List<User> search(String keyword);
}
<mapper namespace="com.example.repository.UserRepository">
<!-- 기존 쿼리 생략 -->
<select id="search" resultType="User">
SELECT * FROM users
WHERE name LIKE #{keyword}
OR email LIKE #{keyword}
</select>
</mapper>
7.4.2. 검색 필터 적용
이제 서비스와 컨트롤러에 검색 기능을 추가합니다. UserService 인터페이스와 구현 클래스에 검색 메서드를 추가하고, UserController에 새로운 엔드포인트를 생성합니다.
public interface UserService {
// 기존 메서드 생략
List<User> search(String keyword);
}
@RestController
@RequestMapping("/api/users")
public class UserController {
// 기존 메서드 생략
@GetMapping("/search")
public List<User> searchUsers(
@RequestParam(value = "keyword", required = false) String keyword) {
if (keyword == null || keyword.isEmpty()) {
return userService.findAll();
}
return userService.search("%" + keyword + "%");
}
}
검색 기능을 포함한 CRUD 애플리케이션을 완성할 수 있습니다.
7.5. 예외 처리 및 유효성 검사
7.5.1. 예외 처리 전략
애플리케이션에서 발생할 수 있는 예외를 효과적으로 처리하기 위해, 글로벌 예외 처리 전략을 사용합니다. 컨트롤러에서 @ExceptionHandler를 사용하여 특정 예외를 처리하거나, @ControllerAdvice를 사용하여 애플리케이션 전체에서 적용할 예외 처리를 구현할 수 있습니다.
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleException(Exception ex) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ex.getMessage());
}
}
7.5.2. 유효성 검사를 위한 Bean Validation 사용
Bean Validation을 사용하여 입력 데이터의 유효성을 검사할 수 있습니다. 도메인 모델에 제약 조건을 명시하고, 컨트롤러에서 @Valid 어노테이션을 사용하여 유효성 검사를 수행합니다.
public class User {
// 기존 필드 생략
@NotBlank
@Email
private String email;
@NotBlank
@Size(min = 3, max = 100)
private String name;
// 기존 메서드 생략
}
@RestController
@RequestMapping("/api/users")
public class UserController {
// 기존 메서드 생략
@PostMapping
public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
User newUser = userService.createUser(user);
return ResponseEntity.status(HttpStatus.CREATED).body(newUser);
}
}
예외 처리 및 유효성 검사를 포함한 CRUD 애플리케이션을 완성할 수 있습니다.
'GD's IT Lectures : 기초부터 시리즈 > 스프링 부트(Spring Boot) & 마이바티스(Mybatis) 연동' 카테고리의 다른 글
[스프링 부트(Spring Boot) & 마이바티스(Mybatis) 연동] 마무리 (0) | 2023.05.07 |
---|---|
[스프링 부트(Spring Boot) & 마이바티스(Mybatis) 연동] 고급 기능 (0) | 2023.05.07 |
[스프링 부트(Spring Boot) & 마이바티스(Mybatis) 연동] 마이바티스와 스프링 부트 연동 (1) | 2023.05.07 |
[스프링 부트(Spring Boot) & 마이바티스(Mybatis) 연동] 마이바티스 기초 (0) | 2023.05.06 |
[스프링 부트(Spring Boot) & 마이바티스(Mybatis) 연동] 데이터베이스 설정 (0) | 2023.05.06 |
댓글