
오늘은 9시부터 코어타임에 갔다왔는데.. 경기도 통학 1교시? 사람이 하는게 아니다.
암튼 7시에 나가서 코어타임 갔다가 밥 먹고 여권발급까지하고 집에 오니까 14시가 됨. 그래서 알바 가기 전에 책이나 한 번 읽으려고한다. 오늘 API 연결하려다 실패해서 개발은 더 못하겠음
@SessionAttributes
여기서 나온 타코 주문과 같이 다수의 HTTP 요청에서 사용할 자료가 있을 때, Model 객체를 사용해 VIEW에 데이터를 전달할 경우에는 SessionAttributes를 사용할 수 있다고한다. 아니면 쿠키처럼 내가 세션에 추가해야하는데, 그냥 JWT토큰을 발급합시다
model 객체에는 다음의 메서드가 있는데,
model.addAttribute("name", Object);
이 메서드는 Object를 name의 이름으로 Model에게 전달한다. 그 이후는 이전 내용 참고~
암튼 여기서 SessionAttributes 어노테이션은 클래스 위에 적용되며,
@Controller
@SessionAttributes("order")
public class TestController {
...
public void testMethod(Model model) {
model.addAttributes("name", Object);
...
}
...
}
이런식으로 개발된 코드가 있다고 했을 때 SessionAttributes의 인자와 model의 addAttributes 된 Object의 이름이 같으면 자동으로 세션에 등록시켜준다.
Model 객체를 사용하지 않을 경우엔
httpSession.setAttribute("name", Object);
이 코드를 사용하면 된다.
받아올 때는 SessionAttribute 방식은 메서드 인자로 넣어줄 수 있고, 어노테이션의 인자로는 세션의 이름을 넣으면 된다.
사용하지 않을 경우에는 getAttribute 메서드를 사용하면 된다.
자세한 내용은 다음 포스트 참고 -> https://sun-22.tistory.com/53
핸들러 메서드: @SessionAttributes, @SessionAttribute
Session은 여러 화면이나 여러 요청에서 사용해야 하는 객체를 공유할 때 사용할 수 있다, HttpSession사용 HttpSession을 사용하여 직접 session을 추가할 수 있다. 테스트를 통해 세션정보를 확인해보면
sun-22.tistory.com
SimpleJDBCInsert
앞서 나왔던 PreparedStatementCreator 방식을 좀 더 쉽게 사용할 수 있는 방법으로 SimpleJdbcInsert 가 있다.
스프링인액션 95쪽에 나온 예시코드를 보자면..
@Repository
public class JdbcOrderRepository implements OrderRepository {
private SimpleJdbcInsert orderInserter;
private SimpleJdbcInsert orderTacoInserter;
private ObjectMapper objectMapper;
@Autwired
public JdbcOrderRepository(JdbcTemplate jdbc) {
this.orderInserter = new SimpleJdbcInsert(jdbc)
.withTableName("Taco_Order")
.usingGenerateKeyColumns("id");
this.orderTacoInserter = new SimpleJdbcInsert(jdbc)
.withTableName("Taco_Order_Tacos");
this.object4Mapper = new ObjectMapper();
}
}
이런 코드가 있다. (문제시 삭제)
참고로 DI가 적용된 버전이다. SimpleJdbcInsert는 스프링이 관리하지 않는 객체이기에 DI 적용대상이 아니지만 인자로 주는 JdbcTemplate이 스프링의 관리를 받는 객체이기에 자동으로 초기화가 된다.
여기서 사용될 핵심개념이 SimplerJdbcInsert다.
생성자에서는 orderInserter 인스턴스 변수에 SimpleJdbcInsert를 넣어주고있고, orderTacoInserter에도 같은 작업을 반복 중이다. 내가 보통 진행한 생성자 형성에는 인스턴스 변수 이름과 레퍼런스의 이름이 동일했는데, 이건 다른 버전. 이렇게도 사용할 수 있구나 정도로 생각하면 된다.
withTableName 메서드는 어느 테이블에 추가할지 이름을 정하고,
usingGenerateKeyColumns는 자동으로 생성되는 열의 이름을 설정한다. JPA에서 쓰는 GeneratedValue 어노테이션에 해당하는 듯
이외에도 usingColumns 메서드는 추가할 열의 이름을 설정한다.
실제로 저장하기
96페이지 참고
SimpleJdbcInsert는 위에 말고도 Map을 인자로 받는 execute()와 .excuteAndReturnKey() 메서드를 가진다. Map에서 String 은 테이블의 열 이름이며, Object는 해당 열에 추가되는 값이다.
즉, SimpleJdbcInsert에서는 .withTableName 메서드를 통해 테이블의 이름을 지정하고, .withColumns 메서드를 통해 어느 컬럼명에 값을 넣을지 지정한다. 이 때 .withColunms 메서드를 사용한 경우 .execute를 통해 들어온 Map 객체에서 String (key) 값과 .withColunms의 인자를 비교해 일치할 경우에만 값을 삽입, 아닐 경우에는 무시된다. 사용하지 않을 경우에는 전부 들어간다. .usingGenerateKeyColunms는 자동으로 생성될 열의 이름을 고른다. 만약에 자동지정된 컬럼명이 Map 객체의 key로 들어온다면 오류가 나겠지...?
.execute는 그냥 값을 저장하고 끝
.executeAndReturnKey 메서드는 값을 저장하고 그의 자동생성된 컬럼의 값을 반환한다. 아까 저기 위에서 usingGenerateKeyColunms에 지정된 컬럼명의 값을 반환. 이때 Number 객체로 반환되기 때문에 각자에 맞는 타입으로 변환시킨 후 이용해야한다.
private long saveToJdbc(Member member) {
PreparedStatementCreator psc =
new PreparedStatementCreatorFactory(
"insert into MEMBER (email, nickname, password, user_Id) values (?, ?, ?, ?)",
Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR
).newPreparedStatementCreator(
Arrays.asList(
member.getEmail(),
member.getNickname(),
member.getPassword(),
member.getUserId()
));
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(psc, keyHolder);
return keyHolder.getKey().longValue();
}
...
private SimpleJdbcInsert memberInserter;
private ObjectMapper objectMapper;
public JdbcMemberRepository(JdbcTemplate jdbc) {
this.memberInserter = new SimpleJdbcInsert(jdbc)
.withTableName("Member")
.usingGenereatedKeyColumns("id");
this.objectMapper = new ObjectMapper();
private long saveToSimpleJdbc(Member member) {
Map<String, Object> values = ObjectMapper.convertValue(member, Map.class);
//이러고 현재시간 등의 추가할 데이터를 put 메서드로 추가하면 됨.
long memberId =
memberInserter
.executeAndReturnKey(values)
.longValue();
return memberId;
}
전에 배운 PreparedStatement와 비교해보니.. 좀 더 쉬워보이긴 하다. 코드가 약간 늘어나긴 했는데 메서드로 구분되어 있기도하고 좀 더 직관적으로 보이기도 하고.. 암튼 저거를 save 메서드는 따로 만들어서 저장까지 구현하면 된다.
이외에도 컨버터를 만드는 방식도 있는데, 코드에서 굳이 컨버터를 만들지도 않고 호출되지도 않아서 아직은 다루지 않을 생각이다.
ObjectMappr는 그냥 객체를 Map 형식으로 바꾼다고 생각하고 넘어가면 될 듯 (원래 ObjectMapper의 용도는 이게 아니라고 한다.)
여기까지가 스프링인액션에서의 JDBC 내용인데, 생각보다 어렵다..
DB 접근하는게 좀 귀찮기도하고 어렵기도하고 암튼 메서드들의 내용과 클래스의 내용이 DB 배경지식이 조금 필요하기도하고 코드도 다소 복잡하기 때문에 읽는데 오래걸렸다. 게다가 JPA도 해야하니...
암튼 JDBC까지 읽고 다시 정리를 하던가 매듭을 한 번 지어야할 것 같다. 그 뒤에 JPA를 해야지 그렇지 않으면 JPA랑 JDBC랑 헷갈려서 뒤죽박죽이 될 것 같다.
'CS > 백엔드' 카테고리의 다른 글
| [2025백엔드] 스프링인액션 독서 #6 - 4장. 스프링 시큐리티 1 (4) | 2025.08.04 |
|---|---|
| [2025백엔드] 스프링인액션 독서 #5 - 3장. 데이터로 작업하기 #3 (2) | 2025.08.04 |
| [2025백엔드] 스프링인액션 독서 #3 - 3장.데이터로 작업하기 1 (3) | 2025.07.29 |
| [2025 백엔드] 스프링 인 액션 독서 #2 - 2장. 웹 애플리케이션 개발하기 (7) | 2025.07.24 |
| [2025 백엔드] 도메인과 Model, 도메인 주도 개발 (DDD) (1) | 2025.07.22 |