참고 Source : pro25
Spring에서는 트랜잭션 기능을 마이바티스 기능과 연동해서 사용하게된다
1. XML을 사용하는 법
2. annotation으로 사용하는법
트랜잭션은 여러개의 DML 명령문을 하나의 논리적인 작업 단위로 묶어서 관리하는것.
All or Nothing 방식으로 작업 단위가 처리된다. SQL문이 정상적으로 전부 처리된다면
데이터베이스에 commit되지만, 하나라도 잘못된것이 있다면 취소 즉 rollback되게 된다.
ex) 은행에서 이체작업을 할때에 A가 B에게 이체를 할때에 한곳에서 잘못된다면
원래대로 돌아와야 정상적인 은행이체작업이될것이다.
//action-mybatis.xml
//DataSourceTransactionManager 클래스를 사용해서 dataSource빈엥 트랜잭션 적용
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
//annotaion을 사용하여 트랜잭션 적용하기 위해 txManager 빈 설정
<tx:annotation-driven transaction-manager="txManager" />
대부분의 어플리케이션에서는 Service 클래스에 트랜잭션을 적용하게된다
//AccountService.java
@Transactional(propagation=Propagation.REQUIRED)
//클래스의 모든 메서드의 트랜잭션 적용
public class AccountService{
private AccountDAO accDAO;
//setter 구현
public void setAccDAO(AccountDAO accDAO){
this.accDAO = accDAO;
}
public void sendMoney() throws Exception{
accDAO.updateBalance1();
accDAO.updateBalance2();
}
}
<context:component-scan base-package="패키지이름" />
위 의 방법으로 사용하면 애플리케이션 실행시 해당 패키지에서 애너테이션으로 지정된 클래스를 빈으로 만들어준다. 아래의 것들은 스프링 컨테이너가 component-scan에 의해 지정한 클래스를 변환하는것이다.
1. @Controller : 지정한 클래스를 컨트롤러빈으로 자동 변환합니다
2. @Service : 지정한 클래스를 서비스빈으로 자동 변환합니다
3. @Repository : 지정한 클래스를 DAO빈으로 자동 변환합니다
4. @Component : 지정한 클래스를 빈으로 자동 변환합니다
//action-servlet.xml
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/test/" />
<property name="suffix" value=".jsp"/>
</bean>
<!-- 클래스 레벨에 @RequestMapping을 처리 -->
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<!-- 메서드 레벨에 @RequestMapping을 처리 -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
<!-- 애너테이션이 적용되도록 설정-->
<context:component-scan base-package="com.spring" />
//MainController.java
//bean의 id가 loginController이다
@Controller("loginController")
public class LoginController {
@RequestMapping(value = {"/test/loginForm.do", "/test/lgoinForm2.do"}, method={RequestMethod.GET})
public ModelAndView loginForm(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView mav = new ModelAndView();
mav.setViewName("loginForm");
return mav;
}
@RequestMapping(value = {"/test/login.do"}, method={RequestMethod.GET, RequestMethod.POST})
public ModelAndView login(HttpServletRequest request, HttpServletResponse response) throws Exception {
System.out.println("나왔다");
request.setCharacterEncoding("utf-8");
ModelAndView mav = new ModelAndView();
mav.setViewName("result");
String userID = request.getParameter("userID");
String userName = request.getParameter("uesrName");
mav.addObject("userID", userID);
mav.addObject("userName", userName);
return mav;
}
}
//loginForm.jsp
...
<tr>
<td>아이디 <input type="text" name="userID" size="10"></td>
</tr>
<tr>
<td>이름 <input type="text" name="userName" size="10"></td>
</tr>
...
//LoginController.java
@RequestMapping(value = "/test/login2.do", method = {RequestMethod.GET, RequestMethod.POST})
public ModelAndView login2(@RequestParam("userID") String userID, @RequestParam("userName") String userName,
HttpServletRequest request, HttpServletResponse response) throws Exception {
request.setCharacterEncoding("utf-8");
ModelAndView mav = new ModelAndView();
mav.setViewName("result");
System.out.println("userID: " + userID);
System.out.println("userName: " + userName);
mav.addObject("userID", userID);
mav.addObject("userName", userName);
return mav;
}
//LoginController.java
@RequestMapping(value = "/test/login3.do", method = {RequestMethod.GET, RequestMethod.POST})
public ModelAndView login3(@RequestParam Map<String, String> info,
HttpServletRequest request, HttpServletResponse response) throws Exception {
request.setCharacterEncoding("utf-8");
ModelAndView mav = new ModelAndView();
String userID = info.get("userID");
String userName = info.get("userName");
System.out.println("userID: " + userID);
System.out.println("userName: " + userName);
mav.addObject("info", info);
mav.setViewName("result");
return mav;
}
//result.jsp
<h1>아이디 : ${info.userID></h1>
<h1>이름 : ${info.userName></h1>
@RequestMapping(value = "/test/login4.do", method = {RequestMethod.GET, RequestMethod.POST})
public ModelAndView login4(@ModelAttribute("info") LoginVO loginVO,
HttpServletRequest request, HttpServletResponse response) throws Exception {
request.setCharacterEncoding("utf-8");
ModelAndView mav = new ModelAndView();
System.out.println("userID: " + loginVO.getUserID());
System.out.println("userName: " + loginVO.getUserName());
mav.setViewName("result");
return mav;
}
@RequestMapping(value = "/test/login5.do", method = {RequestMethod.GET, RequestMethod.POST})
public String login5(Model model,
HttpServletRequest request, HttpServletResponse response) throws Exception {
request.setCharacterEncoding("utf-8");
model.addAttribute("userID", "hong");
model.addAttribute("userName", "홍길동");
return "result";
}
XML에서 빈을 주입해주려면 XML 파일이 복잡해진다는 단점이있다.
그래서 @Autowired를 사용하면 그 기능을 annotation으로 자동으로 수행할수있다.
또한 setter를 사용하지않아도 속성에 빈을 주입할수있다.
//web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/config/action-mybatis.xml
//action-service.xml 제외
</param-value>
</context-param>
//action-mybatis.xml
<bean id="sqlSession"
class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
</bean>
<!-- DAO 클래스는 자바코드에서 annotation으로 설정
<bean id="memberDAO"
class="com.spring.member.dao.MemberDAOImpl">
<property name="sqlSession" ref="sqlSession"></property>
</bean>
-->
//memberController.java
@Controller("memberController")
public class MemberControllerImpl implements MemberController {
@Autowired
private MemberService memberService;
@Autowired
MemberVO memberVO;
@Override
@RequestMapping(value="/member/listMembers.do" ,method = RequestMethod.GET)
public ModelAndView listMembers(HttpServletRequest request, HttpServletResponse response) throws Exception {
String viewName = getViewName(request);
List membersList = memberService.listMembers();
ModelAndView mav = new ModelAndView(viewName);
mav.addObject("membersList", membersList);
return mav;
}
}
//memberDAO.java
@Repository("memberDAO")
public class MemberDAOImpl implements MemberDAO {
//id가 sqlSession인것 자동 주입
@Autowired
private SqlSession sqlSession;
}
//memberService.java
@Service("memberService")
@Transactional(propagation=Propagation.REQUIRED)
public class MemberServiceImpl implements MemberService{
//memberDAO 자동 주입
@Autowired
private MemberDAO memberDAO;
}
//memverVO.java
@Component("memberVO")
public class MemberVO {
}