SPRING
[스프링 핵심 원리-고급] 쓰레드 로컬 주의사항
기본적으로 WAS는 쓰레드풀에서 쓰레드를 관리하고, 요청이 들어오면 쓰레드 하나를 꺼내서 사용한다. ThreadLocal를 사용하여 특정 데이터를 저장 처리한다.(전용 데이터를 보관중) 해당 작업이 끝나고 thread-A를 쓰레드풀에 반환하지만, 해당 쓰레드를 메모리에서 반환하는게 아닉 때문에, ThreadLocal에는 이전에 사용하던 데이터가 남아있게된다. 그다음 요청이 들어왔을때 하필 그 thread-A가 할당되면, 기존 데이터와 혼선이 발생함 해결방안? - 요청을 받아 처리가 끝나면 ThreadLocal.remove()를 통해 꼭 제거한다.
[JPA]스프링 데이터 Common:커스텀 리포지토리
쿼리 메소드로 해결이 되지 않는 경우 직접 코딩으로 구현가능 스프링 데이터 리포지토리 인터페이스에 기능 추가 스프링 데이터 리포지토리 기본 기능 덮어쓰기 가능 구현 방법 커스텀 리포지토리 인터페이스 정의 인터페이스 구현 클래스 만들기(기본 접미어는 IMPL) 엔티티 리포지토리에 커스텀 리포지토리 인터페이스 추가 public Interface PostCustomRepository extends JpaRepository, PostcustomRepository{ List findMyPost(); } 기본 기능도 사용하되 일부 기능은 Override하여 나의 입맛에 맞게 수정하여 사용함 @Repository @Transactional public class PostcustomRepositoryImpl imple..
[JPA]MappedSuperClass
@MappedSuperclass public class BaseEntity{ @Column(name = "INSERT_MEMBER") privateString createdBy; //위 방법으로 하면 해당 테이블 이름을 INSERT_MEMBER로 생성함 private LocalDateTime createDate; private String lastmodifiedBy; private LocalDateTime lastModifiedDate; } 위와 같이 공통으로 사용하는 컬럼의 base entity를 생성함 상속관계 매핑이 아니다. 엔티티가 x (baseEntity 테이블이 생성되는게 아님) 부모 클래스를 상속 받는 자식 클래스에 매핑 정보만 제공 조회, 검색 불가 직접 생성해서 사용할 일이 없으므로 추상..
[JPA] 프록시
지연 로딩 기능을 사용하려면 실제 엔티티 객체 대신에 데이터베이스 조회를 지연할 수 있는 가짜 객체가 필요한데 이것을 프록시 객체라고 한다. 프록시 특징 프록시 클래스는 실제 클래스를 상속 받아서 만들어지므로 실제 클래스와 겉 모양이 같다. 프록시 객체의 초기화 프록시 객체는 member.getName()처럼 실제 사용될 때 데이터베이스를 조회해서 실제 엔티티 객체를 생성하는데 이것을 프록시 객체의 초기화라 한다. 프록시의 특징 프록시 객체는 처음 사용할 때 한번만 초기화된다. 프록시 객체를 초기화한다고 프록시 객체가 실제 엔티티로 바뀌는 것은 아니다. 프록시 객체가 초기화되면 프록시 객체를 통해서 실제 엔티티에 접근할 수 있다. 프록시 객체는 원본 엔티티를 상속받은 객체이므로 타입 체크 시에 주의해서 ..
[JPA]객체지향 쿼리 심화
벌크 연산 엔티티를 수정하여 영속성 컨텍스트의 변경 감지 기능이나 병합을 사용하고 삭제할때 EntityManager.remove() 사용한다. 하지만 이 방법으로 수백개 이상의 엔티티를 하나씩 처리하기에는 시간이 너무 오래걸리고, 이럴 때 여러건을 한 번에 수정하거나 삭제하는 벌크 연산을 사용한다.\ // UPDATE 벌크 연산 String sqlString = "update Product p set p.price = p.price * 1.1 where p.stockAmount < :stockAmount"; int resultCount = em.createQuery(sqlString).setParameter("stockAmount", 10).executeUpdate(); 벌크 연산은 executeUpda..
[JPA]NamedQuery
미리 정의해서 이름을 부여해두 사용하는 sql로 정적 쿼리에서만 사용 가능하다.어노테이션 , XMl에 정의하며, 애플리케이션 로딩 시점에 초기화 후 재사용 한다. 애플리케이션 로딩 시점에서 쿼리를 검증 @Entity @NamedQuery( name ="Member.findByUsername", query = "select m from Member m where m.username = :username" //blabla ) 사용은 아래와 같이 할 수 있다. List results = em.createNamedQuery("Member.findByUserName", Member.class) .setParameter("username", "회원1") .getResultList();
[JPA] 엔티티 직접사용
[JPQL] jpql에서 엔티티를 직접 사용하면 SQL에서 해당 엔티티의 기본 키 값을 사용 SELECT count(m.id) from Member m //엔티티의 아이디를 사용 SELECT count(m) from Member m // 엔티티를 직접 사용 위 두문장은 똑같은 쿼리를 발생함 [sql] select count(m.id) as cnt from Member m 엔티티 직접 사용- 외래키값 1.SELECT m from Member m where m.team = : team 2.m.team.id 위 두문장은 똑같은 쿼리를 발생함(외래키) [sql] SELECT m.^ from member m where m.team_id=?
[JPA] 값 타입종류
엔티티 타입 @Entity로 정의하는 객체 데이터가 변해도 식별자로 지속해서 추적 가능 값 타입 int, integer, String처럼 단순히 값으로 사용하는 자바 기본 타입이나 객체 식별자가 없고, 값만 있으므로 변경시 추적 불가 값타입의 분류 기본값 타입2.값을 공유하면 안됨 int, double 같은 기본 타입은 절대 공유 x Integer같은 래퍼 클래스나 String같은 특수 클래스는 공유 가능한 객체이지만 변경이 안됨 3.자바 기본 타입(int, double)5.String 4.래퍼 클래스(Integer, Long) 1.(생명주기를 엔티티의 의존 → 회원을 삭제하면 이름, 나이 필드 함께 삭제) 임베디드 타입(예를 들면 x,y값을 같이 묶어서 사용하고 싶을때) 새로운 값 타입을 직접 정의할 ..
[JPA] Hibernate 초기화 전략
Spring-data-JPA와 DBMS를 연결해서 사용할 때 간편히 개발환경의 변경사항을 적용하여 테스트 할 수 있다. DDL Generation Spring은 EntityScan을 통해 @Entity 에노테이션이 명시한 클래스를 찾는다. Spring.jpa.generate-ddl=true 옵션을 true로 설정하면 해당 데이터를 근거로 서버 시작 시점에 DDL문을 생성하여 DB에 적용한다. jpa.generate설정은 JPA 구현체 DDL 생성 옵션의 링크이고, true/false밖에 선택할 수 없다. Spring.jpa.hibernate.ddl-auto 옵션을 통해 보다 상세한 데이터 베이스 초기화 전략을 설정할 수 있음 none: 아무것도 실행하지 않음 create-drop : SessionFact..
[스프링 핵심 원리-고급] ThreadLocal
쓰레드 로컬은 해당 쓰레드만 접근할 수 있는 특별한 저장소를 말한다. (같은 인스턴스의 쓰레드 로컬 필드에 접근해도 문제가 없음) ThreadLocal을 활용한 예제 코드 작성 @Slf4j public class ThreadLocalService { private ThreadLocal nameStore = new ThreadLocal(); public String logic(String name) { log.info("저장 name={} -> nameStore={}", name, nameStore.get()); nameStore.set(name); sleep(1000); log.info("조회 nameStore={}", nameStore.get()); return nameStore.get(); } pri..