☆ 전체 소스 : spring305.zip

 

 

BoardVO.java 

package sp.mvc.board.vo;

 

public class BoardVO {

 private int boardSeq;
 private String boardType;
 private int step;
 private int depth;
 private String title;
 private String content;
 private String ip;
 private String deleteYn;
 private String regiDt;
 private String regiUser;
 private String modiDt;
 private String modiUser;
 
 public int getBoardSeq() {
  return boardSeq;
 }
 public void setBoardSeq(int boardSeq) {
  this.boardSeq = boardSeq;
 }

         ......


 @Override
 public String toString() {
  return "BoardVO [boardSeq=" + boardSeq + ", boardType=" + boardType
    + ", step=" + step + ", depth=" + depth + ", title=" + title
    + ", content=" + content + ", ip=" + ip + ", deleteYn="
    + deleteYn + ", regiDt=" + regiDt + ", regiUser=" + regiUser
    + ", modiDt=" + modiDt + ", modiUser=" + modiUser + "]";
 }
} 

 

BoardDaoImpl.java

package sp.mvc.board.dao;

import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;
import sp.mvc.board.vo.BoardVO;

 

public class BoardDaoImpl extends SqlMapClientDaoSupport implements BoardDao {

 

 @Override
 public BoardVO getBoardDetail(int boardSeq) {
  // TODO Auto-generated method stub
  BoardVO boardDetail = (BoardVO)getSqlMapClientTemplate().queryForObject("board.selectBoardDetail", boardSeq);
  
  return boardDetail;
 }

 

 @Override
 public Object insertBoardItem(BoardVO boardVo) {
  // TODO Auto-generated method stub
  return getSqlMapClientTemplate().insert("board.insertBoard", boardVo);
 }

}

 

BoardServiceImpl.java

package sp.mvc.board.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import sp.mvc.board.dao.BoardDao;
import sp.mvc.board.vo.BoardVO;

 

@Component
public class BoardServiceImpl implements BoardService {

 

 @Autowired
 private BoardDao boardDao;
 
 @Override
 public BoardVO getBoardDetail(int boardSeq) {
  // TODO Auto-generated method stub
  return boardDao.getBoardDetail(boardSeq);
 }

 

 @Override
 public Object insertBoardItem(BoardVO boardVo) {
  // TODO Auto-generated method stub
  return boardDao.insertBoardItem(boardVo);
 }

}

 

BoardController.java

package sp.mvc.board.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import sp.mvc.board.service.BoardService;
import sp.mvc.board.vo.BoardVO;

 

@Controller
public class BoardController {
 
 @Autowired
 private BoardService boardService;
 
 @RequestMapping("/boardDetail.sp") 
 public ModelAndView getDetail(@RequestParam(value="seq", required=false, defaultValue="1") int boardSeq){
  System.out.println("boardSeq : " + boardSeq);
  BoardVO boardDetail = boardService.getBoardDetail(boardSeq);
  
  System.out.println("boardDetail : " + boardDetail.toString());

  
  ModelAndView modelAndView = new ModelAndView("board/boardDetail");
  modelAndView.addObject("boardDetail", boardDetail);
  return modelAndView;
 }
  
 @RequestMapping("/boardInsert.sp")

 @Transactional(propagation=Propagation.REQUIRED, rollbackFor={Exception.class})
 public void insertItem(){
  
  BoardVO boardVo1 = new BoardVO();
  boardVo1.setBoardSeq(1);          //무결성 Exception

  boardVo1.setBoardType("001");
  boardVo1.setStep(1);
  boardVo1.setTitle("spring 3.0 mvc - 1");
  boardVo1.setContent("컨텐츠 내용 입력... 테스트 중...");
  boardVo1.setIp("123.123.321.321");
    
  BoardVO boardVo2 = new BoardVO();
  boardVo2.setBoardSeq(2148);
  boardVo2.setBoardType("001");
  boardVo2.setStep(1);
  boardVo2.setTitle("spring 3.0 mvc - 1");
  boardVo2.setContent("컨텐츠 내용 입력... 테스트 중...");
  boardVo2.setIp("123.123.321.321");
    
  System.out.println("===== 1 =====");
  boardService.insertBoardItem(boardVo2);
  System.out.println("===== 2 =====");
  boardService.insertBoardItem(boardVo1);   //무결성 제약 조건 Exception 발생
  System.out.println("===== 3 =====")


 }
}

boardVo2 : 정상적으로 insert가 되는 param값을 가지고 있음

  boardVo1 : boaerSeq가 무결성 제약 조건에 위배되는 값을 가지고 있음

 

◆ 트랜잭션이 설정되어 있지 않다면 위의 경우 boardVo2는 정상적으로 insert가 되고(commit) boardVo1의 경우 Exception 발생 ==>> 하지만 트랜잭션을 설정함으로써 정상적으로 데이터가 들어가는 boardVo2의 경우도 boardVo1의 Exception으로 인해 rollback이 됨

 

 

LogAspect.java

package sp.mvc.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

 

@Aspect
public class LogAspect {

 

 @Pointcut(value="execution(* sp.mvc.board.controller.*.*(..))")
 public void logPrint(){};
 
 
 @AfterThrowing(pointcut="logPrint()", throwing="ex")
 public void afterThrowing(JoinPoint joinPoint, Exception ex){
  System.out.println("***** afterThrowing *****");
  System.out.println("method : " + joinPoint.toShortString());
  System.out.println("Exception : " + ex.toString());
 }
}

 

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:p="http://www.springframework.org/schema/p"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd">

 
 <!-- 1. dataSource 생성 -->
 <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="driverClassName" value="oracle.jdbc.OracleDriver"></property>
  <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"></property>
  <property name="username" value="ADMIN"></property>
  <property name="password" value="GUEST"></property>
 </bean>

 


 <!-- transactionManager -->
 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource"></property>
 </bean>

 

 

 <!-- 2. ibatis 코딩을 지원해주는 SqlMapClient 빈 생성 -->
 <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
  <property name="dataSource" ref="dataSource"></property>
  <property name="configLocation" value="/WEB-INF/SqlMapConfig.xml"></property>
 </bean>


 <!-- 3. 공통 빈 생성 -->
 
 
</beans>

 

pjt_main_config.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:p="http://www.springframework.org/schema/p"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
 
 <context:annotation-config/>
 <aop:aspectj-autoproxy/>
 <context:component-scan base-package="sp.mvc.board.service"/>
 <context:component-scan base-package="sp.mvc.board.dao"/> 
 <context:component-scan base-package="sp.mvc.board.controller"/>

 
 <!-- bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" p:alwaysUseFullPath="true"/ -->
 <!-- bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" p:alwaysUseFullPath="true"/ --> 
 
  
 <!-- ViewResolver 설정 -->
 <bean id="beanNameViewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver" p:order="1"/>
 
 <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"
  p:order="2" p:prefix="/WEB-INF/jsp/" p:suffix=".jsp"></bean>

 


 <!-- aop - transaction -->
 <tx:annotation-driven transaction-manager="transactionManager"/>
 
 
 <!-- aop - log -->
 <bean id="logAspect" class="sp.mvc.aop.LogAspect"></bean>
 
 
 <!-- 각종 bean 설정 -->
 <bean id="boardDao" class="sp.mvc.board.dao.BoardDaoImpl">
  <property name="sqlMapClient" ref="sqlMapClient"></property>
 </bean>
 
</beans>

<tx:annotation-driven transaction-manager="transactionManager"/> 대신 아래의 빈을 등록해도 됨

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/> 

 

 

board.xml

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE sqlMap     
    PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"     
    "http://ibatis.apache.org/dtd/sql-map-2.dtd">

 

<!-- Mapper 파일 -->

<!--
 이름 충돌을 방지하기 위해 namespace를 사용
 SqlMapConfig.xml에 <settings useStatementNamespaces="true"/> 설정이 지정되어 있는 경우
 sql구문을 찾을 때 반드시 namespace값을 포함해야 한다.
-->

<sqlMap namespace="board">

 <resultMap id="r_boardVo" class="sp.mvc.board.vo.BoardVO">
  <result property="boardSeq" column="BOARD_SEQ"/>
  <result property="boardType" column="BOARD_TYPE"/>
  <result property="step" column="STEP"/>
  <result property="title" column="TITLE"/>
  <result property="content" column="CONTENT" jdbcType="CLOB"/>
  <result property="ip" column="IP"/>
  <result property="deleteYn" column="DELETE_YN"/>
  <result property="regiDt" column="REGI_DT"/>
  <result property="regiUser" column="REGI_USER"/>
  <result property="modiDt" column="MODI_DT"/>
  <result property="modiUser" column="MODI_USER"/>
  <result property="depth" column="DEPTH"/>
 </resultMap>


 <select id="selectBoardDetail" parameterClass="int" resultMap="r_boardVo">
  <![CDATA[
  SELECT  BOARD_SEQ, BOARD_TYPE, STEP, TITLE, CONTENT, IP, DELETE_YN,
    TO_CHAR(REGI_DT, 'YYYY-MM-DD') AS REGI_DT, REGI_USER,
    TO_CHAR(MODI_DT, 'YYYY-MM-DD') AS MODI_DT, MODI_USER, DEPTH
  FROM BOARD
  WHERE BOARD_SEQ = #value#
  ]]>
 </select>

 


   <parameterMap id="p_in_boardVo" class="sp.mvc.board.vo.BoardVO">
    <parameter property="boardSeq"/>
    <parameter property="boardType"/>
    <parameter property="step"/>
    <parameter property="title"/>
    <parameter property="content" jdbcType="CLOB"/>
    <parameter property="ip"/>
   </parameterMap>

   <insert id="insertBoard" parameterMap="p_in_boardVo">
    INSERT
    INTO BOARD(BOARD_SEQ, BOARD_TYPE, STEP, TITLE, CONTENT, IP, DELETE_YN, REGI_DT, REGI_USER, MODI_DT, MODI_USER)
  VALUES(?, ?, ?, ?, ?, ?, 'N', SYSDATE, 'ADMIN', SYSDATE, 'ADMIN')
   </insert>
 
</sqlMap>

 

 

결과

요청 URL

   http://localhost:8090/spring305/boardInsert.sp

 

===== 1 =====
===== 2 =====
***** afterThrowing *****
method : execution(BoardController.insertItem())
Exception : org.springframework.dao.DuplicateKeyException: SqlMapClient operation; SQL [];  
--- The error occurred in /query/board/board.xml. 
--- The error occurred while applying a parameter map. 
--- Check the board.p_in_boardVo. 
--- Check the statement (update failed). 
--- Cause: java.sql.SQLException: ORA-00001: 무결성 제약 조건(ANGELOS1981.PK_BOARD)에 위배됩니다
; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException:  
--- The error occurred in /query/board/board.xml. 
--- The error occurred while applying a parameter map. 
--- Check the board.p_in_boardVo. 
--- Check the statement (update failed). 
--- Cause: java.sql.SQLException: ORA-00001: 무결성 제약 조건(ANGELOS1981.PK_BOARD)에 위배됩니다

 

 

 

+ Recent posts