spring 9

Spring boot Transactional rollback test와 Transaction 격리에 관한 소고(feat. requires_new)

Transactional rollback test와 Transaction 격리에 관한 소고 다들 알다시피, @SpringBootTest 에서 @Transactional 을 설정하면, 테스트 환경에서 진행한 내용이 실제로 DB와 격리된다. 즉, 테스트에서 뭘 하든 간에 실제 DB에 적용되지 않는다는 것이다. 나는 이거를 통해 여러 테스트를 해 보았는데(사실 근데 혼자 테스트할때는 거의 맨날 넣었다) 이번에 좀 생각치도 못한 변수를 마주해서 정리한다. Transactional의 기본 propagation은 REQUIRED이다. 기본적으로 Spring Boot의 propagation은 REQUIRED로 되어있고, 이건 이전에 활성화된 트랜잭션이 있다면 그 안에서 따로 새로운 트랜잭션의 호출 없이 거기 참가한다..

Spring 기본(IoC, DI, Bean)

IoC 컨테이너 Inversion of Controll 말하자면 제어의 역전 이라는 것이다. 그래서 그게 뭔데? 라고 하면 말하자면 "주도권을 뺴앗겨서, 그 주도권이 Spring에게 있다."는 뜻이다. 예를 들어 Class 설계도 Object 실체화가 가능한 것 예를 들어 abstract class처럼 실제로 존재하지 않는 것들은 Object가 될 수 없다. Instance 실체화 된 것 이런 3개에 대하여 생각해 보았을 때에 보통은 java에서 Public void MakeHandsomeMan() { Ryoochan ryoochan = new Ryoochan(); }이런 식으로 직접 heap영역에 만들었을 것이다. 그러면 MakeHandsomeMan 에서만 ryoochan이 존재하고, 다른 곳에서는 사..

Springboot에서 외부 Redis에 값을 넣고 빼보자(feat.pipeline, Spring boot 3.0)

코드는 https://github.com/RyooChan/redis-pipeline/tree/main 여기서 확인 가능 Springboot에서 외부 Redis에 값을 넣고 빼보자(feat.pipeline, Spring boot 3.0) 해당 테스트를 하기 전에 Redis는 localhost가 아닌 외부에 존재한다고 가정한다. (외부 레디스를 사용하면 네트워크 지연 시간이 발생하게 될 것이다.) 알다시피 레디스는 굉장히 속도가 빠르다. 그렇지만 레디스와 서버는 TCP 네트워크 모델을 기반으로 통신한다. 이게 무슨 뜻일까... 하면, redis와 서버간의 통신 과정에서 TCP 3-way handshake를 따르고, 여러 번 통신을 하면 결국 속도에서 손해를 볼 수밖에 없다는 것이다. 한번 이를 테스트해 보자..

Springboot3.0에서 [Spring] Could not resolve all files for configuration ':classpath'. 해결하기!!

Springboot3.0에서 [Spring] Could not resolve all files for configuration ':classpath'. 해결하기!! Springboot3.0이 나왔다!! 근데 이거를 깃에서 클론받아서 쓰려하면 Could not resolve all files for configuration ':classpath'. 요런 에러가 나면서 안될때가 있다. 이게 안되는 이유는 아마 JDK버전 문제일 가능성이 크다. 왜냐면 Spring Boot 3.0 이상 버전에서는 JDK17이상만 지원하기 때문! 그니까 당신의 컴터는 다른 JDK인데 필요한게 JDK17이상이기 때문 해결법 IntelliJ의 preference에 들어가서 cmd + , Build, Ex..

querydsl에서 다대다 구현하기. 일대다-다대일(feat. Result Aggregation)

querydsl에서 다대다 구현하기. 일대다-다대일(feat. Result Aggregation) 보통 다대다 매핑을 할 때에는 일대다 - 다대일로 매핑하도록 시킨다. 이 이유는 어차피 JPA에서 만든 후에 이를 처리해주기 위한 중간 테이블을 생성하게 된다. 근데 이 테이블을 사용하는 동안 정체모를 쿼리가 발생할 가능성이 있다. 중간 테이블에도 메타 데이터 등의 추가 쿼리가 필요할 수 있는데, 이를 다대다에서는 개발자가 넣어줄 수 없다. 암튼 그래서... 일대다 다대일로 하는데, 여기서 하나의 파트에서 반대 파트의 데이터를 가져오는 방법을 살펴보도록 한다. 상황 먼저 프로젝트 밈위키 에서는 대충 뭐 이런 느낌으로 "밈 - 태그" 를 갖고 있다. 이는 생각해보면 이렇게 밈과 태그가 다대다로 묶여 있어서 밈..

save랑 saveAll(feat. Transactional)

save랑 saveAll(feat. Transactional) Spring Data JPA를 통해 다양한 쿼링을 쉽게 해줄 수 있다. 근데 만약에 여러 insert를 해줘야 하는 경우가 있다면 어쩔까?? 상황 일단 Spring Data JPA에 대해 안다고 가정한다. 여러 값을 저장할 때에 save방식 넣을값들.forEach( index -> 저장레포지터리.save(index) )이거랑 saveAll방식 저장레포지터리.saveAll(넣을값들);의 차이가 뭘까?? save 일단 save를 한번 본다. saveAll 이제 saveAll을 본다 뭐가 다른겨? 사실 saveAll을 보면 최초에 Transactional 어노테이션 실행 해당 함수 내에서 save함수 실행 저 save는 save함수임 이렇게 간다...

spring boot No serializer found for class 오류

No serializer found for class 오류 프로젝트를 하던 중에 만난 문제인데, 쓸데없이 시간을 자꾸 낭비하게 되어 기록하게 되었다. A의 값을 가져올 때에 A_DTO, B_DTO 이런 식으로 여러 DTO들을 통해 값을 가져오는데 자꾸 No serializer found 에러가 났다. 아니 근데 DTO를 써주고 있는데 직렬화 문제가 왜 나는거지...? 싶었는데 1시간동안 삽질하다가 간단한 문제를 발견했다. 이런 느낌으로 에러가 있을 때에 결국 실제 문제는 tagMemeDetailResponses쪽에서 난건데...? 하고 보았는데 @Getter가 설정이 안돼있었다 그러니까 DTO를 쓸때에 혹시라고 seriablizer 에러가 나면 사용하는 모든 DTO를 확인하면서 @Getter 어노테이션이..

Spring Data JPA에서 get 과 find의 차이

Spring Data JPA에서 ID를 통하여 어떤 엔티티를 조회하고 싶을 때, 우리는 getById나 findById를 사용한다. 둘 간에 어떤 차이가 있을까?? getById @Override public T getById(ID id) { Assert.notNull(id, ID_MUST_NOT_BE_NULL); return em.getReference(getDomainClass(), id); } getById의 내부를 살펴보면 이렇게 나온다. 이 getById는 em.getReferecnce를 이용해서 엔티티를 조회..하는데, 사실 이거는 엔티티가 아니라 프록시를 반환한다는 것이다. 즉, getById를 통해 바로 DB에 검색하는게 아니라, 이를 실제로 사용할 때에 DB에 접근한다는 것이다. 한마디로..

필터와 인터셉트

필터와 인터셉트 게시판을 만들 때, 만약 해당 페이지의 가입자만이 사용할 수 있는 '회원게시판' 을 구현하려고 한다면 단순히 해당 게시판에 들어가는 것 뿐만이 아니라 이와 관련된 모든 부분(글쓰기, 읽기, 마이페이지 등등...) 에서 모두 로그인 로직을 검사해야 할 것이다. 그렇다면 이 로직은 어떻게 만들까?? 먼저 매번 모든 페이지에 해당 로직을 구현해서 넣어준다면...너무 귀찮고 문제 발생 가능성도 높을 것이다. 이럴 때에 사용하는것이 바로 필터와 인터센터이다. 해당 두 가지 방법을 통해 위의 방법을 구현해 낼 수 있다. 먼저 두 방식의 차이는 아래와 같다. 그림을 통해 알 수 있는사실은 Filter은 DispatcherServlet의 앞에서 이루어진다. Interceptor은 Disp..

이론 정리/java 2022.04.02