You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// 트랜잭션 시작TransactionStatusstatus = transactionManager.getTransaction(newDefaultTransactionDefinition());
try {
bizLogic(fromId, toId, money);
// 성공시 커밋transactionManager.commit(status);
} catch (Exceptione) {
transactionManager.rollback(status); // 트랜잭션 매니저가 커밋 or 롤백 하면 커넥션 다 정리해줌.thrownewIllegalStateException(e);
}
트랜잭션 시작 -> 비즈니스 로직 -> 성공시 커밋, 실패시 롤백
다른 서비스에서도 이 로직을 위해 try catch ... 커밋 or 롤백 코드가 반복될 것. 달라지는 것은 비즈니스 로직 뿐.
이럴땐 템플릿 콜백 패턴을 활용해 깔끔히 해결 가능.
템플릿 콜백 패턴에 대해서 지금은 자세히 이해하지 못해도 괜찮다. 스프링이 TransactionTemplate 이라는 편리한 기능을 제공하는 구나 정도로 이해해도 된다. 템플릿 콜백 패턴에 대한 자세한 내용은 스프링 핵심 원리 - 고급편 강의를 참고하자.
트랜잭션 템플릿
템플릿 콜백 패턴을 적용하기 위해 템플릿을 제공하는 클래스를 작성해야하는데, 스프링에서 TransactionTemplate 라는 템플릿 클래스를 제공.
publicclassTransactionTemplate {
privatePlatformTransactionManagertransactionManager;
public <T> Texecute(TransactionCallback<T> action){..} // 응답값이 있을 때 사용voidexecuteWithoutResult(Consumer<TransactionStatus> action){..} // 응답값이 없을 때 사용.
}
이걸 적용해보자!
publicclassMemberServiceV3_2 {
// private final DataSource dataSource;privatefinalTransactionTemplatetxTemplate;
privatefinalMemberRepositoryV3memberRepositoryV3;
publicMemberServiceV3_2(PlatformTransactionManagertransactionManager, MemberRepositoryV3memberRepositoryV3) {
this.txTemplate = newTransactionTemplate(transactionManager); // 이렇게 하는 이유 : 유연성을 위해 (TransactionTemplate 는 클래스여서 유연성이 없음)this.memberRepositoryV3 = memberRepositoryV3;
}
publicvoidaccountTransfer(StringfromId, StringtoId, intmoney) {
txTemplate.executeWithoutResult((status) -> {
try {
bizLogic(fromId, toId, money);
} catch (SQLExceptione) {
thrownewIllegalStateException(e);
}
});
}
트랜잭션 템플릿 덕분에 트랜잭션을 시작하고, 커밋하거나 롤백하는 코드가 모두 제거되었다.
트랜잭션 템플릿의 기본 동작은 다음과 같다.
비즈니스 로직이 정상 수행되면 커밋한다.
언체크 예외가 발생하면 롤백한다. 그 외의 경우 커밋한다. (체크 예외의 경우에는 커밋하는데, 이 부분은 뒤 에서 설명한다.)
코드에서 예외를 처리하기 위해 try~catch 가 들어갔는데, bizLogic() 메서드를 호출하면 SQLException 체크 예외를 넘겨준다. 해당 람다에서 체크 예외를 밖으로 던질 수 없기 때문에 언체크 예외로 바꾸어 던지도록 예외를 전환했다.
하지만 이곳은 서비스 로직인데 비즈니스 로직 뿐만 아니라 트랜잭션을 처리하는 기술 로직이 함께 포함되어 있 다.
애플리케이션을 구성하는 로직을 핵심 기능과 부가 기능으로 구분하자면 서비스 입장에서 비즈니스 로직은 핵심 기능이고, 트랜잭션은 부가 기능이다.
이렇게 비즈니스 로직과 트랜잭션을 처리하는 기술 로직이 한 곳에 있으면 두 관심사를 하나의 클래스에서 처리하 게 된다. 결과적으로 코드를 유지보수하기 어려워진다.
서비스 로직은 가급적 핵심 비즈니스 로직만 있어야 한다. 하지만 트랜잭션 기술을 사용하려면 어쩔 수 없이 트랜 잭션 코드가 나와야 한다. 어떻게 하면 이 문제를 해결할 수 있을까?
트랜잭션 AOP, 프록시로 이를 해결할 수 있음!
트랜잭션 문제 해결 - 트랜잭션 AOP 이해
트랜잭션을 편리하게 처리하기 위해
트랜잭션 추상화
반복적인 로직 줄이기 위해 트랜잭션 템플릿 도입
그러나 아직 서비스 계층에 순수한 비즈니스 로직만 남긴다는 목표 달성 못함.
이는 스프링 AOP를 통해 프록시를 도입하면 해결 가능.
스프링 AOP와 프록시에 대해서 지금은 자세히 이해하지 못해도 괜찮다. 지금은 @Transactional 을 사용하 면 스프링이 AOP를 사용해서 트랜잭션을 편리하게 처리해준다 정도로 이해해도 된다. 스프링 AOP와 프록시에 대한 자세한 내용은 스프링 핵심 원리 - 고급편을 참고하자.
지금은 아래 그림을 그냥 추상적으로 이해하자.
프록시 도입 후: 트랜잭션 프록시가 트랜잭션 처리 로직을 모두 가져간다. 그리고 트랜잭션을 시작한 후에 실제 서 비스를 대신 호출한다. 트랜잭션 프록시 덕분에 서비스 계층에는 순수한 비즈니즈 로직만 남길 수 있다.
스프링이 제공하는 트랜잭션 AOP
스프링이 제공하는 AOP 기능을 사용하면 프록시를 매우 편리하게 적용할 수 있다. 스프링 핵심 원리 - 고급편을 통해 AOP를 열심히 공부하신 분이라면 아마도 @Aspect , @Advice , @Pointcut 를 사용해서 트랜잭션 처 리용 AOP를 어떻게 만들지 머리속으로 그림이 그려질 것이다.
물론 스프링 AOP를 직접 사용해서 트랜잭션을 처리해도 되지만, 트랜잭션은 매우 중요한 기능이고, 전세계 누구 나 다 사용하는 기능이다. 스프링은 트랜잭션 AOP를 처리하기 위한 모든 기능을 제공한다. 스프링 부트를 사용하 면 트랜잭션 AOP를 처리하기 위해 필요한 스프링 빈들도 자동으로 등록해준다.
개발자는 트랜잭션 처리가 필요한 곳에 @Transactional 애노테이션만 붙여주면 된다. 스프링의 트랜잭션 AOP는 이 애노테이션을 인식해서 트랜잭션 프록시를 적용해준다.
순수한 비즈니스 로직만 남기고, 트랜잭션 관련 코드는 모두 제거했다.
스프링이 제공하는 트랜잭션 AOP를 적용하기 위해 @Transactional 애노테이션을 추가했다. @Transactional 애노테이션은 메서드에 붙여도 되고, 클래스에 붙여도 된다. 클래스에 붙이면 외부에서 호출 가능한 public 메서드가 AOP 적용 대상이 된다.
테스트를 그냥 실행하면 예외시 롤백 안됨.
왜냐하면, 이 테스트는 스프링 컨테이너? 를 전혀 쓰고있지 않기 때문.
모든 객체를 직접 만들어 호출함. -> 스프링을 안쓰는것! 스프링 컨테이너에 스프링 빈을 등록해 쓰는게 아니고 그냥 호출했기 때문.
스프링 AOP 를 적용하기 위해선 스프링을 사용해야함. @SpringBootTest 를 보면, 스프링부트를 하나 띄워서 필요한 스프링 빈을 등록하고 의존관계 주입도 진행함. (스프링 자체적으로 필요한 빈들 등록하고, 내가 자체적으로 빈을 추가하고 싶을 땐 @TestConfiguration 사용) @Autowired 등을 통해 스프링 컨테이 너가 관리하는 빈들을 사용할 수 있다.
memberService class=class hello.jdbc.service.MemberServiceV3_3$$SpringCGLIB$$0
memberRepository class = class hello.jdbc.connection.repository.MemberRepositoryV3
앞서 AOP 가 서비스 코드를 호출하기 위해선, 서비스 로직이 있는 클래스를 상속해 우리가 이전까지 작성했던 코드 처럼 트랜잭션 코드를 만들어냄
서비스 로직을 호출하면,
AOP 프록시가 호출되고
AOP 프록시는 트랜잭션 매니져를 가지고있기 때문에 (스프링 빈에 있는 트랜잭션 매니져를 가져다 씀)
트랜잭션 매니저에서 트랜잭션 시작,
트랜잭션 매니저는 데이터 소스로 커넥션을 만듦.
커낵션의 AutoCommit(false) 를 통해 트랜잭션 진짜 시작.
이 커낵션을 트랜잭션 동기화 매니저에 보관
이후 실제 서비스 로직 호출하고, 결국 리포지토리에서 트랜잭션 동기화 매니저에 있는 커넥션을 사용해 (리포지토리에서 getConnection() 사용해 커넥션 획득)
로직이 성공이면 커밋, 실패면 롤백 하며 종료
이 모든 부분을 스프링이 애노테이션 하나로 다 해줌!
선언적 트랜잭션 관리 vs 프로그래밍 방식 트랜잭션 관리
선언적 트랜잭션 관리(Declarative Transaction Management)
@Transactional 애노테이션 하나만 선언해서 매우 편리하게 트랜잭션을 적용하는 것을 선언적 트랜잭 션 관리라 한다.
선언적 트랜잭션 관리는 과거 XML에 설정하기도 했다. 이름 그대로 해당 로직에 트랜잭션을 적용하겠다 라 고 어딘가에 선언하기만 하면 트랜잭션이 적용되는 방식이다.
프로그래밍 방식의 트랜잭션 관리(programmatic transaction management)
트랜잭션 매니저 또는 트랜잭션 템플릿 등을 사용해서 트랜잭션 관련 코드를 직접 작성하는 것을 프로그래 밍 방식의 트랜잭션 관리라 한다.
선언적 트랜잭션 관리가 프로그래밍 방식에 비해서 훨씬 간편하고 실용적이기 때문에 실무에서는 대부분 선언적 트랜잭션 관리를 사용한다.
프로그래밍 방식의 트랜잭션 관리는 스프링 컨테이너나 스프링 AOP 기술 없이 간단히 사용할 수 있지만 실무에서는 대부분 스프링 컨테이너와 스프링 AOP를 사용하기 때문에 거의 사용되지 않는다.
프로그래밍 방식 트랜잭션 관리는 테스트 시에 가끔 사용될 때는 있다.
스프링이 제공하는 선언적 트랜잭션 관리 덕분에 드디어 트랜잭션 관련 코드를 순수한 비즈니스 로직에서 제거할 수 있었다.
개발자는 트랜잭션이 필요한 곳에 @Transactional 애노테이션 하나만 추가하면 된다. 나머지는 스프링 트랜 잭션 AOP가 자동으로 처리해준다.
@Transactional 애노테이션의 자세한 사용법(여러 옵션)은 뒤에서 설명한다. 지금은 전체 구조를 이해하는데 초점 을 맞추자.
스프링 부트의 자동 리소스 등록
스프링 부트 등장 전에는 데이터소스와 트랜잭션 매니저를 개발자가 직접 스프링 빈으로 등록해서 사용해야했다. (test 코드)
스프링부트를 사용하면 이를 자동으로 해준다.
빈 직접 등록
@TestConfigurationstaticclassTestConfig {
@BeanDataSourcedataSource() {
returnnewDriverManagerDataSource(URL, USERNAME, PASSWORD);
}
@BeanPlatformTransactionManagertransactionManager() {
// 트랜잭션 AOP 에서 트랜잭션 진행하기 위해 필요함returnnewDataSourceTransactionManager(dataSource());
}
기존엔 이렇게 직접 등록해야 했지만, 스프링 부트가 많은 부분을 자동으로 해줌. (예전엔 이부분을 XML 로 관리함)
데이터소스 - 자동 등록
스프링 부트는 데이터소스( DataSource )를 스프링 빈에 자동으로 등록한다.
자동으로 등록되는 스프링 빈 이름: dataSource
참고로 개발자가 직접 데이터소스를 빈으로 등록하면 스프링 부트는 데이터소스를 자동으로 등록하지 않는다. (직접 만들었다 = 커스터마이징)
이때 스프링 부트는 다음과 같이 application.properties 에 있는 속성을 사용해서 DataSource 를 생성한다. 그리고 스프링 빈에 등록한다.
스프링 부트가 기본으로 생성하는 데이터소스는 커넥션풀을 제공하는 HikariDataSource. 커넥션풀과 관련된 설정도 application.properties 를 통해서 지정할 수 있다.
spring.datasource.url 속성이 없으면 내장 데이터베이스(메모리 DB)를 생성하려고 시도한다.
트랜잭션 매니저 - 자동 등록
스프링 부트는 적절한 트랜잭션 매니저( PlatformTransactionManager )를 자동으로 스프링 빈에 등록한 다.
자동으로 등록되는 스프링 빈 이름: transactionManager
참고로 개발자가 직접 트랜잭션 매니저를 빈으로 등록하면 스프링 부트는 트랜잭션 매니저를 자동으로 등록하지 않는다.
�
어떤 트랜잭션 매니저를 스프링 빈에 등록할지 (PlatformTransactionManager 는 인터페이스이고, 실제 어떤 구현체를 등록할지) 현재 등록된 라이브러리를 보고 판단함. JDBC를 기술을 사용하면 DataSourceTransactionManager 를 빈으로 등록하고, JPA를 사용하면 JpaTransactionManager 를 빈으
로 등록한다. 둘다 사용하는 경우 JpaTransactionManager 를 등록한다. 참고로 JpaTransactionManager 는 DataSourceTransactionManager 가 제공하는 기능도 대부분 지원한다.
그럼 테스트에서 사용하던 빈 등록을 지워보고 스프링을 사용해보자.
문제: Repository 를 만들때 필요한 데이터소스를 어떻게 가져오나?
@TestConfiguration@RequiredArgsConstructorstaticclassTestConfig {
// 스프링 빈에 있는 DataSource 를 주입받음.privatefinalDataSourcedataSource;
@BeanMemberRepositoryV3memberRepositoryV3() {
returnnewMemberRepositoryV3(dataSource);
}
@BeanMemberServiceV3_3memberService() {
returnnewMemberServiceV3_3(memberRepositoryV3());
}
}
(이하생략)
그냥 돌리면 spring.datasource.url 속성이 없어 메모리 DB 를 사용함.
application.properties 에 추가
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
트랜잭션 문제 해결 - 트랜잭션 템플릿
트랜잭션 사용 로직에서 같은 패턴이 반복된다.
트랜잭션 시작 -> 비즈니스 로직 -> 성공시 커밋, 실패시 롤백
다른 서비스에서도 이 로직을 위해 try catch ... 커밋 or 롤백 코드가 반복될 것. 달라지는 것은 비즈니스 로직 뿐.
이럴땐 템플릿 콜백 패턴을 활용해 깔끔히 해결 가능.
템플릿 콜백 패턴에 대해서 지금은 자세히 이해하지 못해도 괜찮다. 스프링이
TransactionTemplate이라는 편리한 기능을 제공하는 구나 정도로 이해해도 된다. 템플릿 콜백 패턴에 대한 자세한 내용은 스프링 핵심 원리 - 고급편 강의를 참고하자.트랜잭션 템플릿
템플릿 콜백 패턴을 적용하기 위해 템플릿을 제공하는 클래스를 작성해야하는데, 스프링에서 TransactionTemplate 라는 템플릿 클래스를 제공.
이걸 적용해보자!
try~catch가 들어갔는데,bizLogic()메서드를 호출하면SQLException체크 예외를 넘겨준다. 해당 람다에서 체크 예외를 밖으로 던질 수 없기 때문에 언체크 예외로 바꾸어 던지도록 예외를 전환했다.이를 활용하는 테스트 : 서비스를 V3_1 에서 V3_2 로 바꾸면 됨.
트랜잭션 AOP, 프록시로 이를 해결할 수 있음!
트랜잭션 문제 해결 - 트랜잭션 AOP 이해
트랜잭션을 편리하게 처리하기 위해
그러나 아직 서비스 계층에 순수한 비즈니스 로직만 남긴다는 목표 달성 못함.
이는 스프링 AOP를 통해 프록시를 도입하면 해결 가능.
스프링 AOP와 프록시에 대해서 지금은 자세히 이해하지 못해도 괜찮다. 지금은
@Transactional을 사용하 면 스프링이 AOP를 사용해서 트랜잭션을 편리하게 처리해준다 정도로 이해해도 된다. 스프링 AOP와 프록시에 대한 자세한 내용은 스프링 핵심 원리 - 고급편을 참고하자.지금은 아래 그림을 그냥 추상적으로 이해하자.
기존의 트랜직션 로직. 서비스에서 트랜잭션을 시작하고 종료함.
프록시를 사용하면, 서비스 로직은 그대로 두고 트랜잭션 대리인이 생김.
클라이언트가 서비스를 호출하는게 아니라, 트랜잭션 프록시에서 서비스로직을 호출함.
프록시는 스프링이 다 만들어줌.
트랜잭션 프록시 코드 예시 서비스에는 깔끔하게 비즈니스 로직만 있음!
스프링이 제공하는 트랜잭션 AOP
@Aspect,@Advice,@Pointcut를 사용해서 트랜잭션 처 리용 AOP를 어떻게 만들지 머리속으로 그림이 그려질 것이다.@Transactional애노테이션만 붙여주면 된다. 스프링의 트랜잭션 AOP는 이 애노테이션을 인식해서 트랜잭션 프록시를 적용해준다.@transactional
org.springframework.transaction.annotation.Transactional스프링 AOP를 적용하려면 어드바이저, 포인트컷, 어드바이스가 필요하다. 스프링은 트랜잭션 AOP 처리를 위해 다음 클래스를 제공한다. 스프링 부트를 사용하면 해당 빈들은 스프링 컨테이너에 자동으로 등록된다.
어드바이저:
BeanFactoryTransactionAttributeSourceAdvisor포인트컷:
TransactionAttributeSourcePointcut어드바이스:
TransactionInterceptor트랜잭션 문제 해결 - 트랜잭션 AOP 적용
코드로 적용해보자
순수한 비즈니스 로직만 남기고, 트랜잭션 관련 코드는 모두 제거했다.
스프링이 제공하는 트랜잭션 AOP를 적용하기 위해
@Transactional애노테이션을 추가했다.@Transactional애노테이션은 메서드에 붙여도 되고, 클래스에 붙여도 된다. 클래스에 붙이면 외부에서 호출 가능한public메서드가 AOP 적용 대상이 된다.테스트를 그냥 실행하면 예외시 롤백 안됨.
왜냐하면, 이 테스트는 스프링 컨테이너? 를 전혀 쓰고있지 않기 때문.
모든 객체를 직접 만들어 호출함. -> 스프링을 안쓰는것! 스프링 컨테이너에 스프링 빈을 등록해 쓰는게 아니고 그냥 호출했기 때문.
스프링 AOP 를 적용하기 위해선 스프링을 사용해야함.
@SpringBootTest 를 보면, 스프링부트를 하나 띄워서 필요한 스프링 빈을 등록하고 의존관계 주입도 진행함. (스프링 자체적으로 필요한 빈들 등록하고, 내가 자체적으로 빈을 추가하고 싶을 땐 @TestConfiguration 사용)
@Autowired 등을 통해 스프링 컨테이 너가 관리하는 빈들을 사용할 수 있다.
@TestConfiguration: 테스트 안에서 내부 설정 클래스를 만들어서 사용하면서 이 에노테이션을 붙이면, 스 프링 부트가 자동으로 만들어주는 빈들에 추가로 필요한 스프링 빈들을 등록하고 테스트를 수행할 수 있다.TestConfigDataSource스프링에서 기본으로 사용할 데이터소스를 스프링 빈으로 등록한다. 추가로 트랜잭션 매니 저에서도 사용한다.DataSourceTransactionManager트랜잭션 매니저를 스프링 빈으로 등록한다.AOP 적용 확인을 위해 아래 테스트 추가
결과
앞서 AOP 가 서비스 코드를 호출하기 위해선, 서비스 로직이 있는 클래스를 상속해 우리가 이전까지 작성했던 코드 처럼 트랜잭션 코드를 만들어냄
로 의존관계 주입을 받을 때, 스프링 빈에서 알아서 프록시로 만든 녀석을 주입함.
스프링이 클래스에 @transactional 이 있으면 AOP 대상임을 인지하고 AOP 를 만들어냄.
Assertions 로도 AOP 를 확인할 수 있음
트랜잭션 문제 해결 - 트랜잭션 AOP 정리
서비스 로직을 호출하면,
AOP 프록시가 호출되고
AOP 프록시는 트랜잭션 매니져를 가지고있기 때문에 (스프링 빈에 있는 트랜잭션 매니져를 가져다 씀)
트랜잭션 매니저에서 트랜잭션 시작,
트랜잭션 매니저는 데이터 소스로 커넥션을 만듦.
커낵션의 AutoCommit(false) 를 통해 트랜잭션 진짜 시작.
이 커낵션을 트랜잭션 동기화 매니저에 보관
이후 실제 서비스 로직 호출하고, 결국 리포지토리에서 트랜잭션 동기화 매니저에 있는 커넥션을 사용해 (리포지토리에서 getConnection() 사용해 커넥션 획득)
로직이 성공이면 커밋, 실패면 롤백 하며 종료
이 모든 부분을 스프링이 애노테이션 하나로 다 해줌!
선언적 트랜잭션 관리 vs 프로그래밍 방식 트랜잭션 관리
선언적 트랜잭션 관리(Declarative Transaction Management)
@Transactional애노테이션 하나만 선언해서 매우 편리하게 트랜잭션을 적용하는 것을 선언적 트랜잭 션 관리라 한다.프로그래밍 방식의 트랜잭션 관리(programmatic transaction management)
선언적 트랜잭션 관리가 프로그래밍 방식에 비해서 훨씬 간편하고 실용적이기 때문에 실무에서는 대부분 선언적 트랜잭션 관리를 사용한다.
프로그래밍 방식의 트랜잭션 관리는 스프링 컨테이너나 스프링 AOP 기술 없이 간단히 사용할 수 있지만 실무에서는 대부분 스프링 컨테이너와 스프링 AOP를 사용하기 때문에 거의 사용되지 않는다.
프로그래밍 방식 트랜잭션 관리는 테스트 시에 가끔 사용될 때는 있다.
스프링이 제공하는 선언적 트랜잭션 관리 덕분에 드디어 트랜잭션 관련 코드를 순수한 비즈니스 로직에서 제거할 수 있었다.
개발자는 트랜잭션이 필요한 곳에
@Transactional애노테이션 하나만 추가하면 된다. 나머지는 스프링 트랜 잭션 AOP가 자동으로 처리해준다.@Transactional애노테이션의 자세한 사용법(여러 옵션)은 뒤에서 설명한다. 지금은 전체 구조를 이해하는데 초점 을 맞추자.스프링 부트의 자동 리소스 등록
스프링 부트 등장 전에는 데이터소스와 트랜잭션 매니저를 개발자가 직접 스프링 빈으로 등록해서 사용해야했다. (test 코드)
스프링부트를 사용하면 이를 자동으로 해준다.
빈 직접 등록
기존엔 이렇게 직접 등록해야 했지만, 스프링 부트가 많은 부분을 자동으로 해줌. (예전엔 이부분을 XML 로 관리함)
데이터소스 - 자동 등록
DataSource)를 스프링 빈에 자동으로 등록한다.dataSource이때 스프링 부트는 다음과 같이
application.properties에 있는 속성을 사용해서DataSource를 생성한다. 그리고 스프링 빈에 등록한다.HikariDataSource. 커넥션풀과 관련된 설정도application.properties를 통해서 지정할 수 있다.spring.datasource.url속성이 없으면 내장 데이터베이스(메모리 DB)를 생성하려고 시도한다.트랜잭션 매니저 - 자동 등록
PlatformTransactionManager)를 자동으로 스프링 빈에 등록한 다.transactionManager�
어떤 트랜잭션 매니저를 스프링 빈에 등록할지 (PlatformTransactionManager 는 인터페이스이고, 실제 어떤 구현체를 등록할지) 현재 등록된 라이브러리를 보고 판단함. JDBC를 기술을 사용하면
DataSourceTransactionManager를 빈으로 등록하고, JPA를 사용하면JpaTransactionManager를 빈으로 등록한다. 둘다 사용하는 경우
JpaTransactionManager를 등록한다. 참고로JpaTransactionManager는DataSourceTransactionManager가 제공하는 기능도 대부분 지원한다.그럼 테스트에서 사용하던 빈 등록을 지워보고 스프링을 사용해보자.
문제: Repository 를 만들때 필요한 데이터소스를 어떻게 가져오나?
그냥 돌리면
spring.datasource.url속성이 없어 메모리 DB 를 사용함.application.properties 에 추가
데이터소스와 트랜잭션 매니저는 스프링 부트가 제공하는 자동 빈 등록 기능을 사용하는 것이 편리하다.
추가로
application.properties를 통해 설정도 편리하게 할 수 있다.스프링 부트의 데이터소스 자동 등록에 대한 더 자세한 내용은 다음 스프링 부트 공식 메뉴얼을 참고하자.
https://docs.spring.io/spring-boot/docs/current/reference/html/ data.html#data.sql.datasource.production
자세한 설정 속성은 다음을 참고하자.
https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html
All reactions