Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2021.08.06 ~ 2021.08.08] 자바 ORM 표준 JPA 프로그래밍, Two Pointer(투 포인터) 알고리즘 #194

Open
JuHyun419 opened this issue Aug 8, 2021 · 0 comments

Comments

@JuHyun419
Copy link
Owner

JuHyun419 commented Aug 8, 2021

자바 ORM 표준 JPA 프로그래밍 도서

영속성 관리

EntityManager: 엔티티를 저장하고, 수정하고, 삭제하고, 조회하는 등 엔티티와 관련된 모든 일을 처리
엔티티를 저장하는 상의 데이터베이스로 생각

EntityManagerFactory: 엔티티 매니저를 만드는 공장, 단 하나만 생성(비용이 크기 때문에)

영속성 컨텍스트(persistence context): '엔티티를 영구 저장하는 환경'
영속성 컨텍스트 관리하는 엔티티를 영속 상태라고 함
영속성 컨텍스트는 엔티티를 식별자 값(@Id)으로 구분 함, 따라서 영속 상태는 식별자 값이 반드시 있어야 함

JPA는 보통 트랜잭션을 커밋할 때 영속성 컨텍스트에 새로 저장된 엔티티를 DB에 반영 => 플러시 라고 함
영속성 컨텍스트 엔티티를 관리함으로서 생기는 이점
- 1차 캐시
- 동일성 보장
- 트랜잭션을 지원하는 쓰기 지연
- 변경 감지
- 지연 로딩

양방향 매핑 규칙: 연관관계 주인
- 연관관계의 주인만이 데이터베이스 연관관계와 매핑되고 외래키를 관리할 수 있음
- 반면에 주인이 아닌 쪽은 읽기만 능
  - 주인은 mappedBy 속성을 사용하지 않음
  - 주인이 아니면 mappedBy 속성을 사용해서 속성 값으로 연관관계의 주인을 지정
- 연관관계의 주인은 외래키 있는 곳
- 다대일, 일대다 관계에서는 항상 다(Many)쪽이 외래키를 진다. => @ManyToOne이 연관관계의 주인

Class Member {
  @ManyToOne
  @JoinColumn(name="TEAM_ID")
  private Team team;
  ...

class Team {
  @OneToMany(mappedBy="team")
  private List<Member> members = new ArrayList<>();


Class Member {
  @ManyToOne
  @JoinColumn(name="TEAM_ID")
  private Team team;

  // 연관관계 편의 메소드
  public void setTeam(Team team) {
    this.team = team;
    team.getMembers().add(this);
  }

양방향 매핑은 복잡하다. 우선 단방향 매핑을 사용하고 필요시 양방향을 사용하자!

다대다 매핑
- 새로운 기본키 전략
Member <-> Product 엔티티 다대다일때
Member -> Order <- Product 와 같이 중간 엔티티를 하나 둘 것(Order 엔티티는 각 엔티티의 IDFK짐)

@Entity
public class Order {
    
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column
    private Long id;
    
    @ManyToOne
    @JoinColumn(name = "MEMBER_ID")
    private Member member;
    
    @ManyToOne
    @JoinColumn(name = "PRODUCT_ID")
    private Product product;
    
    ...
}

@MappedSuperclass
- 실제 테이블과 매핑되지 않음
- 등록일자, 수정일자, 등록자, 수정자 등 여러 엔티티에서 공통적으로 사용하는 속성을 관리


즉시 로딩(EAGER) + 지연 로딩(LAZY) <<프록시>>
https://zzang9ha.tistory.com/347?category=990401


영속성 전이(CASCADE)
https://zzang9ha.tistory.com/350?category=990401

값 타입
@Embeddable: 값 타입을 정의하는 곳에 표시
@Embedded: 값 타입을 사용하는 곳에 표시

객체지향 쿼리
- JPQL
- Criteria
- QueryDSL
- Native SQL



투 포인터(Two Pointer) 알고리즘

  • 배열에서 완전 탐색으로 시간 초과가 날 경우, 투 포인터 개념을 이용할 수 있음
  • 2개의 포인터(index)를 이용해서 하나의 인덱스는 앞에서부터, 다른 인덱스는 끝에서 부터 접근하는 방식
  • 문제 예제: https://leetcode.com/problems/reverse-vowels-of-a-string/
// 풀이 1

import java.util.ArrayList;
import java.util.List;

public class Reverse_Vowels_of_a_String_345 {
    public static String reverseVowels(String s) {
        List<Integer> vowels = new ArrayList<>();
        for (int i = 0; i < s.length(); i++) {
            if (isVowels(s.charAt(i))) {
                vowels.add(i);
            }
        }

        int reverseIndex = vowels.size() - 1;
        for (int i = 0; i < vowels.size() / 2; i++) {
            int index1 = vowels.get(i);
            int index2 = vowels.get(reverseIndex);
            s = changeIndexChar(s, index1, index2);
            reverseIndex -= 1;
        }
        return s;
    }

    private static boolean isVowels(final char c) {
        return "AEIOUaeiou".indexOf(c) != -1;
    }

    /**
     * str = "hello", index1 = 1, index2 = 4 일때
     * @return "holle"
     */
    private static String changeIndexChar(String str, int index1, int index2) {
        char ch1 = str.charAt(index1);
        char ch2 = str.charAt(index2);
        str = str.substring(0, index1) + ch2 + str.substring(index1 + 1);
        str = str.substring(0, index2) + ch1 + str.substring(index2 + 1);
        return str;
    }
}

image


// 풀이 2

public class Reverse_Vowels_of_a_String2_345 {
    public String reverseVowels(String s) {
        char[] chars = s.toCharArray();
        int index = 0;
        int reverseIndex = s.length() - 1;

        // Two Pointer Approach
        while (index < reverseIndex) {
            if (isVowels(chars[index]) && isVowels(chars[reverseIndex])) {
                char temp = chars[index];
                chars[index] = chars[reverseIndex];
                chars[reverseIndex] = temp;
                index++;
                reverseIndex--;
                continue;
            }
            if (!isVowels(chars[index])) {
                index++;
            }
            if (!isVowels(chars[reverseIndex])) {
                reverseIndex--;
            }
        }
        return String.valueOf(chars);
    }

    private static boolean isVowels(final char c) {
        return "AEIOUaeiou".indexOf(c) != -1;
    }
}

image

시간차이 롸

참고1
참고2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant