티스토리 뷰

2020/08/22 - [Backend/Spring] - Spring. SpringBoot + Gradle + Java + JPA + lombok + h2 DB (1)

 

Spring. SpringBoot + Gradle + Java + JPA + lombok + h2 DB (1)

오늘은 Spring Boot, Gradle, Java, JPA, lombok, h2 DB를 이용하여 로컬에서 Application을 하나 만들어 볼까 합니다. 그냥 기본적인 부분들만 있으니깐 기본적으로 세팅을 원하는 분들만 봐주세요 * 세팅만 있�

mrgamza.tistory.com

세팅은 여기에 있으니 가서 확인하시면 될것 같습니다.

 

그럼 이번글에서는 바로 다음 세팅들을 하도록 할게요.

build.gradle

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	annotationProcessor("org.projectlombok:lombok:1.18.8")
	implementation group: 'org.projectlombok', name: 'lombok', version: '1.18.12'
	runtimeOnly 'com.h2database:h2'

	testImplementation('org.springframework.boot:spring-boot-starter-test') {
		exclude group: 'org.junit', module: 'junit'
	}
	testImplementation 'org.springframework.boot:spring-boot-starter-webflux'
}

이러한 형태면 기본적으로 잘 될겁니다.

프로젝트 전체 구조

UserController.java

@RestController
public class UserController {

    private UserService service;

    public UserController(UserService service) {
        this.service = service;
    }

    @PostMapping("/api/user")
    public ResponseEntity create(@RequestBody UserRequestDto request) {
        UserResponseDto serviceResult = service.create(request);
        return ResponseEntity
                .created(URI.create("/user/"+ serviceResult.getId()))
                .body(serviceResult);
    }

    @GetMapping("/api/user/{id}")
    public ResponseEntity show(@PathVariable("id") Long id) {
        UserResponseDto user = service.show(id);
        return ResponseEntity.ok(user);
    }

    @GetMapping("/api/users")
    public ResponseEntity showAll() {
        List<UserResponseDto> articles = service.showAll();
        return ResponseEntity.ok(articles);
    }

    @PutMapping("/api/user/{id}")
    public ResponseEntity update(@PathVariable("id") Long id,
                                 @RequestBody UserRequestDto request) {
        UserResponseDto updatedArticle = service.update(id, request);
        return ResponseEntity.ok(updatedArticle);
    }

    @DeleteMapping("/api/user/{id}")
    public ResponseEntity delete(@PathVariable("id") Long id) {
        service.delete(id);
        return ResponseEntity.ok().build();
    }
}

CRUD에 매핑되는 데이터들을 그대로 넣어두었습니다.

Create, Show, ShowAll, Update, Delete

User.java

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@Table(name = "User")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name", nullable = false)
    private String name;

    @Column(name = "address")
    private String address;

    @Column(name = "age", nullable = false)
    private Integer age;

    @Lob
    @Column(name = "contents")
    private String contents;

    @Builder
    public User(String name, String address, Integer age, String contents) {
        this.name = name;
        this.address = address;
        this.age = age;
        this.contents = contents;
    }

    public void update(User another) {
        this.name = another.name;
        this.address = another.address;
        this.age = another.age;
        this.contents = another.contents;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof User)) return false;
        User article = (User) o;
        return getId().equals(article.getId());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getId());
    }
}

JPA에 사용하는 부분들을 넣어두었습니다.

Table 이름은 User, Column은 각각 이렇게 들어가 있습니다.

UserRepository.java

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

UserRequestDto.java

@Getter
@Setter
@Builder
public class UserRequestDto {

    private Long id;
    private String name;
    private String address;
    private int age;
    private String contents;
}

UserResponseDto.java

@Getter
@Setter
@Builder
public class UserResponseDto {

    private Long id;
    private String name;
    private String address;
    private int age;
    private String contents;
}

UserService.java

@Service
public class UserService {

    private UserRepository repository;

    public UserService(UserRepository repository) {
        this.repository = repository;
    }

    @Transactional
    public UserResponseDto create(UserRequestDto request) {
        User user = User.builder()
                .name(request.getName())
                .address(request.getAddress())
                .age(request.getAge())
                .contents(request.getContents())
                .build();

        User saved = repository.save(user);

        return UserResponseDto.builder()
                .id(saved.getId())
                .name(saved.getName())
                .address(saved.getAddress())
                .age(saved.getAge())
                .contents(saved.getContents())
                .build();
    }

    @Transactional(readOnly = true)
    public UserResponseDto show(Long userId) {
        User source = repository
                .findById(userId)
                .orElseThrow(() -> new IllegalArgumentException("해당 User를 찾을 수 없습니다."));

        return UserResponseDto.builder()
                .id(source.getId())
                .name(source.getName())
                .address(source.getAddress())
                .age(source.getAge())
                .contents(source.getContents())
                .build();
    }

    @Transactional(readOnly = true)
    public List<UserResponseDto> showAll() {
        List<User> articles = repository.findAll();

        return articles.stream()
                .map(user -> UserResponseDto.builder()
                        .id(user.getId())
                        .name(user.getName())
                        .address(user.getAddress())
                        .age(user.getAge())
                        .contents(user.getContents())
                        .build()
                )
                .collect(Collectors.toList());
    }

    @Transactional
    public UserResponseDto update(Long userId, UserRequestDto request) {
        User source = repository
                .findById(userId)
                .orElseThrow(() -> new IllegalArgumentException("해당 User를 찾을 수 없습니다."));
        User target = User.builder()
                .name(request.getName())
                .address(request.getAddress())
                .age(request.getAge())
                .contents(request.getContents())
                .build();
        source.update(target);

        return UserResponseDto.builder()
                .id(source.getId())
                .name(source.getName())
                .address(source.getAddress())
                .age(source.getAge())
                .contents(source.getContents())
                .build();
    }

    @Transactional
    public void delete(Long userId) {
        User source = repository
                .findById(userId)
                .orElseThrow(() -> new IllegalArgumentException("해당 User를 찾을 수 없습니다."));
        repository.delete(source);
    }
}

UserApiControllerTest.java

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureWebClient
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class UserApiControllerTest {

    private static final String LOCATION = "Location";

    @Autowired
    private WebTestClient testClient;

    private UserRequestDto getUser() {
        return UserRequestDto.builder()
                .id(1L)
                .name("Bear")
                .address("서울시")
                .age(39)
                .contents("코로나 조심하세요")
                .build();
    }

    private UserRequestDto getUpdateUser() {
        UserRequestDto copy = getUser();
        copy.setAddress("강릉시");
        copy.setAge(29);
        copy.setContents("감기 조심하세요");
        return copy;
    }

    @Test
    @DisplayName("User 생성, 조회, 변경, 삭제")
    void test_crud() {
        // Post
        UserRequestDto requestDto = getUser();

        UserResponseDto responseDto = testClient
                .post()
                .uri("/api/user")
                .contentType(MediaType.APPLICATION_JSON)
                .accept(MediaType.APPLICATION_JSON)
                .body(Mono.just(requestDto), UserRequestDto.class)
                .exchange()
                .expectStatus().isCreated()
                .expectHeader().contentType(MediaType.APPLICATION_JSON)
                .expectHeader().valueMatches(LOCATION, "\\/user\\/\\d")
                .expectBody(UserResponseDto.class)
                .returnResult()
                .getResponseBody();

        assert responseDto != null;
        assertThat(responseDto.getId()).isEqualTo(requestDto.getId());
        assertThat(responseDto.getName()).isEqualTo(requestDto.getName());
        assertThat(responseDto.getAddress()).isEqualTo(requestDto.getAddress());
        assertThat(responseDto.getAge()).isEqualTo(requestDto.getAge());
        assertThat(responseDto.getContents()).isEqualTo(requestDto.getContents());

        // Get
        responseDto = testClient
                .get()
                .uri("/api/user/" + requestDto.getId())
                .accept(MediaType.APPLICATION_JSON)
                .exchange()
                .expectStatus().isOk()
                .expectHeader().contentType(MediaType.APPLICATION_JSON)
                .expectBody(UserResponseDto.class)
                .returnResult()
                .getResponseBody();

        assert responseDto != null;
        assertThat(responseDto.getId()).isEqualTo(requestDto.getId());
        assertThat(responseDto.getName()).isEqualTo(requestDto.getName());
        assertThat(responseDto.getAddress()).isEqualTo(requestDto.getAddress());
        assertThat(responseDto.getAge()).isEqualTo(requestDto.getAge());
        assertThat(responseDto.getContents()).isEqualTo(requestDto.getContents());

        // Update
        UserRequestDto updateDto = getUpdateUser();

        responseDto = testClient
                .put()
                .uri("/api/user/" + requestDto.getId())
                .contentType(MediaType.APPLICATION_JSON)
                .accept(MediaType.APPLICATION_JSON)
                .body(Mono.just(updateDto), UserRequestDto.class)
                .exchange()
                .expectStatus().isOk()
                .expectHeader().contentType(MediaType.APPLICATION_JSON)
                .expectBody(UserResponseDto.class)
                .returnResult()
                .getResponseBody();

        assert responseDto != null;
        assertThat(responseDto.getId()).isEqualTo(updateDto.getId());
        assertThat(responseDto.getName()).isEqualTo(updateDto.getName());
        assertThat(responseDto.getAddress()).isEqualTo(updateDto.getAddress());
        assertThat(responseDto.getAge()).isEqualTo(updateDto.getAge());
        assertThat(responseDto.getContents()).isEqualTo(updateDto.getContents());

        // Delete
        testClient
                .delete()
                .uri("/api/user/" + getUser().getId())
                .exchange()
                .expectStatus().isOk();
    }
}

전체 소스는 github에 올려두었습니다.

https://github.com/outofcode-example/springboot-jpa-lombok

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함