Spring 애플리케이션 처음부터 끝까지 3) - DB 조작

june·2022년 1월 6일
0
post-thumbnail

Spring Data JDBC라는 O/R Mapper를 통해 DB조작에 관한 부분을 생성함.

만들부분은 이 부분.

DB연결

aplication.properties 설정

Spring Boot 프로젝트에서 application.properties는 환경설정을 수행하기 위한 파일.
여기서 전편에서 생성한 accountdb를 연결하기 위한 설정을 진행해줘야 함.

src/main/resourcesapplication.properties 파일을 열어 수정해줌.

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://mysql 주소./accountdb
spring.datasource.username=ID
spring.datasource.password=PASSWORD

driver-class-name은 동일하게 설정해주고
url은 localhost로 설정해줘도 상관없고, AWS와 같은 클라우딩 컴퓨팅 서비스의 엔드포인트를 설정해줘도 괜찮다.
usernamepassword는 설정한 것으로 입력해준다.

DB 조작처리 작성


O/R Mapper로는 Spring Data JDBC를 사용하고, RepositoryImpl은 Spring Data JDBC가 자동으로 작성해줌.
따라서 이 프로젝트에서 직접적으로 작성해야하는것은 Domain ObjectRepository가 됨.

Domain Object 생성

서비스처리를 실행하기 위해 필요한 자원.
DB로 치자면 Entity와 같은 말이라고 할 수 있음.
즉 DB의 테이블 한줄에 해당하는 클래스.

src/main/java/에서 entity패키지를 추가한다음 Account 클래스를 추가함.

Account.java

package com.example.account.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;

/**
 * account 테이블용 Entity
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Account {
    // 식별 ID
    @Id
    private Integer key;
    // 회원 id
    private String id;
    // 회원 이름
    private String name;
    // 회원 이메일 주소
    private String mail;
    // 회원 비밀번호
    private String password;
}

@Data 어노테이션은 클래스에 부여함으로 모든 필드에 대해 getter/setter로 엑세스 할 수 있게 해줌.
@NoArgsConstructor어노테이션은 클래스에 부여함으로 기본적인 생성자를 자동으로 생성해줌
@AllArgsConstructor 어노테이션은 클래스에 부여함으로 모든 필드에 대한 초기화 값을 인수로 얻을 수 있게 하는 생성자(Constructor)를 생성함.
@Id 어노테이션은 테이블의 Primary Key에 해당하는 필드 id에 대해서 부여됨.

Repository 생성

Repository는 인터페이스이며 DB에대한 데이터 조작 정의만 구성됨.
src/main/java에서 repository패키지를 추가하고, 패키지 안에 AccountRepository 인터페이스를 추가함.

RepositoryImpl 생성

Repository 인터페이스에 Spring Data가 제공하는 CrudRepository를 상속하여 RepositoryImpl이 생성이 됨.
CrudRepository의 형 인수는 Entity형인Account@Id 어노테이션이 부여된 Integer를 순서대로 지정함.

AccountRepository.java

package com.example.account.repository;

import com.example.account.entity.Account;
import org.springframework.data.repository.CrudRepository;

/**
 * Account 테이블의 RepositoryImpl
 */
public interface AccountRepository extends CrudRepository<Account, Integer> {
}

Spring Data가 제공하는 CurdRepository를 상속함으로써 자동으로 CRUD를 지원하는 메소드를 사용 가능함.
메소드의 종류는 아래와 같음.
CRUDRepository 메소드 종류

<Account, Integer>는 저장대상의 객체형과 저장대상의 객체의 기본키형의 지정.

DB 조작 처리 확인

Spring Boot 어플리케이션 시작 클래스인 AccountApplication필드에 AccountRepository@Autowired 어노테이션을 주입하고 AccountApplication의 실행상태를 확인함.

등록처리 확인

src/main/java/AccountApplication.java에 다음과 같은 내용을 추가해줌

AccountApplication.java

package com.example.account;

import com.example.account.entity.Account;
import com.example.account.repository.AccountRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class AccountApplication {

    public static void main(String[] args) {
        SpringApplication.run(AccountApplication.class, args).getBean(AccountApplication.class).execute();
    }

    @Autowired
    AccountRepository repository;

    /**
     * 실행 메소드
     */

    private void execute() {
        // 등록처리
        setup();
    }

    /**
     * 2개의 계정 추가
     */
    private void setup() {
        // 엔티티 생성
        Account account1 = new Account(null, "aaaa", "가나다","aaaa@gmail.com","11111");
        // 등록
        account1 = repository.save(account1);
        // 등록 확인
        System.out.println("등록된 데이터: " + account1);
        // 엔티티 생성
        Account account2 = new Account(null, "bbbb", "James","james@naver.com","22222");
        // 등록
        account2 = repository.save(account2);
        // 등록 확인
        System.out.println("등록된 데이터: " + account2);
    }

}

@Autowired에서는 AccountRepository를 주입함.
main 메소드는 execute 메소드를 호출하며, execute메소드가 호출하는 것은 setup메소드.
setup 메소드 중에서 CrudRepository를 상속하에 사용가능하게 된 save메소드를 호출함.
save메소드는 엔티티를 저장하는 메소드. 따라서 엔티티가 null이면 안되지만 @Id어노테이션이 부여된 항목이라면 자동으로 반영하여 INSERT 쿼리문을 SQL에 던져줌.
지정한 엔티티를 데이터베이스에 저장함.

실행 결과

SQL DB에도 정상적으로 쿼리문이 작동되었음을 알 수 있다.

전체 검색 확인

AccountApplicaion 클래스에 아래 메소드를 추가함

private void showList() {
        System.out.println("---전체 검색 시작---");
        // Repository를 사용하여 모든 내역을 얻는 결과
        Iterable<Account> accounts = repository.findAll();
        for (Account account : accounts) {
            System.out.println(account);
        }
    }

showList 메소드에서는 CrudRepository를 상속하에 사용가능하게 된 findAll 메소드를 호출하여, 모든 엔티티의 값을 Iterable 형으로 바꿔서 저장한다.
그것들을 for문으로 모두 출력하는 형식의 메소드라고 할 수 있다.

실행하기위해 AccountApplicaion의 execute 메소드의 값도 바꿔준다.

    /**
     * 실행 메소드
     */

    private void execute() {
        // 등록처리
        //setup();
        showList();
    }

그럼 다음과 같은 값이 출력된다.

1건의 데이터 얻기

AccountApplicaion 클래스에 아래 메소드를 추가함

    /**
     * 1건 데이터 얻기
     */
    private void showOne() {
        System.out.println("---1건의 데이터 얻기---");
        // Repository를 사용하여 1건의 데이터를 얻고 결과를 얻음
        // return값은 Optional
        Optional<Account> accountOptional =repository.findById(2);
        // 값 존재 확인
        if(accountOptional.isPresent()) {
            System.out.println(accountOptional.get());
        } else {
            System.out.println("해당 퀴즈가 없습니다.");
        }
        System.out.println("---1건 데이터 얻기 완료---");
    }

showOne 메소드에서는 CrudRepository를 상속하에 사용가능하게 된 findById 메소드를 호출하여 메소드에 제시된 값에 대응하는 엔티티를 얻을 수 있음.
여기서는 Primary Key에 대응하는 id의 2를 넘김.
findById 메소드의 리턴값은 Optional(java.util.Optional)
null일지도 모르는 값이 있을 수도 있기 때문에 Optional을 통해 값을 래핑하여 사용함.
Optional의 메소드 isPresent()를 통해 값이 들어있는지를 확인하여 get 메소드로 래핑한 값을 취득함.
값이 존재하지 않으면 런타임 예외 - NoSuchElementException 을 던짐.

마찬가지로 AccountApplicaion의 execute메소드 수정

    /**
     * 실행 메소드
     */

    private void execute() {
        // 등록처리
        //setup();
        //showList();
        showOne();
    }

다음과 같은 값이 출력된다.

업데이트 프로세스 실행

AccountApplicaion 클래스에 아래 메소드를 추가

    /**
     * 업데이트 처리
     */
    private void updateAccount() {
        System.out.println("--- 업데이트 처리 시작 ---");
        // 변경 엔티티 설정
        Account account1 = new Account(1, "abab","가가가", "abab@gmail.com", "1212");
        // 업데이트 실행
        account1 = repository.save(account1);
        // 업데이트 확인
        System.out.println("업데이트 된 데이터: " + account1);
        System.out.println("--- 업데이트 처리 완료 ---");
    }
}

updateAccount 메소드는 CrudRepository를 상속하에 사용가능하게 된 save 메소드를 호출하여 지정한 엔티티를 데이터베이스에 저장함.
save에 대한 설명은 앞서 했으므로 생략.

AccountApplicaion의 execute 메소드도 수정

    /**
     * 실행 메소드
     */

    private void execute() {
        // 등록처리
        //setup();
        //showList();
        //showOne();
        updateAccount();
    }

실행결과

제대로 실행되었음을 알 수 있음.

삭제 실행

AccountApplicaion 클래스에 아래 메소드를 추가

    /**
     * 삭제
     */
    private void deleteAcoount() {
        System.out.println("--- 삭제 처리 실행 ---");
        repository.deleteById(2);
        System.out.println("--- 삭제 처리 완료 ---");
    }
}

상속받은 CrudRepository의 deleteById 메소드 사용
Id 2인 엔티티 삭제하게 됨.

AccountApplicaion 클래스 execute메소드 수정

	/**
     * 실행 메소드
     */
    private void execute() {
        // 등록처리
        //setup();
        //showList();
        //showOne();
        //updateAccount();
        deleteAcoount();
    }

실행 결과

정상적으로 실행이 됨.

profile
초보 개발자

0개의 댓글