Mybatis, Transactional

Similar presentations


Presentation on theme: "Mybatis, Transactional"— Presentation transcript:

1 Mybatis, Transactional
2015 Web Service Computing

2 Mybatis iBatis Mybatis
SQL에 기반한 데이터베이스와 자바, 닷넷(.NET), 루비(Ruby) 등을 연결시켜 주는 역할. JDBC를 대체하는 영속성 프레임워크(Persistence Framework)이다. 소스코드에서 SQL 문장을 분리하여 별도의 XML 파일로 저장하고 이 둘을 연결시켜주는 방식으로 작동한다 Mybatis 아파치 소프트웨어 재단의 iBatis개발자팀이 구글 코드로 이전하기로 결정하고 구글 코드에서 새로이 만들어지는 이름이 MyBatis로 변경 되었다. MyBatis는 개발자가 지정한 SQL, 저장프로시저, 그리고 몇가지 고급 매핑을 지원하는 퍼시스턴스 프레임워크이다. MyBatis는 JDBC 코드와 수동으로 셋팅하는 파라미터와 결과 매핑을 제거한다. MyBatis는 데이터베이스 레코드에 원시타입과 Map 인터페이스 그리고 자바 POJO를 설정하고 매핑하기 위해 XML과 애노테이션을 사용할 수 있다.

3 Mybatis pom.xml에 dependency 추가 <!– Spring jdbc -->
<groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.2.0.RELEASE</version> </dependency> <!-- Apache Commons --> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> <!-- MySQL Connector --> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.34</version> <!-- MyBatis --> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.8</version> <artifactId>mybatis-spring</artifactId> <version>1.2.2</version>

4 Mybatis /src/resources/common에 mybatis.xml 추가 spring 설정 파일에 다음과 같이 추가
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" " <configuration> <settings> <setting name="mapUnderscoreToCamelCase" value="true" /> </settings> </configuration> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> <!-- MyBatis --> <mybatis:scan base-package="koreatech.cse.repository" /> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:mybatis.xml" />

5 Mybatis config.properties에 다음과 같이 추가(DataSource 정보)
koreatech.cse.repository 패키지 생성 후 UserMapper.java 다음과 같이 생성 jdbc.driverClassName = com.mysql.jdbc.Driver jdbc.url = jdbc:mysql://localhost:3306/wsc?characterEncoding=utf8&useUnicode=true&mysqlEncoding=utf8 jdbc.username = root jdbc.password = 비밀번호 package koreatech.cse.repository; import koreatech.cse.domain.User; import org.apache.ibatis.annotations.*; import org.springframework.stereotype.Component; import org.springframework.stereotype.Repository; @Repository public interface UserMapper { @Insert("INSERT INTO USERS (NAME, , PASSWORD, AGE) VALUES (#{name}, #{ }, #{password}, #{age})") @SelectKey(statement = "SELECT LAST_INSERT_ID()", keyProperty = "id", before=false, resultType = int.class) void insert(User user); @Update("UPDATE USERS SET NAME = #{name}, = #{ }, PASSWORD = #{password}, AGE = #{age} WHERE ID = #{id}") void update(User user); @Select("SELECT * FROM USERS WHERE ID = #{id}") User int id); @Delete("DELETE FROM USERS WHERE ID = #{id}") void int id); }

6 Mybatis @Insert Mysql insert문 @Update Mysql update문 @Select
Mysql select문 @Delete Mysql delete문 @SelectKey statement: 방금 삽입한 id를 가져오기 위한 문구 keyProperty: ID 프로퍼티 resultType: 결과값 형태 @Param - 매퍼 메서드가 여러개의 파라미터를 가진다면, 이 어노테이션은 이름에 일치하는 매퍼 메서드 파라미터에 적용된다. - 반면에 여러개의 파라미터는 순서대로 명명된다. 예를 들어, #{param1}, #{param2} 등이 기본이다. 를 사용하면, 파라미터는 #{person} 으로 명명된다.

7 Transaction Transaction이란? A가 B에게 금액을 이체하는 상황을 보자.
데이터베이스 내에서 한꺼번에 수행되어야할 일련의 연산들 DB와 JAVA 언어가 데이터를 주고 받는 과정에 원자성을 부여하는 수단 트랜잭션의 모든 연산들은 한꺼번에 모두 완료되거나 그렇지 않으면 모두 취소되어야 한다. A가 B에게 금액을 이체하는 상황을 보자. 1. A의 계좌에서 잔액을 –한다. 2. B의 계좌에 잔액을 +한다. 만약 1.과 2.의 사이에서 오류가 발생한다면?

8 Transaction Transaction기술은 하나의 커넥션에서 autoCommit을 해제하고 수동으로 제어하는 기술이다.
즉 이용자가 직접 쿼리 결과를 컨트롤할 수 있는 기술이다. Commit(커밋) : 해당 Connection의 요청을 완료하고 특별한 에러가 없다면 결과를 DB에 반영한다.  RollBack(롤백) : 해당 Connection 수행 중 예기치 않은 에러가 발생하였다면 모든 과정을 취소하고 DB를 Connection이 수행되기 이전상태로 변경한다. 어노테이션을 이용하여 간단하게 자동으로 적용할 수 있다.

9 Mybatis spring 설정 파일에 다음과 같이 추가
참고: proxy-target-class=“true”: Spring에서는 interface기반의 다이나믹 프록시를 지원하는데 interface를 사용하지 않고 구체 클래스에 직접 트랜잭션을 적용하려면 위와 같이 설정해준다. <tx:annotation-driven proxy-target-class="true" /> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean>

10 Transaction @Transactional 어노테이션은 컨트롤러나 서비스, 메소드 레벨에 적용시킬 수 있다.
임의로 오류를 발생시키는 코드를 작성해보자. 아래 코드를 실행 후 데이터베이스에 값이 삽입되었는지 확인해보자. @Transactional @RequestMapping(value="/signup", method= RequestMethod.POST) @ResponseBody public String User user, BindingResult result) { userMapper.insert(user); double i = 3 / 0; System.out.println("i = " + i); System.out.println("user = " + user); return "success"; }

11 실습 CRUD(Create, Read, Update, Delete)에 대한 각각의 URL을 구성하고 테스트 해보시오. URL
메소드 설명 view /user/signup GET 회원 가입 폼 양식 표시 signup.jsp POST 회원 가입, 성공하면 /user/list로 이동 /user/list 유저 목록을 테이블로 보여주는 화면 list.jsp /user/edit 특정 ID를 가지는 유저를 수정할 수 있는 화면 /user/signup과 거의 동일하나 특정 ID를 가지는 유저 정보가 미리 폼에 입력되어 있다 edit.jsp 특정 ID를 가지는 유저를 수정한 결과를 받아 데이터베이스에서 업데이트 업데이트 후 /user/list 로 이동 /user/delete 특정 ID를 가지는 유저를 삭제할 수 있는 URL 삭제 후 /user/list로 이동

12 동적 SQL 경우에 따라 SQL문을 동적으로 처리해야 할 경우가 있다.
첫번째 방법은 SqlProvider와 SqlBuilder를 이용하여 Java에서 동적으로 SQL을 생성하는 방법이다. 예) 동적으로 Select문을 구성할 어노테이션을 이용한다. @DeleteProvider가 있다. UserMapper.java @SelectProvider(type = UserSqlProvider.class, method = "findAllByProvider") List<User> findByProvider(Searchable searchable);

13 동적 SQL 동적 쿼리를 위한 객체 Searchable.java public class Searchable {
private String name; private String ; private String orderParam; public String getName() { return name; } public void setName(String name) { this.name = name; public String get () { return ; public void set (String ) { this. = ; public String getOrderParam() { return orderParam; public void setOrderParam(String orderParam) { this.orderParam = orderParam;

14 동적 SQL 동적 쿼리를 작성하는 객체 koreatech.cse.repository.provider.UserSqlProvider.java package koreatech.cse.repository.provider; import koreatech.cse.domain.Searchable; import org.apache.ibatis.jdbc.SQL; public class UserSqlProvider { public String findAllByProvider(final Searchable searchable) { return new SQL() { { SELECT("*"); FROM("USERS"); if(searchable.getName() != null) { WHERE("NAME = #{name}"); if(searchable.get () != null) { OR(); WHERE(" = #{ }"); } if(searchable.getOrderParam() != null) { ORDER_BY(searchable.getOrderParam() + " DESC"); }.toString();

15 동적 SQL 동적 쿼리를 위한 Controller 수정 view를 통한 확인
koreatech.cse.controller.UserController.java @RequestMapping(value = "/list", method = RequestMethod.GET) public String list(Model String String String order) { Searchable searchable = new Searchable(); searchable.setName(name); searchable.set ( ); searchable.setOrderParam(order); model.addAttribute("users", userMapper.findByProvider(searchable)); return "list"; } /WEB-INF/views/list.jsp page contentType="text/html;charset=UTF-8" language="java" %> taglib prefix="c" uri=" %> <html> <head> <title>Edit</title> </head> <body> Search Users By Sql Provider<br/> <c:forEach var="u" items="${users}"> ${u}<br/> </c:forEach> </body> </html>

16 동적 SQL UserController와 UserMapper는 자신에게 어떤 쿼리가 올지 모르는 상태이다.
동적 SQL을 활용해 유저의 URL요청에 따라 동적으로 대응을 하여 보여줄 수 있다. 다음과 같은 주소로 테스트 해보자.

17 동적 SQL 두번째 방법은 스크립트형식의 쿼리를 작성하는 것이다.
Mybatis는 JSTL과 비슷한 형식의 스크립트를 제공한다. 앞서 UserSqlProvider와 비슷한 동작을 하는 스크립트는 다음과 같다. 추가) 리스트와 같은 형식을 for문으로 동적으로 추가하고자 할 때는 아래와 같이 활용할 수 있다. UserMapper.java @Select("<script>" + "SELECT * FROM USERS" + "<if test='name != null'> WHERE NAME = #{name}</if>" + "<if test='name != null and != null'> OR = #{ }</if>" + "<if test='orderParam != null'>ORDER BY ${orderParam} DESC</if>" + "</script>") List<User> findByScript(Searchable searchable); @Select("<script>" + "SELECT * FROM USERS" + "<if test='stringList != null and !stringList.empty'> WHERE NAME IN <foreach item='item' collection='stringList' open='(' separator=',' close=')'>#{item}</foreach></if>" + "</script>") List<User> List<String> stringList);

18 동적 SQL 이 때, #{string}와 ${string}의 차이는? #{string}은 SQL에서 ‘값’으로써 인식된다.
즉, SELECT * FROM USERS WHERE ID = #{id} 와 같이 해당 컬럼(ID)의 값으로 사용될 때 쓰인다. ${string}은 직접적인 쿼리 그 자체로써 인식된다. 만약 String string = “SELECT * FROM USERS WHERE ID > 0”; 과 같은 쿼리가 있다면 다음과 같이 바로 사용할 수도 있다. @Select("${string}") List<User> String string);

19 동적 SQL 즉, String param = “AGE”; 일 때 최종 쿼리는 아래와 같으며, 2)는 오류가 발생한다.
1) SELECT * FROM USERS ORDER BY AGE; 2) SELECT * FROM USERS ORDER BY ‘AGE’; @Select(“SELECT * FROM USERS ORDER BY ${param}") List<User> String param); @Select(“SELECT * FROM USERS ORDER BY #{param}") List<User> String param);


Download ppt "Mybatis, Transactional"
Ads by Google