@PersistenceContext private EntityManager em;
Jpa가 제공하는 표준 어노테이션 @PersistenceContext을 붙여주면 스프링이 엔티티매니저를 만들어 주입해준다.
public List findAll(){
return em.createQuery("select m from Member m ", Member.class)
.getResultList();
}
모든 멤버를 찾기 위해 em.createQuery라는 jpql을 작성해야 한다. jpql의 조회타입 "select m from Member m " , Member.class는 반환 타입
jpql과 sql의 차이점
sql은 테이블을 대상으로 쿼리를 하는데 jpql은 엔티티 객체를 대상으로 쿼리를 한다.
service 패키지를 만들고 MemberService 클래스 작성
클래스 위에 @Service 어노테이션을 붙여주어야 스프링 빈으로 자동 등록됨
영속성 컨텍스트에 키값과 value 값이 필요한데 PK이 값이 키 값이 된다.
JPA의 모든 데이터 변경이나 로직들은 가급적이면 트랜잭션 안에서 실행되어야 함
@Transactional이 있어야 한다.
클래스 레벨의 @Transactional을 쓰면 public 메서드들은 트랜잭션에 다 걸려간다.
클래스 레벨에서 쓰지 않고 각각 메서드 위에 쓰게 되면 쓰기 전용 메서드에서는 @Transactional을 해주고 읽기 전용 메서드에서는 @Transactional(readonly=true)를 해주어야 한다. readonly = true를 하게 되면 데이터 변경이 안된다. 클래스 레벨에 위치해 있는 것 보다 메서드 위에 위치해 있는 것이 더 높은 우선순위를 가진다.
@Autowired
private MemberRepository memberRepository;
스프링이 스프링 빈에 있는 memberRepository를 인잭션 해준다. 이 방식의 단점은 private 선언이라 접근할 수가 없다는 점 때문에 test코드를 작성할 때 불편하다. 해결책으로 setter 인잭션 방식을 사용 한다.
@Autowired
public void setMemberRepository(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
이 방식의 장점은 test 코드에서 내가 주입하고 싶은 가짜 memberRepositiory를 주입할 수 있다. 하지만 치명적은 단점으로 애플리케이션이 돌아가는 시점에 누군가 이 값을 바꿀 수 있다는 점이다. 그래서 생성자 주입 방식을 사용한다.
@Autowired
public MemberService(MemberRepository memberRepository){
this.memberRepository=memberRepository;
}
스프링이 생성자에서 인잭션을 해준다. 중간에 memberRepository 값을 바꿀 수는 없다. test 코드 작성시에 내가 직접 주입을 해야 하기 때문에 의존하고 있다는 점을 놓치지않을 수 있다.
하나의 생성자를 사용할 경우 @Autowired 어노테이션을 생략할 수 있다. 이제 필드는 변경할 일이 없기 때문에 final로 지정해주는게 좋다.
private final MemberRepository memberRepository;
Lombok의 @RequiredArgsConstructor 어노테이션을 사용하면 final이 있는 필드만 가지고 생성자를 만들어 주기 때문에 내가 직접 생성자를 적을 필요가 없어진다.
이 기능을 MemberRepository에서도 사용할 수 있다.
단축키 ctrl + shift + t
Genegrate 전략에서는 영속성에서 insert문이 나가지 않는다.
@Transactional은 기본적으로 트랜잭션을 커밋하지 않고 롤백을 해버리기 때문에
@Rollback(false)로 주면 됨 이러면 insert문이 나가는 것을 볼 수 있다.
@Rollback문을 쓰지 않는 rollback 상태에서 쿼리가 나가는걸 보고 싶다면 Entitymanager를 Autowired로 받아서 em.flush()
memory db 사용법
test 폴더에 resources 디렉토리를 만들고 디렉토리 안에 application.yml을 복사해서 넣어주면 main에 있는 yml은 무시되고 test폴더에 있는 yml이 실행된다. h2database.com에서 jdbc:h2:mem:test를 복사해 yml url을 바꿔주면 된다.