한계를 넘어 마법 같은 기술
스프링 부트 스타터 : 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
<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>();
}