일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- PS
- 연관관계
- 스프링 폼
- 백트래킹
- SQL프로그래밍
- 유니크제약조건
- 다대다
- querydsl
- 동적sql
- 연결리스트
- 비관적락
- 힙
- 지연로딩
- eager
- CHECK OPTION
- BOJ
- FetchType
- shared lock
- execute
- JPQL
- 데코레이터
- 낙관적락
- exclusive lock
- 일대다
- 다대일
- 스토어드 프로시저
- 즉시로딩
- fetch
- 이진탐색
- dfs
- Today
- Total
목록JPA (46)
흰 스타렉스에서 내가 내리지
예를 들어, 북마크 여부를 boolean 타입으로 사용하고 싶다고 하자. JPA 를 사용하면 DB에 저장될 때 0 또는 1인 숫자로 저장된다. 그런데 DB 에 숫자 대신 문자 Y 또는 N 으로 저장하고 싶다면 컨버터를 사용하면 된다. @Entitypublic class Member { ... @Convert(converter=BooleanToYNConverter.class) private boolean bookmarked; ...} - Boolean 을 YN 으로 변환해주는 컨버터@Converterpublic class BooleanYNConverter implements AttributeConverter{ @Override public String co..
즉시 로딩은 JPQL 을 실행할 때 N+1 문제가 발생할 수 있다.그럼, 지연 로딩일 때는 N+1 문제가 발생하지 않는가? @Entitypublic class Order{ ... @ManyToOne(fetch = FetchType.EAGER) private Member member; ...} 주문 엔티티를 조회하면 연관된 member 엔티티도 항상 함께 로딩된다. # 글로벌 페치 전략에 즉시 로딩 사용 시 단점사용하지 않는 엔티티를 로딩한다.N+1 문제가 발생한다. # N+1 문제em.find() 메소드로 엔티티를 조회할 때 연관된 엔티티를 로딩하는 전략이 즉시 로딩이면, 데이터베이스에 JOIN 쿼리를 사용해서 한 번에 연관된 엔티티까지 조회한다. Order or..
스프링 컨테이너는 트랜잭션 범위의 영속성 컨텍스트 전략을 기본으로 사용한다.이 말은 트랜잭션의 범위와 영속성 컨텍스트의 생존 범위가 같다는 뜻이다. 트랜잭션을 시작할 떄 영속성 컨텍스트를 생성하고, 트랜잭션이 끝날 때 영속성 컨텍스트를 종료한다.같은 트랜잭션 내에서는 항상 같은 영속성 컨텍스트에 접근한다. 즉, 1트랜잭션 1PC -- -- 보통 서비스 계층에 @Transactional 어노테이션을 선언해서 트랜잭션을 시작한다.이 어노테이션이 있으면 호출한 메서드를 실행하기 직전에 스프링의 트랜잭션 AOP 가 먼저 동작한다. # 흐름도 트랜잭션 시작⬇️메서드 호출⬇️메서드 정상 종료⬇️Persistence Context flush⬇️DB 트랜잭션 커밋-- 만약 메서드에서 예외가 발생하면 트랜잭션을 롤백..
# 영속성 컨텍스트에 이미 엔티티 데이터가 있는데, 이를 다시 JPQL 로 조회하면?em.find(Member.class, "hong");em.createQuery("select m from Mmebr m", Member.class).getResultList(); JPQL 로 데이터베이스에서 조회한 엔티티가 영속성 컨텍스트에 이미 있으면, JPQL 로 데이터베이스에서 조회한 결과를 버리고 대신에 영속성 컨텍스트에 있던 엔티티를 반환한다.이 때, 식별자 값을 사용해서 비교한다. JPQL 은 항상 데이터베이스에 SQL 을 실행해서 결과를 조회한다. JPQL 을 사용해서 조회를 요청한다JPQL 은 SQL 로 변환되어 데이터베이스를 조회한다.조회한 결과와 영속성 컨텍스트를 비교한다식별자 값을 기준으로 memb..
# 스프링 데이터의 Page, Pageable 활용 @Override public Page searchPage(MemberSearchCondition condition, Pageable pageable) { List content = queryFactory .select(new QMemberTeamDto( member.id, member.username, member.age, team.id, team.name)) .from(member) .leftJoin(member.team, team) .where(usernameEq(condition.getUsername()), teamNameEq(condition.getTeamName()), ageGoe(condition.getAgeGoe()), ageLoe(con..
이 때, search() 는 querydsl 메소드이다. public interface MemberRepository extends JpaRepository, MemberRepositoryCustom { List findByUsername(String username); } /***/ public interface MemberRepositoryCustom { List search(MemberSearchCondition condition); } /***/ public class MemberRepositoryImpl implements MemberRepositoryCustom{ private final JPAQueryFactory queryFactory; public MemberRepositoryImpl(E..
# 회원 검색 조건 클래스 @Data public class MemberSearchCondition { //회원명, 팀명, 나이(ageGoe, ageLoe) private String username; private String teamName; private Integer ageGoe; private Integer ageLoe; } # 동적 쿼리 - Builder 사용 // Builder 사용 // 회원명, 팀명, 나이 (ageGoe, ageLoe) public List searchByBuilder(MemberSearchCondition condition){ BooleanBuilder builder = new BooleanBuilder(); if(StringUtils.hasText(condition.g..
# member → M @Test public void sqlFunction(){ List result = queryFactory .select(Expressions.stringTemplate( "function('replace', {0}, {1}, {2})", member.username, "member", "M")) .from(member) .fetch(); } select m.username from member m; select replace(m.username, 'member', 'M') from member m; # 소문자로 변경해서 비교하라 @Test public void sqlFunction2(){ List result = queryFactory .select(member.username)..
# 벌크 연산 쿼리 한 번으로 대량 데이터 수정 # 나이가 28 미만인 회원의 이름을 비회원으로 지정 @Test @Commit public void bulkUpdate(){ long count = queryFactory .update(member) .set(member.username, "비회원") .where(member.age.lt(28)) .execute(); em.flush(); em.clear(); List result = queryFactory .selectFrom(member) .fetch(); for (Member member1 : result){ System.out.println("member1 = " + member1); } } 벌크 연산이 수행되는 순간 영속성 컨텍스트와 DB 는 일치..
# 동적 쿼리를 해결하는 두가지 방식 1. BooleanBuilder 2. Where 다중 파라미터 사용 BooleanBuilder 도 많이 쓰이지만, 이 방법을 사용하면 훨씬 깔끔해진다. private List searchMember2(String usernameCond, Integer ageCond){ return queryFactory .selectFrom(member) .where(usernameEq(usernameCond), ageEq(ageCond)) .fetch(); } private BooleanExpression usernameEq(String usernameCond){ return usernameCond != null ? member.username.eq(usernameCond) : n..