-
[Spring] JPA 설정 및 사용Spring 2021. 10. 11. 15:53
jpa를 쓰기에 앞서 몇가지 설정이 필요하다.
build.gradle 파일의 디펜던시에서 첫번째줄을 삽입해줘야한다.
spring boot starter data jpa는 jdbc관련 라이브러리를 포함한다.
resources/application.properties 파일에도 수정할 것이 있다.
spring.jpa.show-sql=true spring.jpa.hibernate.ddl-auto=none
이 두 줄을 넣어줘야 하는데, 첫째 줄의 의미는 jpa로 날린걸 sql로 볼 수 있게 해준다.
둘째 줄은 원래 jpa를 쓰면 객체를 보고 테이블까지 만들어 버린다.
그래서 이미 만들어놨거나 그 기능이 필요없는 경우 none으로 끄고 시작하면 된다.
JPA를 통한 모든 데이터 변경은 트랜잭션 안에서 실행해야 한다.
때문에 서비스 클래스에 @Transactional을 붙여 런타임에러가 나면 롤백을, 정상 종료되면 커밋을 할 수 있도록 한다.
JPA 사용을 위한 매핑작업
jpa는 관계형 데이터베이스와 객체를 매핑하기 위해 몇가지 작업이 필요하다.
import javax.persistence.*; @Entity public class Member { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; // @Column(name = "username") private String name; }
맵핑을 위해 @Entitiy 어노테이션을 해줘야한다.
각 멤버변수마다 테이블에서 어떤 칼럼인지를 맵핑해줘야한다.
특정 멤버변수가 pk값일 경우 @id를 써 설정을 해준다.
또한 pk값이 자동으로 마지막 pk값에서 +1을 해주는 식이라면
@GeneratedValue(strategy = GenerationType.IDENTITY)로 지정해준다.
JPA를 이용한 레퍼지토리 클래스 만들기
package hello.hellospring.repository; import hello.hellospring.domain.Member; import org.springframework.expression.spel.ast.OpInc; import javax.persistence.EntityManager; import java.util.List; import java.util.Optional; public class JpaMemberRepository implements MemberRepository{ private final EntityManager em; public JpaMemberRepository(EntityManager em) { this.em = em; } @Override public Member save(Member member) { em.persist(member); return member; } @Override public Optional<Member> findById(long id) { Member member = em.find(Member.class, id); return Optional.ofNullable(member); } @Override public Optional<Member> findByName(String name) { List<Member> result = em.createQuery("select m from Member m where m.name = :name", Member.class) .setParameter("name", name) .getResultList(); return result.stream().findAny(); } @Override public List<Member> findAll() { List<Member> result = em.createQuery("select m from Member m", Member.class) .getResultList(); return result; } }
JPA는 entity manager로 모든 동작을 한다.
그래서 스프링 부트는 jpa 라이브러리를 받으면 자동으로 entity manager를 자동으로 생성해준다.
때문에 개발자는 인젝션만 해주면 된다.
Insert
@Override public Member save(Member member) { em.persist(member); return member; }
entity manager의 persist함수를 써 매개변수로 그대로 넣어주기만 하면 된다.
Search
@Override public Optional<Member> findById(long id) { Member member = em.find(Member.class, id); return Optional.ofNullable(member); } @Override public Optional<Member> findByName(String name) { List<Member> result = em.createQuery("select m from Member m where m.name = :name", Member.class) .setParameter("name", name) .getResultList(); return result.stream().findAny(); } @Override public List<Member> findAll() { List<Member> result = em.createQuery("select m from Member m", Member.class) .getResultList(); return result; }
search는 상황마다 방법이 다르다.
PK로 찾기
pk값으로 값을 찾으면 간단하다.
@Override public Optional<Member> findById(long id) { Member member = em.find(Member.class, id); return Optional.ofNullable(member); }
멤버클래스의 정보를 넣고, 찾는 키값을 넣는 find함수를 쓰면 리턴을 클래스형식으로 해준다.
pk값이 아닌 column으로 찾기
@Override public Optional<Member> findByName(String name) { List<Member> result = em.createQuery("select m from Member m where m.name = :name", Member.class) .setParameter("name", name) .getResultList(); return result.stream().findAny(); } @Override public List<Member> findAll() { List<Member> result = em.createQuery("select m from Member m", Member.class) .getResultList(); return result; }
createQuery함수를 써 쿼리를 쓰긴해야한다. 하지만 그냥 쿼리는 아니고 jpql이라는 객체지향쿼리를 써야한다.
select *을 하는 식의 쿼리가 아닌 Member entity 자체를 조회하는 식이라고 보면 된다.
그렇게 조회해서 리스트로 뽑아낼 경우 getResultList()함수를 써 그대로 리턴을 하면 된다.
그리고 리스트로 전부 뽑아내는게 아닌 하나의 정보값을 가져오는 함수라면
where을 써 Member entity의 name과 비교할 변수를 쓰고, setParameter를 통해 해당 변수에 값을 할당해서 다시 값을 받아오면 된다.
SpringConfig 설정
@Configuration public class SpringConfig { @PersistenceContext private EntityManager em; @Autowired public SpringConfig(EntityManager em) { this.em = em; } @Bean public MemberService memberService() { return new MemberService(memoryRepository()); } @Bean public MemberRepository memoryRepository() { return new JpaMemberRepository(em); }
entity manager를 받아와 할당해주고, 그걸 다시 레포지토리 클래스로 보내주면 된다.
'Spring' 카테고리의 다른 글
[Spring] 조회한 빈이 모두 필요할 때 방법 (0) 2021.11.04 [Spring] 스프링 빈의 자동, 수동의 올바른 실무 운영 기준 (0) 2021.11.04 [Spring] Form에 쏴준 데이터 받고 다시 출력하기 (0) 2021.10.06 [Spring] 스프링 빈과 의존관계 (0) 2021.10.05 [Spring] Test 코드 기초작성 (0) 2021.10.04