오늘 배운 것 :
InteliJ DB 조회, 시퀄날리기 IDE에서 하는 법
view > tools window > Database 툴 꺼내고
+ 눌러서 DB connection 정보 설정하면 테이블하고 컬럼, 데이터 타입 조회
SQL 날리기까지 전부 IDE에서 할 수 있음
(IDE에서 날리는 거라 환경빨을 많이 탄다. 구글링 필수)
InteliJ 디버깅 하는 법
break point 걸고 thread 선택, make 하고 디버깅 모드(shift+f9) 틀면 됨
f8 라인 이동, 나머지는 아이콘으로 되어있음
JPA 영속성 컨텍스트
뭔가 어려워 보이지만 그냥 Ioc 컨테이너와는 다르게 JPA가 따로 가지고 있는 컨테이너(임시 저장소)에 캐시(임시 저장)로 DB로 보냈던 테이블 데이터 정보를 어느 정도 쌓아두고 있어 굳이 조회 같은 상황에 DB에 SEQ을 날릴 필요없이 임시로 저장했던 값 중에 그와 일치하는 값이 있으면 그걸 꺼내 써서 굳이 DB에 접속하는 횟수를 줄이겠다는 거다
(일치하는 값이 캐시에 없으면 어쩔 수 없이 DB 다시 접속하는 거고)
장점1 DB 커넥션 횟수를 줄임
장점2 객체 동일성 보장 (DB row 1개당 Java 객체 1개가 사용되는 것을 보장)
객체 동일성 보장
싱글톤을 생각하면 된다
DB에서는 Row 1개가 하나의 데이터일 뿐이지만
Java에서는 인스턴스화 할 때마다 내용물(멤버변수)이 같더라도 참조변수라 각각 다른 메모리 주소를 포인터하는 객체가 생성된다. 이때 생성되는 객체가 포인터로 1차 캐시에 있는 DB로 들어간 데이터의 원본을 똑같이 가리키게 되면 DB처럼 객체(row) 1개당 동일한 객체를 가리키는(포인터) 상황이 되므로 객체 동일성 보장인지 뭐시긴지를 보장할 수 있게된다
(ID 어노테이션을 부여한 PK값을 식별자로 하는지 아니면 정말로 메모리 주소를 타게팅해 포인팅하는 지는 잘 모르겠다)
(물론 내부적으로 JPA와 Java가 알아서 하는 부분이고 자바에는 포인터 따위 없으므로 알고만 있으면 됨)
@Transactional 붙이면 DB에 commit, rollback 등을 처리하기 전, SEQ을 대신 번역해서 던져주는 서비스메소드가 끝나는 시점에 spring 객체와 DB 데이터 불일치 등의 문제가 있으면 예외처리를 적용해 문제들을 catch해 일괄적으로 rollback 같은 것을 대신하던지 아니면 불일치하는 결과값을 수정해주던지 하는 어노테이션이라고 한다
(저 어노테이션을 붙이면 갑자기 출처모를 변덕이 끓어올라 미친듯이 entity의 변수에 setter로 똥을 묻혀도 마법처럼 변경 내역이 변화한다. (뭐지ㅅㅂ...) 눈에 보이는 대로 절차적으로 분석하려하면 지는거임)
- 간단히 함수가 종료되는 시점에 각 Entity 에 save() 가 호출된다라고 이해
정말 위 글처럼 생각해야 넘어갈 수 있을 듯
JPA DB 관계성 형성 어노테이션
일대다 (1:N) @OneToMany
다대일 (N:1) @ManyToOne
일대일 (1:1) @OneToOne
다대다 (N:N) @ManyToMany
관계성을 DB단에서 설정해주면 그만큼 서버가 할 일이 적어진다
(= 내가 적을 코드가 기능이 방대해 질수록 적어진다)
Spring Data JPA) 기본 제공해 주는 기능
// 1. 상품 생성
Product product = new Product(...);
productRepository.save(product);
// 2. 상품 전체 조회
List<Product> products = productRepository.findAll();
// 3. 상품 전체 개수 조회
long count = productRepository.count();
// 4. 상품 삭제
productRepository.delete(product);
ID 외의 필드에 대한 추가 기능은 interface 만 선언해 주면, 구현은 Spring Data JPA 가 대신한다
public interface ProductRepository extends JpaRepository<Product, Long> {
// (1) 회원 ID 로 등록된 상품들 조회
List<Product> findAllByUserId(Long userId);
// (2) 상품명이 title 인 관심상품 1개 조회
Product findByTitle(String title);
// (3) 상품명에 word 가 포함된 모든 상품들 조회
List<Product> findAllByTitleContaining(String word);
// (4) 최저가가 fromPrice ~ toPrice 인 모든 상품들을 조회
List<Product> findAllByLpriceBetween(int fromPrice, int toPrice);
}
문법은 공식 문서 참고)
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/
JPA를 사용할 때의 페이징, 페이저 구현
대충 클라이언트에서 url 쿼리로 요청받아다 Page, Pageable, Sort 객체 가져다 쓴다
(page = page -1; page는 인덱스값으로는 시작인 0을 가져와야 하므로 -1 해줘야함)
등차수열 공식 적용해서 DB의 Limit 메소드 같은거 사용해서 view로 만든 다음에 그 view에 order by desc 이런 거 할 필요 없다
(page 디폴트 값을 설정해줘야 처음 클라이언트 로드 당시 문제가 생기지 않을텐데 인자로 받아오는 값에 @pageDefault를 붙여주면 된다. 사실 어노테이션 설정을 해주지 않아도 fallbackPageable 리턴값이 있어 어느정도 디폴트가 잡힌다)
페이저에 대해 잘 정리해주신 분의 블로그 주소 ) https://tecoble.techcourse.co.kr/post/2021-08-15-pageable/
JPA로 DB 관계성 설정만 어노테이션 한줄 띡으로 잘해주면
즐겨찾기 기능이나 폴더 기능 같은 건 아주 쉽게 만들 수 있다
라이브러리, 프레임워크를 사용하는데 오히려 POJO의 숙련도가 중요하게 느껴지는 수준임
(딴애들이 다해주니 데이터 핸들링만 잘하면 되서 그런갑다)
느낀 점:
코드를 이해하지 말고 일단 복붙으로 쓰라고는 하는데 나는 이해하지 못하면 넘어가지 못한다
그럴바에는 어떤 상황에 어떻게 쓰는지 차라리 외우라고 하는 게 나은 것 같다
외우는건 사고력을 떠나 시간만 때려박으면 나같은 평범한 머리로도 가능하다
사람 머리가 서번트 증후군을 앓고 있어 사진적 기억능력을 가진 사람이나 고기능 자폐로 특정 분야로 심하게 발달한 사람을 제외하면 대부분 거기서 거기라고 생각한다
개인적으로 사고력이란 브레인 라이브러리에 저장된 게 많을 수록 활용할 수 있는 리소스가 많아지면 저절로 늘어날 수 밖에 없다고 생각하기 때문에, 본인이 기억력이 낮아 스스로 이미 배웠었다는 점을 인지하지 못해 무의식 중에 사용하는 지식의 발원지를 잊고 스스로가 사고력이 높다고 자평할 뿐이라고 생각하는 파라 그런지 이쪽이 더 몸에 맞는건가 싶기도 하다. 아니면 주입식 교육의 폐해일 수도 있고.
알고있는 공식이 많으면 머리속에서 해당 공식의 사용처를 묶은 카테고리가 다른 카테고리와 엮이며 더 정밀한 복합 공식을 만들어낸다
눈으로 본 자연과 빛이 만들어내는 정보를 정립하고 해석해 담아내는 지식이 많을 수록 현실적인 그림을 그릴 수 있게 된다
개인의 지식이 늘어나면 늘어날수록 한명의 사람으로써 한명의 타인이 판단할 수 있는 이해 범주를 벗어나게 되면 소위 말하는 천재가 되고, 그 단어가 주는 인상과 다르게 천재는 전혀 창의적이랄 것 없이 과거에 사람들이 이미 만들어놓은 지식과 지식을 한데 엮어, 사용된 지식의 원저작자들의 무덤에 자신의 새로운 묘비를 새길 뿐이라고 생각하게 된다
라는 생산성 없이 어디선가 주워들은 내용들을 섞어탕한 개똥철학을 싸지르며 공부하기 싫어서 게으름 피우고 있음
그래도 가만히 생각해보니 그냥 외우는 게 짱인덧 외우자
아쉬웠던 점:
투자 시간대비 자료의 정보 전달 수준이 너무 낮음 또는 내 이해도가 너무 낮음
재밌게 배우려면 돈 써야 함