- 1. Jpa활성화(코드스니펫)
문제: 코드 스니펫을 보고 타이핑 ->안보고 작성할 정도에 공부는 필요
@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class) // JPA Auditing 활성화
public abstract class BaseEntity {
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdAt;
@Setter
@LastModifiedDate // 수정 시간 자동 업데이트
private LocalDateTime updatedAt;
}
@EnableJpaAuditing
@SpringBootApplication
public class ScheduleApplication {
public static void main(String[] args) {
SpringApplication.run(ScheduleApplication.class, args);
}
}
- 2. filter부분& Webconfig(코드스니펫)
문제: 코드 스니펫을 보고 타이핑 ->안보고 작성할 정도에 공부는 필요
@Configuration
public class WebConfig {
@Bean
public FilterRegistrationBean loginFilter(){
FilterRegistrationBean<Filter> filterRegistrationBean= new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new LoginFilter());
filterRegistrationBean.setOrder(1);
filterRegistrationBean.addUrlPatterns("/*");
return filterRegistrationBean;
}
}
package com.example.schedule.login;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.util.PatternMatchUtils;
import java.io.IOException;
public class LoginFilter implements Filter {
private static final String[] whiteList={"/home/login","/home/logout","/authors"};
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest=(HttpServletRequest) servletRequest;
String requestURL=httpServletRequest.getRequestURI();
HttpServletResponse httpServletResponse=(HttpServletResponse) servletResponse;
HttpSession httpSession=httpServletRequest.getSession(false);
if (!IsWhiteList(requestURL)) {
if (httpSession == null || httpSession.getAttribute(Const.LOGIN_USER) == null) {
throw (new IOException("하기싫어요"));
}
}
filterChain.doFilter(httpServletRequest,httpServletResponse);
}
private boolean IsWhiteList(String requestURL ){
//보고 하자
return PatternMatchUtils.simpleMatch(whiteList,requestURL);
}
}
- 3. Password(발제)
목적 : 비밀번호 설정
@Component ->"생성자 주입하면 되겠네"-> 문제가 발생x
문제:아래 코드를 보면서 작성했기 때문에 공부 필요합니다
궁금증:Spring Security 을 사용해도 아래코드가 필요한가?
import at.favre.lib.crypto.bcrypt.BCrypt;
import org.springframework.stereotype.Component;
@Component
public class PasswordEncoder {
public String encode(String rawPassword) {
return BCrypt.withDefaults().hashToString(BCrypt.MIN_COST, rawPassword.toCharArray());
}
public boolean matches(String rawPassword, String encodedPassword) {
BCrypt.Result result = BCrypt.verifyer().verify(rawPassword.toCharArray(), encodedPassword);
return result.verified;
}
}
- 4 jqpl문(아래 블로그)
목적 : Return LoginResponseDto
검색: jpa 기본문법 구글
Member singleResult1 = em.createQuery("select m from Member as m where m.username = :username", Member.class)
.setParameter("username", "member1")
.getSingleResult();
해결법: 위 코드를 목적에 qurey문 변환,class 변환, parameter 변환
결론 :아직 미숙한 jqpl문 추가적인 공부가 필요합니다.
궁금증: jqpl문보다 더 좋은 방법이 있을지 궁금합니다.
- 5. oneToMany(chatGpt)
문제: 동기화가 안되는 발생
해결법: chatGpt 질문: 동기화가 되지않는 문제가 발생해 원인이 뭐고 이유를 알려줘
@OneToMany(mappedBy = "schedule", cascade = CascadeType.ALL, orphanRemoval = true)
원인 : JPA의 변경 감지가 일어나지 않음 (하이버네이트의 1차 캐시 문제)
해결 : @OneToMany를 @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)로 변경하여 schedule 만 저장해도 자동으로 저장되도록 설정할 수도 있음.- mappedBy = "schedule" → 연관 관계의 주인을 Task로 설정하여, 외래 키 관리
- cascade = CascadeType.ALL → 부모의 변경이 자식에게 자동으로 반영되도록 설정
- orphanRemoval = true → 부모에서 제거된 자식 엔티티를 자동으로 삭제
궁금증: 하이버네이트의 1차 캐시 문제가 무엇인가?
- 6. page
목적 : 페이지 표현하기
해결법 : 아래코드들 참고해서 구현방식 참고한 후, 본 코드에 맞게 수정
문제: "Page<>" 자체에 이해가 부족-> "List<>"로 표현
// Controller
@GetMapping("/users")
fun findAll(pageable: Pageable): ResponseEntity<UsersResponse> {
val usersResponse = userService.findAllUsers(pageable)
return ResponseEntity.ok(usersResponse)
}
// Service
fun findAllUsers(pageable: Pageable): UsersReponse {
val findUsers = users.findAllUsersWithPaging(pageable)
return UsersReponse.from(findUsers)
}
// Repository
fun findAllUsersWithPaging(pageable: Pageable): Page<Task>
Pageable pageable = PageRequest.of(pageNo, PAGE_SIZE, Sort.by(Sort.Direction.DESC, criteria));
- 7. @NotBlank
문제: No validator could be found for constraint 'jakarta.validation.constraints.NotBlank' validating type
'java.lang.Long'. Check configuration for 'id']
해결: Long에는 NotBlank가 안된다. NotLull로 해야 한다.(type이 맞지 않습니다)
해결방법: 영어 잘 읽고 1차 수정 -> 구글 검색 후 2차 수정-> ChatGpt 사용 3차 수정 ->튜터님 질문 4차 수정
[JPA] JPQL 기본문법(JPA 기본편 by 김영한)
JPQL 기본문법 이제까지 단순히 특정 pk값의 객체를 조회할 때 em.find()를 사용해왔습니다. 하지만 만약 조건이 더 복잡한 조회를 해야한다면 JPQL을 사용해야합니다! JPQL은 객체지향적으로 쿼리문
velog.io
https://xrabcde.github.io/pagination/
JPA/No offset 방식으로 페이징 성능 개선하기
offset 방식에서 no offset 방식으로 개선하는 방법과 성능 차이에 대해 알아보자
xrabcde.github.io
[JPA] Spring Data Jpa + Pageable로 Pagination 쉽게 구현하기
이번주는 독서리뷰를 남길 수 있는 미니 프로젝트를 진행하고 있다. 리뷰 글을 특정 조건으로 뽑아서 정렬 기준을 선택하여 조회하는 기능을 구현하고자 한다.전체 리뷰글을 조회하거나, 내가
velog.io