스프링 데이터 JPA - 세팅

김강현·2023년 4월 17일
0

스프링 데이터 JPA

목록 보기
1/4
post-thumbnail

한계를 넘어 마법 같은 기술

세팅

스프링 부트 스타터 : https://start.spring.io

왜인지 잘 안됨. 그냥 이거 복붙해서 gradle 돌리기!!

<build.gradle>

plugins {
	id 'java'
	id 'org.springframework.boot' version '2.7.10'
	id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}

group = 'study'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	compileOnly 'org.projectlombok:lombok'
	runtimeOnly 'com.h2database:h2'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
	useJUnitPlatform()
}

Settings > Build, Execution, Deployment > Build Tools > Gradle > ... InteilliJ IDEA 로 변경

Settings > Build, Execution, Deployment > Compiler > Annotaion Processors > Enable annotation processing 체크!! (lombok 사용)

H2 세팅
첫 JDBC URL : jdbc:h2:~/datajpa
이후에는 : jdbc:h2:tcp://localhost/~/datajpa

Application.yml 세팅

처음엔 application.properties 가 있음 -> application.yml 만들고 지워주기!

spring:
  datasource:
    url: jdbc:h2:tcp://localhost/~/datajpa
    username: sa
    password:
    driver-class-name: org.h2.Driver
  jpa:
    hibernate:
      ddl-auto: create
    properties:
      hibernate:
        # show_sql: true
        format_sql: true

logging.level:
  org.hibernate.SQL: debug
  # org.hibernate.type: trace

JPA 연결 설정, DB 동작 확인

<Member.java>

@Entity
@Getter @Setter
public class Member {
    @Id
    @GeneratedValue
    private Long id;

    private String username;

    protected Member(){}
    
    public Member(String username) {
        this.username = username;
    }
}

protected Member(){} JPA 에서 엔티티 생성할때, 프록시로 구현할 때도 있어서, protected 레벨까지는 빈 Constructor를 열어주어야함!!
덧. @NoArgsConstructor(access = AccessLevel.PROTECTED) 로 대체 가능

<MemberJpaRepository.java>

@Repository
@RequiredArgsConstructor
public class MemberJpaRepository {
    private final EntityManager em;

    public Member save(Member member){
        em.persist(member);
        return member;
    }

    public Member find(Long id){
        return em.find(Member.class, id);
    }
}

test code

class MemberJpaRepositoryTest {

    @Autowired MemberJpaRepository memberJpaRepository;
    @Test
    public void testMember() throws Exception {
        // given
        Member member = new Member("memberA");
        Member saveMember = memberJpaRepository.save(member);

        // when
        Member findMember = memberJpaRepository.find(saveMember.getId());
        // then
        assertThat(findMember.getId()).isEqualTo(member.getId());
        assertThat(findMember.getUsername()).isEqualTo(member.getUsername());
        assertThat(findMember).isEqualTo(member);
    }
}

<MemberRespository.java>

public interface MemberRepository extends JpaRepository<Member, Long> {
    // 이걸로 끝, interface 라는 점!!
}

test code

class MemberRepositoryTest {
    @Autowired MemberRepository memberRepository;
    
    @Test
    public void testMember() throws Exception {
        // given
        Member member = new Member("memberA");
        Member saveMember = memberRepository.save(member);

        // when
        Member findMember = memberRepository.findById(saveMember.getId()).get();
        // then
        assertThat(findMember.getId()).isEqualTo(member.getId());
        assertThat(findMember.getUsername()).isEqualTo(member.getUsername());
        assertThat(findMember).isEqualTo(member);
    }
}

memberRepository 내부에 메소드가 엄청 많다!! (save, findById 등등)
아무것도 해준게 없는데!!!

ctrl + p 자료형, 파라미터 알려주는!!
get() 을 쓸때 예외처리 해주는게 맞음. 지금은 그냥 편의상 하는 것!!

query 파라미터를 로그로 남기는 외부 라이브러리가 있음 (운영 시스템에서는 꼭 성능 테스트 ㄱ)
implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.5.7'

스프링부트 3.0 이상 버전부터는 추가 세팅이 필요함!!

도메인 모델

<Member.java>

@Entity
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(of = {"id", "username", "age"})
public class Member {
    @Id
    @GeneratedValue
    @Column(name="member_id")
    private Long id;

    private String username;

    private int age;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "team_id")
    private Team team;

    public Member(String username) {
        this.username = username;
    }
}

덧. JPA 에서 모든 @xToOne 관계는 FetchType.LAZY 로 설정해줘라!

<Team.java>

@Entity
@Getter @Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(of={"id", "name"})
public class Team {
    @Id @GeneratedValue
    @Column(name = "team_id")
    private Long id;

    private String name;

    @OneToMany(mappedBy = "team")
    private List<Member> member = new ArrayList<Member>();
}
profile
this too shall pass

0개의 댓글