ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TIL(22일차)(2021.11.12)
    TIL(Today I Learned) 2021. 11. 12. 14:22

    Spring Framework의 장점📌

    -> 객체지향 설계가 가능
    -> 인터페이스를 지정하고 구현체를 사용자 임의대로 바꿀 수 있음.(DI 덕분에)
    -> 즉, memberService는 memberRepository를 의존하고 있고, 구현체로 memoryMemberReposotory와 , jdbcMemberRepository가 있다고 가정했을 때
    -> 사용자 임의대로 memoryMemberRepository를 삭제하고 jdbcMemberRepository로 구현할 수 있다.
    -> 이는, SOLID에서 O(OCP, Open-Closed Principle) 즉, 개방-폐쇄의 원칙을 만족시킨다.
    -> 확장에는 열려있고, 수정에는 닫혀있다. 왜냐하면 기존 코드는 손대지 않고 새로운 jdbcMemberRepository를 새로 구현한뒤에 추가할 때
    -> memberRepository 인터페이스 구현체를 살짝만 수정해도 되기 때문이다.

    JDBC(Java DataBase Connectivity) 📌

    -> java에서 데이터베이스와 연결하기 위한 드라이버

        //build.gradle
        implementation 'org.springframework.boot:spring-boot-starter-jdbc'
        runtimeOnly 'com.h2database:h2'

    -> DB와 연결하기위해 dependencies에 추가

    //HelloSpringApplicationTests
    spring.datasource.url=jdbc:h2:tcp://localhost/~/test
    spring.datasource.driver-class-name=org.h2.Driver
    spring.datasource.username=sa
    

    -> 경로 지정
    -> buildGradle에 가서 Load Gradle Changes 클릭.

    preparedStatement 📌

    -> 객체를 캐시에 담아 재사용한다.
    -> 반복적으로 사용한다면 statement에 비해 성능이 좋다.
    -> secure coding에 나와있듯이 statement보다 보안성이 좋다.
    -> statement는 sql 쿼리문을 작성할 때, 변수값을 사용하지만
    -> preparedStatement는 변수값 대신 ?를 사용한다.

    statement

       String sql = "INSERT into member(name) VALUES('"name"')";

    preparedStatement

      String sql = "INSERT into member(name) VALUES(?)";

    e.printStackTrace(); 📌

    -> 에러의 발생근원지를 찾아서 단계별로 에러 출력한다.
    -> 상세한 에러 내역을 확인할 수 있어서 유용하다.
    -> log4에서는 사용할 수 없다.
    -> 때문에 log.error("error:",e);로 선언해줘야한다.

    e.printStackTrace(); 예시

    try{
        if(conn !== null){
            close(conn);
        }
        catch(SQLException e) {
            e.printStackTrace();
        }
    }

    log4에서 e.printStackTrace(); 예시

    try {
        //..
    }
    catch(Exception e){
        StackTraceElement[] elem = e.getStackTrace();
        for(int i = 0; i<elem.length; i++)
            logger.error(elem[i]);
    }

    spring integration Test 📌

    -> spring + database + test를 한변에 통합해서 테스트
    -> 단점 : 속도가 느리다.
    -> 더 좋은 테스트 방식은 더 잘게 쪼개서 단위테스트를 하는것이 바람직함.
    -> Configuration에 선언된 spring bean으로 구현한 spring container에 있는 객체들을 가져다가 쓴다.

    @SpringBootTest Annotation

    -> 스프링 컨테이너와 테스트를 함께 실행한다.

    @Transactional Annotation

    -> 테스트 시작 전에 트랜잭션을 시작하고(각각의 메소드마다), 테스트 완료 후에 항상 롤백한다.
    -> 이렇게하면 DB에 데이터가 남지 않으므로, 다음 테스트에 영향을 주지 않는다.
    -> AfterEach Annotation 구현과 비슷한 기능이다.
    -> 트랜잭션을 통해 회원 중복 테스트 , 반복 테스트, 회원 join 테스트 등을 수행할 수 있다.
    -> 트랜잭션이 서비스에 선언되면 롤백하지 않고 정상적으로 돌고, 테스트에 붙을 때만 롤백한다.

    JdbcTemplate와 Mybatis 라이브러리 📌

    -> JDBC API에서 사용되는(아주 오래된 방식의 코드) 반복 코드를 대부분 제거해준다.
    -> 하지만 SQL은 직접 작성해야한다.
    -> injection을 받을 수 없다. 즉, DI가 불가능하다.
    -> DataSource(DB와 연결할 때 선언해주는..)를 통해 injection 문제를 해결
    -> 손쉽게 DB와 연동할 수 있도록 구현되어 있다.

    JdbcTemplate 선언

        //JdbcTemplateMemberRepository
        private final JdbcTemplate jdbcTemplate;
    
        public JdbcTemplateMemberRepository(DataSource dataSource) {
            jdbcTemplate = new JdbcTemplate(dataSource);
        }

    스프링 빈 수정

    //SpringConfig
    @Bean
        public MemberRepository memberRepository(){
    //        return new MemoryMemberRepository();
        return new JdbcTemplateMemberRepository(dataSource);
        }

    -> return new JdbcTemplateMemberRepository(dataSource); 추가

    DataSource

    private final DataSource dataSource;
     public SpringConfig(DataSource dataSource) {
     this.dataSource = dataSource;
     }

    -> DataSource를 통해 DB connection을 획득한다.
    -> 스프링부트는 데이터베이스 커넥션 정보를 바탕으로 DataSource를 생성하고
    -> 스프링 빈으로 만들어 DI를 받을 수 있게된다.

    stream() 📌

    -> 람다에서 사용하는 메서드.
    -> '데이터의 흐름'
    -> 배열 또는 컬렉션 인스턴스를 함수형으로 처리 가능
    -> 람다를 사용하여 코드의 양을 줄이고 간결하게 표현할 수 있다.
    -> 병렬처리 가능(multi-threading)
    -> List로 반환할 수 있다.

    RowMapper 📌

    -> 원하는 형태의 결과값을 반환할 수 있다.
    -> SELECT로 나온 여러개의 값을 반환할 수 있을 뿐만 아니라
    -> 사용자가 원하는 형태로도 바꿀 수 있다.
    -> 람다식으로 코드를 간결하게 만들 수 있다.
    -> RowMapper는 과거 순수 JDBC에서 ResultSet으로 값을 받고
    -> 객체에 담아서 반환하는 과정을
    -> 간결하고 짧게 구현할 수 있게 해준다.
    -> 즉, 쿼리날려준걸 맵핑해준다.

        //JdbcTemplateMemberRepository
        private RowMapper<Member> memberRowMapper(){
            return (rs, rowNum) -> {
                Member member = new Member();
                member.setId(rs.getLong("id"));
                member.setName(rs.getString("name"));
                return member;
            };
        }

    JPA(Java Persistence API)📌

    -> JdbcTemplate도 코드가 짧고 간결해졌지만, SQL문 쿼리를 직접 작성해야한다는 단점이있다.
    -> 이를 JPA가 해결해준다.
    -> JPA는 기존의 반복 코드도 실행해준다.
    -> JPA를 사용하면 SQL과 데이터 중심의 설계에서, 객체 중심의 설계로 패러다임을 전환할 수 있다.
    -> JPA를 사용하면 개발 생산성을 크게 향상시킬 수 있다.
    -> 객체랑, ORM을 이용하는 인터페이스이다.(ORM: Object Relational Mapping)

        //build.gradle
        implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    

    -> dependencies에 추가
    -> 입력후 Load Gradle Changes 클릭(라이브러리 다운로드)

        //application.properties
        spring.jpa.show-sql=true //jpa에서 sql문 확인 가능하게 해줌
        spring.jpa.hibernate.ddl-auto=none //none이 아닌 create로 선언하면 DB column 객체를 보고 자기가 테이블을 자동으로 생성함.
        //Member.java
        @Id @GeneratedValue(strategy = GenerationType.IDENTITY)

    -> IDENTITY는 컬럼의 ID값을 자동으로 생성하고 증가 시키는것을 의미한다.
    -> 본 구현에서는 자동으로 ID가 상승하도록(++sequence) or (h2database 성질) 설정해주었기 때문에 IDENTITY를 선언해준다.
    -> DB가 알아서 생성해주는것을 IDENTITY라고 한다.

        //JpaMemberRepository
     private final EntityManager em;
    
        public JpaMemberRepository(EntityManager em) {
            this.em = em;
        }

    -> 위에서 build.gradle에 선언한
    -> implementation 'org.springframework.boot:spring-boot-starter-data-jpa'가 자동으로
    -> EntityManager를 선언할 수 있게 해줌.
    -> EntityManager를 통해 JPA를 컨트롤함
    -> application.properties와 DB Connection에 들어있는 정보랑 섞어서 자동으로 EntityManager를 만들어준다.
    -> EntityManager를 통해 DB와의 통신을 내부적으로 처리한다.
    -> 결론 JPA를 사용하려면 EntityManager를 주입받아야한다.

    @Transaction 
    @Commit

    -> 트랜잭션 어노테이션을 사용할 때, 모든 값을 롤백해주는데,
    -> 이때, 롤백하기 싫다면, Commit 어노테이션을 사용하면 값이 정상적으로 저장된다.

        @Override
        public Member save(Member member) {
            em.persist(member);
            return member;
        }

    -> jpa em을 이용한 선언 방식
    -> persistence : 영속적
    -> 즉, 영속적으로 save한다.라는 의미

        //JpaMemberRepository
        @Override
        public List<Member> findAll() {
            return em.createQuery("select m from Member m", Member.class)
                    .getResultList();
        }

    -> JPQL
    -> 객체를 대상으로 쿼리를 날림

    @Transactional
    public class MemberService {

    -> JPA 사용할 때는 @Transaction을 추가해줘야한다(JPA는 트랜잭션 안에서 실행되어야함).

        //springConfig.java
        private EntityManager em;
    
        @Autowired
        public SpringConfig(EntityManager em) {
            this.em = em;
        }
    
        return new JpaMemberRepository(em);
    

    -> spring환경을 JPA로 돌아가도록 설정.
    -> EntityManager를 선언해서 DI

    'TIL(Today I Learned)' 카테고리의 다른 글

    TIL(24일차)(2021.11.14)  (0) 2021.11.14
    TIL(23일차)(2021.11.13)  (0) 2021.11.13
    TIL 21일차(11.11)  (0) 2021.11.11
    TIL 20일차 (2021.11.10)  (0) 2021.11.10
    TIL 19일차(2021.11.09), 단축키 TIP 모음, intellij create git  (0) 2021.11.09
Designed by Tistory.