[TIL 20] Spring 기초 공부_10

돗치·2024년 3월 6일

Spring으로 CRUD구현하기 DAY1

스프링으로 CRUD기능을 한 번 만들어보자.
Repository를 이용할 것이다.

public interface Repository <T, ID>{
}

를 만들고 DataRepository도 만든다.

package com.example.demo.db;
public interface DataRepository <T, ID> extends Repository <T, ID> {
}

여기서 public interface DataRepository <T, ID> extends Repository <T, ID>는
'엔티티, 즉 데이터의 타입을 받을 것이고 각 고유한 ID를 받을 것이다. 그리고 인터페이스를 상속한다.' 라는 의미다.

DataRepository는 CRUD 기능을 인터페이스로 가지도록 할 것 이다.

Optional<T> findById(ID id)

이건 CRUD 중 Read에 해당한다.
리턴시키는 것은 당연히 method인데 data가 있을 수도 있고 없을 수도 있기 때문에 Optional을 사용한다.
findById는 Data의 ID를 통해서 Data를 return하는 method이다. 즉 ID type의 id를 받아서 return시킬 것이다.

List<T> findAll();

여기서 findById는 한 건을 return하는 것이니 List로 return해주는 FindAll이라는 method를 하나 만들 것이다.

    T save(T data);

이건 CRUD 중 Create, Update에 해당한다.
특정한 data를 가지고 들어올 것이다. 이 data(id)가 여기서 있으면 id를 Update 시키고 없으면 save시킬것이다.

    void delete(ID id);

이건 CRUD 중 Delete에 해당한다.
Delete는 data가 삭제됐기 때문에 return할 게 없고 ID통해서 Delete시키기만 한다.

이제 이러한 DB에 들어가는 data를 정의하는 Entity를 만들어보자.

우선 PrimaryKey라는 interface를 만든다. Id data는 많을 것이니 Long Type을 가질 것이다.

public interface PrimaryKey {
    void setId(Long id);
    Long getId();
}

이를 상속 받는 엔티티 클래스를 만든다.

public abstract class Entity implements PrimaryKey {
    @Getter
    @Setter
    private Long id;
}

추상 클래스를 만들어서 이를 상속받는 것들이 구현을 해도 되고 안 해도 되는 형태로 만들자.
자신만의 저장 공간을 두도록 하는 코드를 만들어보자.

abstract public class SimpleDataRepository<T, ID> implements DataRepository<T, ID>{
    private List<T> dataList = new ArrayList<T>();
    private static long index = 0;
}

이제는 unique하게 id를 지정해줘야한다.
data에 setId를 통해서 id를 넣어줘야 되는데, 이 data가 Generic type이기 때문에 id를 setId를 해줄 수 없는 상황이다.
extends 키워드를 통해서 type을 어느정도 제한을 줄 수 있다.
Entity를 상속받은 ID만 이 type에다가 지정할 수 있다 라고 할 수 있다.
ID에 대한 type은 반드시 Long type으로 제한을 하겠다고 지정해줘야한다.

abstract public class SimpleDataRepository<T extends Entity, ID extends Long> implements DataRepository<T, ID>{

아까 만들었던 entity는 long타입의 변수를 갖고있기 때문에 여기서 T는 entity라고 보면 된다.
그렇기 때문에 data에 setId가 가능해진다.
data에 index를 지정해주고 unique id를 딸 수 있게 된다.
index++ 을 해서 항상 이 index가 unique하게 올라갈 수 있도록 만들어준다.

        data.setId(index);

        dataList.add(data);
        index++;

null일 경우의 예외도 작성해준다.

        if(Objects.isNull(data)){
            throw new RuntimeException("Data is null");
        }

여기도 CRUD 구조로 작성해준다.
Create, Update 부터, data list에 이미 data가 있으면 Update를 하고, 없으면 새로 save를 할 것이다.
그래서 사전에 DB에 이미 있는가를 볼 수 있는 작업을 할 것 이다. 현재 들어있는 data의 getId와 object, 즉 data가 가지고 있는 id가 동일한 경우 findFirst로 찾도록 하자.

        var prevData = dataList.stream()
                .filter(it->{
                    return it.getId().equals(data.getId());
                })
                        .findFirst();

이제는 사전 data가 있는 경우 없는 경우를 작성해주자. 있는 경우에는 업데이트를 할 건데 기존 데이터를 remove하고 새 데이터를 add하는 방식으로 작성한다.
없는 경우는 index++ 해서 들어가고자 하는데다가 set하자.

        if(prevData.isPresent()){
            dataList.remove(prevData);
            dataList.add(data);
        }else{
            data.setId(index);

            dataList.add(data);
            index++;
        } 
         return data;
    }

이제 Read 부분을 작성하자
아까처럼 id를 읽어오고 전체를 list로 읽어오는 것을 작성한다.

    @Override
    public Optional<T> findById(ID id){
        return dataList.stream()
                .filter(it->{
                    return (it.getId().equals(id));
                })
                .findFirst();
    }

sort를 이용해서 전체 리스트를 받아와보자

    private Comparator<T> sort = new Comparator<T>() {
        @Override
        public int compare(T o1, T o2) {
            return Long.compare(o1.getId(), o2.getId());
        }
    };
``
```java
    @Override
    public List<T> findAll(){
        return dataList
                .stream()
                .sorted(sort)
                .collect(Collectors.toList());
    }

Delete는 isPresent로 데이터가 있는 경우 삭제하도록 하자

    @Override
    public void delete(ID id){
        var deleteEntity = dataList.stream()
                .filter(it->{
                    return (it.getId().equals(id));
                })
                .findFirst();
        if (deleteEntity.isPresent()){
            dataList.remove(deleteEntity);
        }
    }

}

이제 CRUD 추상 클래스로 구현체까지 다 만들었다.

전체코드

DataRepository

import java.util.List;
import java.util.Optional;

public interface DataRepository <T, ID> extends Repository <T, ID> {
    T save(T data);
    Optional<T> findById(ID id);
    List<T> findAll();

    void delete(ID id);
}

Repository

public interface Repository <T, ID>{
}

SimpleDataRepository

import com.example.demo.entity.Entity;
import java.util.*;
import java.util.stream.Collectors;

abstract public class SimpleDataRepository<T extends Entity, ID extends Long> implements DataRepository<T, ID>{
    private List<T> dataList = new ArrayList<T>();
    private static long index = 0;


    private Comparator<T> sort = new Comparator<T>() {
        @Override
        public int compare(T o1, T o2) {
            return Long.compare(o1.getId(), o2.getId());
        }
    };

    @Override
    public T save(T data){

        if(Objects.isNull(data)){
            throw new RuntimeException("Data is null");
        }


        var prevData = dataList.stream()
                .filter(it->{
                    return it.getId().equals(data.getId());
                })
                        .findFirst();

        if(prevData.isPresent()){
            dataList.remove(prevData);
            dataList.add(data);
        }else{
            data.setId(index);

            dataList.add(data);
            index++;
        }

        return data;
    }

    @Override
    public Optional<T> findById(ID id){
        return dataList.stream()
                .filter(it->{
                    return (it.getId().equals(id));
                })
                .findFirst();
    }

    @Override
    public List<T> findAll(){
        return dataList
                .stream()
                .sorted(sort)
                .collect(Collectors.toList());
    }


    @Override
    public void delete(ID id){
        var deleteEntity = dataList.stream()
                .filter(it->{
                    return (it.getId().equals(id));
                })
                .findFirst();
        if (deleteEntity.isPresent()){
            dataList.remove(deleteEntity);
        }
    }

}

PrimaryKey

public interface PrimaryKey {
    void setId(Long id);
    Long getId();
}

Entity

public abstract class Entity implements PrimaryKey {
    @Getter
    @Setter
    private Long id;
}

0개의 댓글