* 68. Spring IOC 컨테이너를 이용해서 페이지 컨트롤러 객체분리
기존 DispacherServlet 에서 Map 객체를 통해 맵핑해주었음.
Spring IOC를 도입하여 DispacherServlet 에서 IOC container를 사용하며,
Component를 통해서 각 Controller를 매칭
* 69. Mybatis + Spring IOC 컨테이너
* Mybatis가 DAO 구현체를 자동생성하는 원리
JSP처럼 소스파일을 만들고 컴파일 하는 것이 아니라,
프록시 클래스를 통해서 인터페이스 구현체를 만들어서
메소드를 호출하여 작업을 진행한다.
구현체가 아니라 실제 작업객체를 생성해서 파라미터 값으로 입력받아
프록시를 실행한다는 것이다. 이것은 Mybatis의 기능이다.
요약:
인터페이스 정의:
개발자는 Mapper 인터페이스를 정의합니다.
이 인터페이스에는 데이터베이스와 상호 작용할 메소드가 선언됩니다.
프록시 객체 생성:
MyBatis는 실행 시에 Mapper 인터페이스에 대한 프록시 객체를 동적으로 생성합니다.
이 프록시 객체는 인터페이스 메소드 호출을 가로채서 실제 SQL 쿼리를 실행하는 역할을 합니다.
SQL 실행:
프록시 객체는 메소드 호출을 가로채면 해당 메소드에 대응하는 SQL 쿼리를 실행하고, 결과를 반환합니다.
실제 작업 객체 생성:
필요한 경우, MyBatis는 SQL 실행에 필요한 파라미터 값을 사용하여
실제 작업 객체를 생성하고 메소드에 전달합니다.
이 방식을 통해 MyBatis는 개발자가 직접 DAO 구현체를 작성하지 않고도
SQL 쿼리와의 상호 작용을 추상화하고 효과적으로 처리할 수 있도록 합니다.
Dao 구현체를 한번 출력해보자,
jdk.proxy 에서 MemberDao 구현체와 BoardDao 구현체를 확인할 수 있다.
memberaddController 를
MemberService,
DefaultMemberService를 통해서 구조 변경
@AutoWired 를 통해서 생성자를 없앨 수 있다.
memberService.add(m) 이라는 호출자를 통해서
메서드를 호출해서 프록시를 자동생성했다.
`boardService.add(board)` 메서드를 호출함으로써 MyBatis는 내부적으로 필요한 SQL 쿼리를 실행하기 위해
프록시 객체를 자동으로 생성하고 사용합니다.
이렇게 하면 개발자는 SQL 쿼리 작성과 관리의 번거로움을 덜고,
편리하게 데이터베이스와 상호 작용할 수 있습니다.
이 메서드는 트랜잭션을 관리하고 데이터베이스 작업을 수행하는 역할도 수행합니다.
* DefaultBoardService 반복시행 코드 리팩토링
스프링 공식문서 Transaction Management
https://docs.spring.io/spring-framework/reference/data-access/transaction/programmatic.html
<1번>
<2번>
<3번>
<4번>
우리가 직접 구현하여 만든 TransactionTemplate 은
Spring 에서 구현하는 기능이다.
어떠한 기능인지 알아보기 위해 사용해보았다.
(Spring으로 대체)
위의 예제를 따르면,
add같은 경우에는 Transactional 애노테이션이 붙어있기 때문에
TransactionTemplate 에서 트랜잭션을 처리해주기때문에 TransactionTemplate 과
관련한 코드처리가 불필요해졌다. (리팩토링)
또한 List 는 Transactional 애노테이션이 없기 때문에 구현체를
DefaultService에서 직접 구현할 수 있다.
예시)
* Transactional 부족한 설명 보충 (GPT)
아래에 각각의 경우에 대한 설명을 제공합니다:
add 메서드와 Transactional 애노테이션:
"add" 메서드에 "Transactional" 애노테이션이 붙어있다면, 해당 메서드가 실행될 때 Spring은 자동으로 트랜잭션을 시작하고, 메서드가 예외 없이 실행될 경우에만 트랜잭션을 커밋합니다. 반면에 예외가 발생하면 트랜잭션을 롤백합니다. 이렇게 하면 트랜잭션 관리 코드를 직접 작성하지 않아도 됩니다.
"TransactionTemplate"은 더 세밀한 트랜잭션 컨트롤이 필요한 경우에 사용됩니다. 예를 들어, 여러 메서드 간에 트랜잭션을 공유하거나 중첩 트랜잭션을 처리해야 할 때 유용합니다. 일반적인 경우에는 "Transactional" 애노테이션을 사용하여 트랜잭션을 간편하게 처리할 수 있습니다.
List와 Transactional 애노테이션:
"List" 또는 다른 자바 컬렉션 클래스에는 "Transactional" 애노테이션이 직접 적용되지 않습니다. 대신, 트랜잭션 관리는 주로 서비스 레이어에서 이루어집니다.
"Transactional" 애노테이션은 주로 메서드 레벨에서 사용되며, 메서드 호출 시에 트랜잭션을 시작하고 종료합니다. 따라서 여러 메서드가 한 번에 트랜잭션을 공유하려면 이러한 메서드를 호출하는 서비스 클래스 레벨에서 트랜잭션을 처리합니다.
"List"나 다른 자바 컬렉션을 다룰 때, 트랜잭션의 범위는 일반적으로 메서드 호출 단위로 설정되며, 메서드 내에서 해당 자료구조를 변경한 후에 트랜잭션이 커밋되거나 롤백됩니다.
결론적으로, "Transactional" 애노테이션은 간단한 트랜잭션 처리에 적합하며, "TransactionTemplate"은 보다 세밀한 트랜잭션 컨트롤이 필요한 경우에 사용됩니다. 그리고 자바 컬렉션과 같은 데이터 구조를 다룰 때는 해당 서비스 클래스 레이어에서 트랜잭션을 관리하는 것이 일반적입니다.