Mybatis Transactional 2015 Web Service Computing Mybatis pom
Mybatis, Transactional 2015 Web Service Computing
Mybatis pom. xml에 dependency 추가 <!– Spring jdbc --> <dependency> <group. Id>org. springframework</group. Id> <artifact. Id>spring-jdbc</artifact. Id> <version>4. 2. 0. RELEASE</version> </dependency> <!-- Apache Commons --> <dependency> <group. Id>commons-dbcp</group. Id> <artifact. Id>commons-dbcp</artifact. Id> <version>1. 4</version> </dependency> <!-- My. SQL Connector --> <dependency> <group. Id>mysql</group. Id> <artifact. Id>mysql-connector-java</artifact. Id> <version>5. 1. 34</version> </dependency> <!-- My. Batis --> <dependency> <group. Id>org. mybatis</group. Id> <artifact. Id>mybatis</artifact. Id> <version>3. 2. 8</version> </dependency> <dependency> <group. Id>org. mybatis</group. Id> <artifact. Id>mybatis-spring</artifact. Id> <version>1. 2. 2</version> </dependency> 3
Mybatis /src/resources/common에 mybatis. xml 추가 <? xml version="1. 0" encoding="UTF-8"? > <!DOCTYPE configuration PUBLIC "-//mybatis. org//DTD Config 3. 0//EN" "http: //mybatis. org/dtd/mybatis-3 -config. dtd"> <configuration> <settings> <setting name="map. Underscore. To. Camel. Case" value="true" /> </settings> </configuration> spring 설정 파일에 다음과 같이 추가 <bean id="data. Source" class="org. apache. commons. dbcp. Basic. Data. Source" destroy-method="close"> <property name="driver. Class. Name" value="${jdbc. driver. Class. Name}" /> <property name="url" value="${jdbc. url}" /> <property name="username" value="${jdbc. username}" /> <property name="password" value="${jdbc. password}" /> </bean> <!-- My. Batis --> <mybatis: scan base-package="koreatech. cse. repository" /> <bean id="sql. Session. Factory" class="org. mybatis. spring. Sql. Session. Factory. Bean"> <property name="data. Source" ref="data. Source" /> <property name="config. Location" value="classpath: mybatis. xml" /> </bean> 4
Mybatis config. properties에 다음과 같이 추가(Data. Source 정보) jdbc. driver. Class. Name = com. mysql. jdbc. Driver jdbc. url = jdbc: mysql: //localhost: 3306/wsc? character. Encoding=utf 8&use. Unicode=true&mysql. Encoding=utf 8 jdbc. username = root jdbc. password = 비밀번호 koreatech. cse. repository 패키지 생성 후 User. Mapper. java 다음과 같이 생성 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 User. Mapper { @Insert("INSERT INTO USERS (NAME, EMAIL, PASSWORD, AGE) VALUES (#{name}, #{email}, #{password}, #{age})") @Select. Key(statement = "SELECT LAST_INSERT_ID()", key. Property = "id", before=false, result. Type = int. class) void insert(User user); @Update("UPDATE USERS SET NAME = #{name}, EMAIL = #{email}, PASSWORD = #{password}, AGE = #{age} WHERE ID = #{id}") void update(User user); @Select("SELECT * FROM USERS WHERE ID = #{id}") User find. One(@Param("id") int id); @Delete("DELETE FROM USERS WHERE ID = #{id}") void delete(@Param("id") int id); } 5
Mybatis spring 설정 파일에 다음과 같이 추가 <tx: annotation-driven proxy-target-class="true" /> <bean id="transaction. Manager" class="org. springframework. jdbc. datasource. Data. Source. Transaction. Manager"> <property name="data. Source" ref="data. Source" /> </bean> – 참고: proxy-target-class=“true”: Spring에서는 interface기반의 다이나믹 프록시를 지원하는데 interface를 사용하지 않고 구체 클래스에 직접 트랜잭션을 적용하려 면 위와 같이 설정해준다. 9
Transaction @Transactional 어노테이션은 컨트롤러나 서비스, 메소드 레벨에 적 용시킬 수 있다. 임의로 오류를 발생시키는 코드를 작성해보자. 아래 코드를 실행 후 데이터베이스에 값이 삽입되었는지 확인해보 자. @Transactional @Request. Mapping(value="/signup", method= Request. Method. POST) @Response. Body public String signup(@Model. Attribute User user, Binding. Result result) { user. Mapper. insert(user); double i = 3 / 0; System. out. println("i = " + i); System. out. println("user = " + user); return "success"; } 10
동적 SQL 경우에 따라 SQL문을 동적으로 처리해야 할 경우가 있다. 첫번째 방법은 Sql. Provider와 Sql. Builder를 이용하여 Java에서 동적 으로 SQL을 생성하는 방법이다. 예) 동적으로 Select문을 구성할 때는 @Select. Provider 어노테이션 을 이용한다. 그 외 @Update. Provider, @Insert. Provider, @Delete. Provider가 있다. User. Mapper. java @Select. Provider(type = User. Sql. Provider. class, method = "find. All. By. Provider") List<User> find. By. Provider(Searchable searchable); 12
동적 SQL 동적 쿼리를 위한 객체 Searchable. java public class Searchable { private String name; private String email; private String order. Param; public String get. Name() { return name; } public void set. Name(String name) { this. name = name; } public String get. Email() { return email; } public void set. Email(String email) { this. email = email; } public String get. Order. Param() { return order. Param; } public void set. Order. Param(String order. Param) { this. order. Param = order. Param; } } 13
동적 SQL 동적 쿼리를 작성하는 객체 koreatech. cse. repository. provider. User. Sql. Provider. java package koreatech. cse. repository. provider; import koreatech. cse. domain. Searchable; import org. apache. ibatis. jdbc. SQL; public class User. Sql. Provider { public String find. All. By. Provider(final Searchable searchable) { return new SQL() { SELECT("*"); FROM("USERS"); if(searchable. get. Name() != null) { WHERE("NAME = #{name}"); if(searchable. get. Email() != null) { OR(); WHERE("EMAIL = #{email}"); } if(searchable. get. Order. Param() != null) { ORDER_BY(searchable. get. Order. Param() + " DESC"); } }. to. String(); } } 14
동적 SQL 동적 쿼리를 위한 Controller 수정 koreatech. cse. controller. User. Controller. java @Request. Mapping(value = "/list", method = Request. Method. GET) public String list(Model model, @Request. Param(required=false) String name, @Request. Param(required=false) String email, @Request. Param(required=false) String order) { Searchable searchable = new Searchable(); searchable. set. Name(name); searchable. set. Email(email); searchable. set. Order. Param(order); model. add. Attribute("users", user. Mapper. find. By. Provider(searchable)); return "list"; } view를 통한 확인 /WEB-INF/views/list. jsp <%@ page content. Type="text/html; charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http: //java. sun. com/jsp/jstl/core" %> <html> <head> <title>Edit</title> </head> <body> Search Users By Sql Provider<br/> <c: for. Each var="u" items="${users}"> ${u}<br/> </c: for. Each> </body> </html> 15
동적 SQL User. Controller와 User. Mapper는 자신에게 어떤 쿼리가 올지 모르는 상태이 다. 동적 SQL을 활용해 유저의 URL요청에 따라 동적으로 대응을 하여 보여줄 수 있다. 다음과 같은 주소로 테스트 해보자. – http: //localhost: 8080/user/list? name=admin&email=user 1@email. com&order=age – http: //localhost: 8080/user/list? name=admin 16
동적 SQL 두번째 방법은 스크립트형식의 쿼리를 작성하는 것이다. Mybatis는 JSTL과 비슷한 형식의 스크립트를 제공한다. 앞서 User. Sql. Provider와 비슷한 동작을 하는 스크립트는 다음과 같다. User. Mapper. java @Select("<script>" + "SELECT * FROM USERS" + "<if test='name != null'> WHERE NAME = #{name}</if>" + "<if test='name != null and email != null'> OR EMAIL = #{email}</if>" + "<if test='order. Param != null'>ORDER BY ${order. Param} DESC</if>" + "</script>") List<User> find. By. Script(Searchable searchable); 추가) 리스트와 같은 형식을 for문으로 동적으로 추가하고자 할 때는 아래와 같이 활용할 수 있다. @Select("<script>" + "SELECT * FROM USERS" + "<if test='string. List != null and !string. List. empty'> WHERE NAME IN <foreach item='item' collection='string. List' open='(' separator=', ' close=')'>#{item}</foreach></if>" + "</script>") List<User> find. By. List(@Param("string. List") List<String> string. List); 17
동적 SQL 즉, String param = “AGE”; 일 때 최종 쿼리는 아래와 같으며, 2)는 오류가 발 생한다. 1) SELECT * FROM USERS ORDER BY AGE; @Select(“SELECT * FROM USERS ORDER BY ${param}") List<User> find. By. String(@Param(“param") String param); 2) SELECT * FROM USERS ORDER BY ‘AGE’; @Select(“SELECT * FROM USERS ORDER BY #{param}") List<User> find. By. String(@Param(“param") String param); 19
- Slides: 19