스프링에서의 트랜잭션
스프링에서도 SQL 을 배울 때 처럼 CRUD 를 사용할 때 예외가 발생한다면 중간에 있는 코드가 실행되지 않게 하는 트랜잭션 처리를 해주어야 하는데 이 때 여러가지 기술들을 사용하게 된다.
알아보자.
스프링 트랜잭션 의존성 추가
<!-- 스프링 트랜잭션 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${org.springframework-version}</version>
</dependency>
의존성 추가할 때 버전 맞추는법 :
<version>${org.springframework-version}</version>
이 부분에서 기존 버전을 지우고 안에 ${org.springframework-version} 을 써주면 동적으로 스프링의 버전과 일치시켜준다.
스프링 설정을 할 때보면 버전을 맞추는게 있고 따로 있는게 있는데, 이런거는 기본적으로 알아놔야 한다고함.
스프링에서 트랜잭션 사용하기
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
public class TxConfig {
@Autowired
private DataSource dataSource3;
@Bean
public DataSourceTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource3);
}
}
우선 트랜잭션 속성을 지정하려는 곳에 두개의 어노테이션을 추가해준다.
@Configuration @EnableTransactionManagement
트랜잭션의 사용
트랜잭션은 보통 비즈니스 로직에서 사용한다.(서비스 계층)
@Transactional(rollbackFor = SQLException.class)
public boolean memoAddTx(MemoDto memoDto) {
int result = memoDaoImpl.insertTx(memoDto);
return result>0;
}
SQL 예외가 날시에는 rollback이 되도록한다.
트랜잭션 전파속성
[ 트랜잭션 전파 속성(Transaction Propagation)이란? ]Spring이 제공하는 선언적 트랜잭션(트랜잭션 어노테이션, @Transactional)의 장점 중 하나는 여러 트랜잭션을 묶어서 커다란 하나의 트랜잭션 경계를 만들 수 있다는 점이다. 작업을 하다보면 기존에 트랜잭션이 진행중일 때 추가적인 트랜잭션을 진행해야 하는 경우가 있다. 이미 트랜잭션이 진행중일 때 추가 트랜잭션 진행을 어떻게 할지 결정하는 것이 전파 속성(Propagation)이다.
@Transactional 의 추가 옵션 정리
propagation: 트랜잭션 전파 방식을 설정합니다. 다른 트랜잭션 내에서 메서드가 호출될 때 어떻게 트랜잭션을 전파할지를 결정합니다.
예를 들어, REQUIRED, REQUIRES_NEW, SUPPORTS 등이 있습니다.
isolation: 트랜잭션 격리 수준을 설정합니다. 여러 트랜잭션이 동시에 실행될 때 데이터의 일관성을 보장하기 위해 어떤 수준의 격리를 유지할지를 결정합니다.
예를 들어, DEFAULT, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE 등이 있습니다.
timeout: 트랜잭션 타임아웃을 설정합니다. 특정 시간 내에 트랜잭션이 완료되지 않으면 롤백됩니다. 단위는 초(seconds)입니다.
readOnly: 읽기 전용 트랜잭션 여부를 설정합니다. 읽기 전용 트랜잭션은 해당 트랜잭션 동안 데이터를 수정하지 않음을 나타냅니다. 기본값은 false이며, true로 설정하면 성능을 향상시킬 수 있습니다.
rollbackFor / noRollbackFor: 롤백을 수행할 예외 클래스를 지정하거나 롤백을 수행하지 않을 예외 클래스를 지정합니다.
ViewResolver란?
- 🗸 실행할 뷰를 찾는 일을 한다.
- 🗸 페이지 컨트롤러가 리턴한 뷰 이름에 해당하는 뷰 콤포넌트를 찾는 역할.
컨트롤러 계층에서 찾는다.
그리고 어떤 뷰로 응답을 생성할지 결정하는 역할을 한다.
REST 란 ?
[ RestController ]@RestController는 @Controller에 @ResponseBody가 추가된 것입니다. 당연하게도 RestController의 주용도는 Json 형태로 객체 데이터를 반환하는 것입니다. 최근에 데이터를 응답으로 제공하는 REST API를 개발할 때 주로 사용하며 객체를 ResponseEntity로 감싸서 반환합니다. 이러한 이유로 동작 과정 역시 @Controller에 @ReponseBody를 붙인 것과 완벽히 동일합니다.
출처:
https://mangkyu.tistory.com/49
[MangKyu's Diary:티스토리]
@Controller와 @RestController 어노테이션의 차이
일단 둘다 스프링에서 Controller 로 지정해주는 어노테이션은 맞다.
여기서 차이점은 ResponseBody가 생성되는 방식이다.
Controller로 View 를 반환할 경우
컨트롤러는 받은 요청을 처리하고 View 이름을 반환하는데 이 때
DispatcherServlet 이 뷰 리졸버를 통해 일치하는 view 를 찾아 사용자에게 반환함. (포워딩처리)
[Controller로 Data를 반환할 경우]
Controller 가 view 가 아닌 Data 를 반환해야 하는 경우도 있는데 , 그럴 때는 데이터를 반환하기 위해서 ResponseBody를 사용해야 하는데 이 때 @ResponseBody 를 사용한다.
이 어노테이션으로 Controller 도 View 뿐이 아닌 JSON 형태의 데이터도 반환을 할 수 있다.
이처럼 ResponseBody 에 Data를 담아 다른 View 에 이동할 때 model 객체에 데이터를 실어서 보낼 수 있다.
※ 주로 Controller 메서드의 반환값은 View 이름으로 간주된다.
@RestController
@RestController 는 Controller 와 ResponseBody 가 합쳐진 어노테이션이라고 생각하면 된다.
@Controller 와 다르게 반환하는 주 데이터는 JSON 형태의 객체 데이터이다.
REST API를 개발할 때 주로 사용하며 마찬가지로 ResponseEntity로 감싸서 주로 반환한다.
예시
@RestController
public class MyRestController {
@GetMapping("/api/welcome")
public Map<String, String> welcome() {
Map<String, String> response = new HashMap<>();
response.put("message", "Welcome to the site!");
return response; // JSON 응답
}
}
Json 데이터를 반환해준다.
@PatchMapping(value="/patch",consumes= MediaType.APPLICATION_JSON_VALUE) //들어오는 타입 JSON 타입
public ResponseEntity<Boolean> update_patch(@RequestBody MemoDto memoDto) {
log.info("/patch... patch !! "+memoDto); //patch 는 부븐을 수정 put 은 전체 매핑
boolean isUpdate = memoServiceImpl.memoUpdate_patch(memoDto);
return isUpdate? new ResponseEntity(isUpdate,HttpStatus.OK) : new ResponseEntity(isUpdate,HttpStatus.BAD_REQUEST); //결국 이 responseEntity 는 웹의 반응결과를 같이 함수결과와 보내주기 위한 객체 용도인듯하다.
}
Consume 을 사용한 rest 메서드
@GetMapping(value="/getJsonEntity/{show}",produces = MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<MemoDto> t6( //반환 타입이 XML 파일로 강제된다.
@PathVariable boolean show
) {
log.info("getjsonlist ffkfkfkffk");
if(!show)
return new ResponseEntity(null,HttpStatus.BAD_GATEWAY);
return new ResponseEntity(new MemoDto(20,"memo","ex@ex.com",null),HttpStatus.OK);
}
produce를 사용한 메서드
Consume 과 Produce 메서드의 차이
- Consume : consume 은 들어오는 데이터를 정의한다 (주로 get 같이 데이터를 받을 때 사용)
- produce : produce 는 반환 데이터타입을 정의한다 (Post 같이 데이터를 보낼 때 사용)
@ResponseEntity , @RequestEntity
응답 데이터를 포함하는 클래스
HttpEntity 클래스를 상속받아 구현하는 클래스이다.
public ResponseEntity<MemoDto> update //
boolean isUpdate = memoServiceImpl.memoUpdate_patch(memoDto);
new ResponseEntity(isUpdate,HttpStatus.OK)
(바디, 헤더 , 상태코드) 의 정보를 객체에 담을 수 있다.
이렇게 Controller 와 RestController 를 잘 사용하면
파라미터를 쿼리스트링으로 날리거나 바디에 숨겨서 날릴수있다. !
'Developer Note > 국비과정 수업내용 정리&저장' 카테고리의 다른 글
24년 11월 18일 (0) | 2024.11.24 |
---|---|
24년 11월 15일 (0) | 2024.11.24 |
24년 11월 13일 (0) | 2024.11.24 |
24년 11월 12일 (0) | 2024.11.22 |
24년 11월 11일 (1) | 2024.11.21 |