본문 바로가기
Blog/TIL

[240530] 도메인 연관 관계의 중요성

by 코젼 2024. 5. 30.
728x90
반응형

🔶ArrayDeque

🔶JPA 연관 관계

🔶DB Profile

🔶Git


목차

    / 오늘의 TIL /


    ArrayDeque

    Stack, Queue보다 좋은 성능을 가지고 있고, 둘다 구현할 수 있다.

     

    https://school.programmers.co.kr/learn/courses/30/lessons/76502

    괄호 회전하기 (Stack 사용)

    회전하는 문제가 있을 때 원본 문자열을 2배로 늘려서 계산하는 경우 번거로운 회전을 진행시키지 않아도 된다.

    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    import java.util.ArrayDeque;
    import java.util.HashMap;
    import java.util.Map;
     
    public class Solution {
     
        /**
         * 문자열 회전: 괄호 문자를 왼쪽으로 한 칸씩 밀고, 맨 앞의 괄호 문자를 맨 뒤로 보낸다.
         * @param s (원본) 괄호 문자열
         * @return 올바른 괄호 문자열 개수
         */
        public int solution(String s) {
            //괄호 짝을 미리 선언해둔다.
            Map<Character, Character> map = new HashMap<>();
            map.put(')''(');
            map.put(']''[');
            map.put('}''{');
     
            int n = s.length(); //원본 문자열 길이
            //회전 대신 문자열의 길이를 늘려서 확인한다.
            s += s;
            int answer = 0;
     
            A: for (int i = 0; i < n; i++) {
               ArrayDeque<Character> stack = new ArrayDeque<>();
     
                //s 배열 값을 순회하면서 닫힌 괄호가 있는지 확인한다.
                for (int j = i; j < i + n; j++) {
     
                    char c = s.charAt(j);
     
                    //열린 괄호: stack에 추가
                    if (!map.containsKey(c)) {
                        stack.push(c);
                    }
                    //닫힌 괄호: 비교
                    else {
                        //stack이 비어있거나 짝이 안 맞는 괄호인 경우는 올바른 괄호가 아니다. A로 되돌아간다.
                        if (stack.isEmpty() || !stack.pop().equals(map.get(c)))
                            continue A;
                    }
                }
                //continue 되지 않고, 스택이 비어있으면 올바른 괄호 문자열이다.
                if (stack.isEmpty()) {
                    answer++;
                }
            }
            return answer;
        }
    }
     
    cs

    JPA 연관 관계, 객체지향설계

    JPA를 이용해서 객체지향설계를 하게되면 최대한 domain끼리 협력할 수 있게 된다!

     

    연관 관계 주인인 객체가 연결되는 기준이 된다.

    Transaction이 진행되는 상태에서 연관 관계 주인 객체에서 매핑 되어있는 객체를 setter로 설정한 경우,

    아직 commit되지 않았을 때 매핑 되어있는 객체에 getter를 하면 null이다.

    -> 한 번에 양쪽을 setter 연결해서 해결할 수 있다.

    @OneToOne
    private Address address;
    
    public void setAddress(Address address) {
    	this.address = address;
        this.address.setPerson(this); //객체 서로 연결
    }

     

    연관 관계 주인은 @JoinColumn을 사용해서 속성을 설정할 수 있다. (@Column 대신)

    cascade 옵션을 통해 연결된 테이블을(연관 관계 주인까지) 삭제시킬 수 있다.

    orphanRemoval 옵션을 통해 객체 간의 관계가 끊어진 데이터를 자동으로 제거할 수 있다.

    ex) User <-> UserSell 에서 판매 데이터를 삭제한 경우 db에 있는 판매 데이터도 삭제된다.

     

    Entity에서 외래키처럼 객체를 가져와서 사용하고 싶은 경우

    @ManyToOne(단방향 가능), @OneToMany 등 어노테이션을 사용한다.

    N:1인 경우 N쪽이 연관 관계 주인이어야 한다.

    N:M @ManyToMany 는 구조가 복잡하고 테이블이 직관적으로 매핑되지 않아서 비추천한다.

     

    예시

    User <-> UserSell 테이블이 있다고 가정해보자.

     

    User 테이블에서 사용하는 id 값을 UserSell 에서 userId로 가져와서 사용하는 경우

    유저당 판매 개수가 여러 개가 있기 때문에

    User(1:N), Usersell(N:1) 형태를 가지게 된다.

    create table user (
    	id bigint auto_increment
        primary key(id)
    );
    
    create table user_sell (
    	id      bigint auto_increment,
        user_id    bigint  #user 테이블의 primary key
        primary key(id)
    );

     

    UserSell 테이블이 User의 id를 가지고 있기 때문에, 연관 관계의 주인(관계의 주도권)은 UserSell 테이블이 된다.

    따라서 User 테이블에서 연관 관계가 가지고 있는 필드의 이름(name) (mappedBy = "user') 속성을 등록해준다.

    //UserSell
    @ManyToOne
    private User user; //이 객체 필드명을 mapping 해준다.
    
    //User
    @OneToMany(mappedBy = "user") //mappedBy 속성으로 mapping 해준다.
    private List<UserSell> userSell = new ArrayList<>();

    DB Profile 설정

    application.yml

    local 환경과 dev 환경을 구분해서 환경설정을 하고 싶을 때, profile을 사용한다.

    현재 MODE=MYSQL로 mysql과 유사한 환경을 구축하고 있으나 mysql은 user를 예약어로 사용하기 때문에

    user 테이블이 있는 경우 keyword로 사용하지 않는다고 설정해 주어야 한다.

    h2 db는 memory에서만 동작하기 때문에 ddl이 장기 저장되지 않아서 서버를 재시작 할 때마다 create로 테이블을 생성해 주어야 한다.

    spring:
      config:
        activate:
          on-profile: local
      datasource:
        url: "jdbc:h2:mem:library;MODE=MYSQL;NON_KEYWORDS=USER"
        username: "sa"
        password: ""
        driver-class-name: org.h2.Driver
      jpa:
        hibernate:
          ddl-auto: create
        properties:
          hibernate:
            show_sql: true
            format_sql: true
            dialect: org.hibernate.dialect.H2Dialect
      h2:
        console:
          enabled: true
          path: /h2-console

    Git

    1. git iniit
    2. git remote add origin [repository 주소]
    3. git add . <-> git reset
    4. git status
    5. git commit -m "메시지"
    6. (최초) git push --set -upstream origin master
    7. (이후) git push origin master
    728x90
    반응형

    'Blog > TIL' 카테고리의 다른 글

    [240601] 코딩 테스트 문제 풀기  (0) 2024.06.01
    [240531] 처음으로 배포를 해보다  (0) 2024.05.31
    [240529] 직접 해봐야 안다  (0) 2024.05.29
    [240528] 백문이 불여일타!  (0) 2024.05.28
    [240527] 코딩테스트 다다익선  (0) 2024.05.27

    댓글