Spring_20_ Spring Boot MVC2 model
📌 MVC2 흐름
📌 DispatcherServlet
- Web browser에서 어떠한 요청이 들어오면 그걸 가장 먼저 받아서 요청값에 알맞는 Controller로 값을 보내주는 것인데
그 요청 정보에 대해 HandlerMappinng에 위임하여 처리할 Handler(Controller)을 찾습니다.
📌 @Controller
- 받은 요청값을 통하여 비즈니스 로직을 수행하고 받은 결과값을 view에 전달하는 역할을 한다.
- 자동으로 Component에 담겨진다.
1. 사용 방법
- controller는 로직을 수행하기 위해 Service를 찾게된다.
- 서비스를 찾는 방법은 Controller 클래스에 Service의 객체가 호출되어야 한다.
- Component에 Service가 담겨져 있으면 어노테이션으로 그 객체를 불러올 수 있다.
- 불러오는 방법은 크게 세가지 이다.
- 1번은 스프링을 사용하지 않은 전통적인 방식이다.
- 2번은 @Autowired를 사용하여 Component에 담겨진 것들의 객체정보를 가져온다.
단, 그림과 같이 기본 생성자가 있어야 한다.(서비스가 private여서 반드시 생성자를 통하여 값을 가져올 수 있다.)
- 3번은 @RequiredArgsConstructor 사용하여 생성자 생성없이도 값을 가져올 수 있다.
단, 서비스가 private 이라는 가정하에 @RequiredArgsConstructor 어노테이션을 직역해보면 생성자가 요구되어지는 것을
찾아주는 것이다.
2. 사용 추세
- 3번의 @RequiredArgsConstructor방식을 보통 사용한다.
📌 @Service(Service)
- 서비스도 위 컨트롤러와 동일하게 세가지 방식으로 선언이 가능하다.
- Service는 유지보수를 위하여 인터페이스를 활용하는 것이 좋다.
1. JDBC 방식
2. Mybatis 방식
3. JPA 방식
- JPA는 트랜젝션 단위로 작업되어 반드시 Service 또는 Dao에 @Transactional을 걸어줘야 한다.
- 참고로 Mybatis는 @Transactional을 사용할수 없어서 별도로
DAO에 트랜잭션을 걸어줘야한다. 하지만 @Transactional을 Mybatis
에서도 사용하려면 별도로 설정이 필요하다.
- 보통 Service에 많이 걸어준다.
트랜젝션이란?
- 데이터베이스 관리 시스템 또는 유사한 시스템에서 상호작용의 단위이다. 여기서 유사한 시스템이란 트랜잭션이 성공과 실패가 분명하고 상호 독립적이며, 일관되고 믿을 수 있는 시스템을 의미한다. 데이터의 정합성을 보장하기 위해 고안된 방법이다.
즉, 예를들어서 DAO에서 insert하는 문이 3개라고 가정하자 근데 3개 중에 2개만 insert가 먼저되고 나머지 한개는 insert가 안되어 오류가 되면 다시 실행하면 또 3개 중에 2개만 insert 될 것이다. 이렇게 되면 만일, PK가 3개인데 2개만 값이 들어가고 1개는 안들어가면 데이터가 꼬이게 된다. 이렇기 때문에 트랜젝션 단위로 실행하는 것이다.
특정 실행단위에서 오류 발생시 전체 실행 내용을 롤백해주는 기능
- 서비스가 DAO를 호출하여 DAO가 메소드를 실행하는데 insert가 있었지만 DAO가 끝났다고 하더라도 실제로 isnert 되지 않고 다시 서비스로 넘어와서 service에 실행될것이 남았으면 다 실행하고 마지막에 return되기 직전에 commit된다..
📌 @Repository(DAO)
- repository 패키지는 DB에 접근하는 모든 코드가 모여있다고 생각하시면 된다.
- DAO는 DB와 연결하기 위해 DataSorce, SqlSession, EntityManager를 찾는다.
- 찾는 방법은 컨트롤러와 동일하다.
- DAO에 @Repository를 붙여준다.
- 참고
1. JDBC DB 연결방식
- DataSource 객체를 이용하여 DB와 연결한다.
- 단순히 메소드안에 쿼리를 직접 작성하여 CRUD를 진행한다.
2. JPA DB 연결방식
- EntityManager 객체를 이용하여 DB와 연결한다.
- JPA는 EntityManager를 사용하기 때문에 sql쿼리를 자동으로 짜준다.
- EntityManager 명령어 참고
참고사항 : JPA 특징
- 영속성을 가진다 단, persist를 해야지 해당 객체가 영속성을 가진다.
예시
3. Mybatis DB 연결방식
- sqlSession 객체를 이용하여 DB와 연결한다.
- 명령어
- mapper에 쿼리를 담아놓고 쿼리를 불러와서 사용한다.
참고사항 : Mybatis 트랜잭션
- 트랜잭션을 하는 이유는 예를들어서 DAO에서 insert가 두개 있었다 그런데 PK가 같아서 첫번째것만 insert가되고 두번째거는 안되서 DB가 꼬이게 된다.
SqlSession은 한 실행문마다 자동으로 커밋되기 때문이다. 하지만 이것을 방지하기 위해서 트랜잭션 단위로 만드는 것이다.
그래서 JPA에서 @Transactional을 서비스에 걸어주었던 것이다. 다른것들이 실행되더라도 서비스에서 커밋이 되기 위함이다. 하지만 Mybatis에서는 @Transactional을 사용할수는 없고 별도로 트랜잭션 객체를 선언해줘야 한다.
(try 안에를 트랜잭션 단위로 만드는 것이다.)
📌 DTO 정리
1. JDBC 방식
2. Mybatis 방식
3. JPA 방식
- @Entity 어노테이션을 DTO에 선언해줘야 한다.
- 그래야지 EntityManager가 쿼리를 수행할때 @Entity로 지정된것들을 가지고 쿼리를 생성한다.
- 그리고 만일 DB에 해당 DTO의 테이블이 없으면 알아서 @Entity로 지정된 DTO 테이블을 생성해준다.
- 단, 조건은 아래와 같다.
- application.yml(application.properties)에 create로 되어 있으면 알아서 테이블 생성
※ 하지만, create로 해놓으면 전체 삭제하고 다시 생성하기 때문에 처음 프로젝트 만들때만 create로 하고
나중에는 update로 해야지 기존 데이터가 날아가지 않는다.
4. 참고사항(@Data)
- lombok을 사용하면 @Data를 사용할 수 있다.
- DTO를 사용하게 되면 Getter와 Setter를 변수마다 정의해야 하지만, lombok을 사용하면 @Getter, @Setter 이렇게 어노테이션 하나만 지정해주면 사용가능하다.
- lombok중에서 @Data 어노테이션은 많은 기능을 담고 있다.
- 실질적으로 Controller, Service, Dao 에서 생성자를 위해서 @RequiredArgsConstructor가 필요 하지만, @Data를 사용해도된다.
- 하지만, @Data는 많은 기능이 함축되어 있어서 불필요한 메모리까지 잡아먹어서 필요한것만 어노테이션을 선언하는 경우도 많다.