jdbc -> jdbcTemplate -> JPA
이런순으로 더 간결하고 쉽게 코드를 짤 수있게끔 발전하는것 같다.
jdbc 에서 jdbcTemplate으로 교체했을때는 반복적인 코드가 확 줄었지만 sql문은 개발자가 직접 작성해야했다.
그런데
jpa라는 기술을 사용하면 그런 sql쿼리도 jpa가 자동으로 처리해준다. 그럼으로써 개발 생산성을 크게 증가 시킬수있다.
jpa를 사용하면 sql과 데이터보다는 객체중심으로 생각할 수 있다.
jpa 라이브러리 추가
기존에 쓰던 jdbc는 jpa안에 들어있으므로 없어도된다.
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' // jpa를 사용하기 위해 추가
// implementation 'org.springframework.boot:spring-boot-starter-jdbc'//jdbc를 사용하려고 -> jpa쓸때는 jap안에 들어있으므로 없어도됨
스프링부트에 jpa 설정 추가
resources/application.properties
#h2 데이터베이스 관련 정보들
spring.datasource.url=jdbc:h2:tcp://localhost/~/test
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
#jpa가 생성하는 SQL를 출력하는 기능킨다.
spring.jpa.show-sql=true
#jpa는 테이블을 자동으로 생성하는 기능을 제공하는데 none으로 해줘서 해당 기능을 끈다.
#create를 사용하면 엔티티 정보를 바탕으로 테이블도 직접 생성해준다.
spring.jpa.hibernate.ddl-auto=none
jpa는 인터페이스이고 구현체로 hibernate가 있다.
우리는 hibernate를 사용하면된다.
jpa는
ORM( Object-Relational Mapping의 약자로 객체(Object)와 관계형 데이터베이스(Relational Database)의 데이터를 매핑(Mapping)해주는 것을 의미한다.)
객체와 데이터베이스의 데이터를 어떻게 매핑하는가? -> 어노테이션을 이용한다.
@Entity
https://gmlwjd9405.github.io/2019/08/11/entity-mapping.html
매핑하기위해 수정된 Member.java
@Entity //jpa가 관리하는 엔티티라는 뜻
//아래는 lombok관련 어노테이션
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
public class Member {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)//@Id로 pk를 매핑해준다, db에 멤버이름만 넣어도 키값이 자동으로 생성되는것을 identity 전략이라고한다.
//멤버에는 그런 전략을 사용했으므로 @GeneratedValue로 해당 전략에 대해 적어준다.
private Long id;
// @Column(name = "username") // 만약에 db상에서 컬럼이름이 username이라면 @Column 어노테이션을 이용해서 매핑해준다, 컬렴명과 변수명이 같다면 필요없다.
private String name;
}
jpaMemberRepository.java
EntityManager
private final EntityManager em; //jpa는 엔티티매니저라는것으로 모든게 동작을 한다.
//jpa관련 라이브러리를 받으면 spring boot가 자동으로 현재 데이터베이스와 연결까지 시켜줘서 엔티티매니저를 생성해준다.
//(application.properties에 적은 데이터베이스정보를 이용하여)
//그래서 스프링부트가 만들어 놓은것을 injection(주입) 받기만 하면된다.
public jpaMemberRepository(EntityManager em) {
this.em = em;
}
Save 구현
@Override
public Member save(Member member) {
em.persist(member); //persist가 고집하다 지속하다도 있지만 영구저장하다는 느낌도 있다고한다.
return member;
}
이렇게만해도 jpa가 insert query를 만들어서 알아서 집어넣고, 데이터 넣을시 자동 생성되는 id까지
멤버에 넣어서 리턴해준다.
findById 구현
@Override
public Optional<Member> findById(Long id) {
Member member = em.find(Member.class, id);//조회할 타입과 식별자를 넘겨주면 조회가 된다.
return Optional.ofNullable(member);
}
id가 pk(primaryKey)라서 find로 간단하게 처리가 가능
pk기반이 아닌 나머지들은 jpql을 작성해서 처리해줘야한다.
findAll 구현
@Override
public List<Member> findAll() {
//jpql이라는 쿼리언어를 사용한다.
//보통 테이블을 대상으로 쿼리를 날리는데, 여기서는 객체를 대상으로 쿼리를 날린다.(그게 sql로 번역이됨)
//Member엔티티를 대상으로 쿼리를 날리는데 멤버 m 엔티티 전체를 select한다 (sql문의 *과 같은거)
//jdbc와 달리 jpa에서는 매핑없고 알아서 매핑도 됨
return em.createQuery("select m from Member m", Member.class)
.getResultList();
}
findByName 구현
@Override
public Optional<Member> findByName(String name) {
List<Member> result = em.createQuery("select m from Member m where m.name= :name",
Member.class) //findByname은 이런식으로.
.setParameter("name", name) //파라미터 전달은 여기서
.getResultList();
return result.stream().findAny();
}
jpa 쓸때 주의해야할점
항상 트랜잭션이 있어야한다.
서비스 계층에 @Transactional 처리를 해준다.
데이터를 저장하거나 변경할때는 항상 트랜잭션 처리가 되어있어야한다.
클래스네임위에 해서 전체를 트랜잭션 처리를 하던지
클래스네임위에다 하지않고 메소드마다 트랜잭션처리를 하던지 고르면 될듯하다. (전체를 해놓는게 편할듯)
Test
application.properties에서
#jpa가 생성하는 SQL를 출력하는 기능킨다.
spring.jpa.show-sql=true
이걸 true로 했기에
hibernate가 어떤 쿼리를 날렸는지 확인할 수 있다.
첫번째 select는 중복회원체크(validation 처리) 때문에 날라간거고
두번쨰의 insert에서 저장시키는걸 확인할 수 있다.
'인프런 > 스프링 입문' 카테고리의 다른 글
끝) AOP (0) | 2022.11.30 |
---|---|
12) 스프링 데이터 JPA (0) | 2022.11.28 |
10) 스프링 JdbcTemplate,RowMapper,lambda (0) | 2022.11.28 |
9)순수 JDBC, DI(dependency injection)과 다형성의 장점 , 스프링통합테스트 (0) | 2022.11.27 |
8)스프링 DB 접근기술(H2 데이터베이스 설치), 테이블생성,데이터생성,DDL SQL 관리 (0) | 2022.11.27 |
댓글