[22강]

2023. 2. 6. 00:43Spring 강의/section6

JPA

  • JPA는 기존의 반복 코드는 물론이고, 기본적인 SQL도 JPA가 직접 만들어서 실행해준다.
  • JPA를 사용하면, SQL과 데이터 중심의 설계에서 객체 중심의 설계로 패러다임을 전환을 할 수 있다.
  • JPA를 사용하면 개발 생산성을 크게 높일 수 있다.

 

Jdbc -> JdbcTemplate

: 반복적인 코드가 줄었다. 그러나 sql은 결국 작성을 해야했는데 jpa를 사용하면 sql도 jpa가 자동으로 처리해준다.

 

먼저 build.gradle에 라이브러리를 추가해줘야 한다.

jdbc는 주석처리해주고 data-jpa를 추가해준다.

그리고 application.properties에 몇 가지 설정을 추가한다.

spring.jpa.show-sql=true 
: jpa가 날리는 sql을 볼 수 있다.

spring.jpa.hibernate.ddl-auto=none 
: jpa를 사용하면 객체를 보고 테이블도 만들어줌
  우리는 이미 테이블이 있고 그 테이블을 쓸 거니까 자동으로 테이블 만들어주는 기능을 끄고 시작한다.

 

JPA라는 것은 인터페이스이고, 구현체로 Hibernate, eclipse 등이 있다.

JPA는 객체와 ORM이라는 기술이다.(Object Relational Mapping)

 

JPA를 쓰려면 @Entity라는 것으로 mapping을 해야한다.

  • @Entity : jpa가 관리하는 entity가 된다.
  • @Id : pk로 설정할 컬럼에 단다.
  • @GeneratedValue(strategy = GenerationType.IDENTITY) : insert할 때 값을 세팅하지 않아도 자동으로 값을 준다.
  • @Column(name = " ") : db에 있는 해당 컬럼명과 mapping 해준다.

repository - JpaMemberRepository 클래스를 만든다.

EntityManager를 생성해준다.

JPA는 EntityManager라는 것으로 모든 것을 동작시킨다.

build.gradle에서 data-jpa를 받으면 스프링부트가 application.properties의 정보와 DBConnection 정보들을 합쳐서 EntityManager를 만들어준다.

우리는 인젝션 받아서 사용하면 되는 것.

 

JPA를 쓰려면 EntityManager를 주입받자!

 

이제 기능들을 jpa로 구현해보자.

1. save() 

em.persist(member)

: member라는 객체를 db에 저장한다.(엄밀히 말하면 영속성 컨텍스트에 저장하는 것)

: jpa가 insert 쿼리 만들어서 db에 집어넣고 member에다가 setId까지 해준다.

 

2. findById - pk이 인경우

em.find(조회할 타입, pk)

조회이므로 결과가 null일 수도 있다 -> Optional.ofNullable(member)

 

3. findByName - pk가 아닌 경우

jpql이라는 객체지향 쿼리 언어를 사용해야 한다.

sql과 jpql의 차이 

sql : 테이블 대상으로 쿼리를 날린다.

jpql : 객체(Entity)를 대상으로 쿼리를 날린다.

 

 

4. findAll()

select member.id 이렇게 말고 객체 자체를 select 한다. 

 

JdbcTemplateMemberRepository.class  전체코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package hello.hellospring2.repository;
 
import hello.hellospring2.domain.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
 
import javax.sql.DataSource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
 
public class JdbcTemplateMemberRepository implements MemberRepository{
 
    private final JdbcTemplate jdbcTemplate;
 
    @Autowired
    public JdbcTemplateMemberRepository(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }
 
    @Override
    public Member save(Member member) {
        SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(jdbcTemplate);
        jdbcInsert.withTableName("member").usingGeneratedKeyColumns("id");
        Map<String, Object> parameters = new HashMap<>();
        parameters.put("name", member.getName());
        Number key = jdbcInsert.executeAndReturnKey(new
                MapSqlParameterSource(parameters));
        member.setId(key.longValue());
        return member;
    }
 
    @Override
    public Optional<Member> findById(Long id) {
        List<Member> result = jdbcTemplate.query("select * from member where id =?",memberRowMapper(), id);
        //query() 메서드는 sql 파라미터로 전달받은 쿼리를 실행하고 memberRowMapper를 이용해서 ResultSet의 결과를 자바 객체로 변환한다.
        return result.stream().findAny();
    }
 
    @Override
    public Optional<Member> findByName(String name) {
        List<Member> result = jdbcTemplate.query("select * from member where name =?",memberRowMapper(), name);
        return result.stream().findAny();
    }
 
    @Override
    public List<Member> findAll() {
        return jdbcTemplate.query("select * from member",memberRowMapper());
    }
 
    private RowMapper<Member> memberRowMapper(){
        return new RowMapper<Member>() {
            @Override
            public Member mapRow(ResultSet rs, int rowNum) throws SQLException {
 
                Member member = new Member();
                member.setId(rs.getLong("id"));
                member.setName(rs.getString("name"));
                return member;
            }
        };
    }
}
 
cs

 

MemberService.class에 @Transactional을 달아준다.

JPA를 쓰려면 꼭 필요한 어노테이션이다.

데이터를 저장하고 변경할 때 필요하다.

 

 

실행시키려면 SpringConfig에서 바꿔끼자.

통합 테스트를 실행해본다.

select와 insert가 이루어지고 있다.

'Spring 강의 > section6' 카테고리의 다른 글

[23강]  (0) 2023.02.06
[21강]  (0) 2023.02.05
[20강]  (0) 2023.02.05
[19강]  (0) 2023.02.05
[18강]  (0) 2023.02.05