이번포스팅은 Spring3 + Mybatis 연동에서 INSERT 쿼리 실행 후
시퀀스값을 가져오는 방법에 대해서 포스팅을 해보도록 하겠습니다.
먼저 시퀀스 자동증가를 지원해주는 MySQL,MSSQL 버전에 대하여 예를 들도록 해보겠습니다.
MySQL의 경우는 자동증가 시켜주고자 하는 컬럼에 auto_increment 옵션을 적용해주고
MSSQL의 경우는 IDENTITY(초기값,증가값) 에 대한 옵션을 적용해주면 되겠습니다.
CREATE TABLE increment ( seq bigint(20) NOT NULL PRIMARY KEY AUTO_INCREMENT, title varchar(100) NOT NULL )
MSSQL에 경우는 상단 쿼리에서 AUTO_INCREMENT 를 IDENTITY(1,1)로 변경해주시면 되겠습니다.
제일먼저 컨트롤러에 들어갈 샘플코드입니다.
@RequestMapping("/savedata") public void savedata(){ try { Map<String, Object> map = new HashMap<String, Object>(); map.put("title", "제목입니다."); studyService.savedata(map); } catch (Exception e) { e.printStackTrace(); } }
이어서 Service interface 부분과 ServiceImpl class 부분 샘플 코드입니다.
public void savedata(Map<String, Object> map) throws SQLException;
@Override public void savedata(Map<String, Object> map) throws SQLException { System.out.println("INSERT직전 시퀀스값이 존재하는지:"+map.get("seq")); dao.savedata(map); System.out.println("INSERT직후 시퀀스값이 존재하는지:"+map.get("seq")); }
이어서 Dao interface와 DaoImpl class 부분에 대한 샘플코드입니다.
public Integer savedata(Map<String, Object> map) throws SQLException;
@Override public Integer savedata(Map<String, Object> map) throws SQLException { return query.insert("query.savedata",map); }
마지막으로 Mybatis INSERT 쿼리 xml 코드부분입니다.
<insert id="savedata" parameterType="java.util.Map" useGeneratedKeys="true" keyProperty="seq"> INSERT INTO increment (title) VALUES(#{title}) </insert>
실행결과를 확인 후 각 설명을 드리도록 하겠습니다.
위와같이 "/savedata" URL 을 호출하여 2번에 데이터 insert처리를 하였습니다.
각 설명을 드리겠습니다.
useGeneratedKeys : 사용하는 DB에서 자체적으로 생성한 키(ex : 자동 증가 컬럼)를 받는옵션입니다.
디폴트는 false이므로 자동증가 값을 받고자 할경우 TRUE로 정의합니다.
keyProperty : INSERT/UPDATE 쿼리에만 적용되는 속성이며 return값으로 보내주고자 하는 컬럼명을 정의해 주면 됩니다.
(대신, vo 혹은 map의 key값과 일치하여야 합니다.)
INSERT 후 자동증가값을 RETURN값으로 가져왔으므로 return으로 ServiceImpl 클래스로 보내주도록 합니다.
DaoImpl에서는 Integer 타입을 return 해주었지만 ServiceImpl부분에서는 별도로 return 값을 받지 않습니다.
이유는 자동적으로 dao.savedata(map); 코드에 넘겨준 map타입에
Mybatis에서 자동적으로 return값을 key mapping을 해주어 담아주었기 때문입니다.
두번째 방법은 오라클을 포함한 모든 DBMS(MySQL,MSSQL,Oracle) 에 적용이 가능합니다.
Service / Dao 영역 코드는 첫번째 방법과 동일하며
쿼리xml부분만 SelectKey태그를 이용하여 return값을 보내주는 방식인대
다음처럼 선택하여 적용하시면 되겠습니다.
<insert id="savedata" parameterType="java.util.Map"> INSERT INTO increment (title) VALUES(#{title}) <selectKey keyProperty="seq" resultType="Integer" order="AFTER"> SELECT LAST_INSERT_ID() </selectKey> </insert>
<insert id="savedata" parameterType="java.util.Map"> INSERT INTO increment (title) VALUES(#{title}) <selectKey keyProperty="seq" resultType="Integer" order="AFTER"> SELECT IDENT_CURRENT('increment') </selectKey> </insert>
MSSQL의 경우 IDENT_CURRENT('테이블명')을 작성해주시면 되겠습니다.
<insert id="savedata" parameterType="java.util.Map"> INSERT INTO seq_test(idx,title) VALUES(idx_test_seq.nextval,#{title}) <selectKey keyProperty="seq" resultType="Integer" order="AFTER"> SELECT seq.currval FROM dual </selectKey> </insert>
Oracle의 경우는 seq는 create sequence 로 생성한 시퀀스.currval을 적용해주시면 되겠습니다.
그럼 SelectKey를 이용한 결과값을 확인해 보도록 하겠습니다.
역시 동일하게 결과값이 출력되었습니다.
insert된 데이터의 시퀀스를 가져오는 경우는
보통 다른 테이블에 외래키 insert하기 위해 사용하기 때문에
알아두시면 좋겠습니다.
by 개발로짜
mybatis와 ibatis별 동적태그 비교문 알아보도록 하자 (5) | 2014.11.17 |
---|---|
mybatis와 ibatis 반복문 비교하기(foreach vs iterate) (0) | 2014.11.17 |
우선 mybatis와 ibatis에서는 동적태그를 기본적으로 지원을 합니다.
즉, 프로시저로 짜여져 있는 로직을 동적태그를 사용하여 쿼리로 변경할 수 있습니다.
장점이 있을수도 있지만 자칫 잘못 사용하면 큰 문제를 일으킬수 있다는 단점이있을수 있다는...
양날의 칼날과 같다는것만 알아두시면 되겠습니다.
isNull : "널일경우"
isNotNull : "널이아닐경우"
isEmpty : "공백일경우"
isNotEmpty : "공백이아닐경우"
isGreaterTan : ">"
isGreaterEqual : ">="
isLessThan : "<"
isLessEqual : "<="
isEqual : "=="
isNotEqual : "!="
if : 단일조건문
choose when otherwise : 다중조건문
위와같이 각 mybatis(ibatis) 별 동적태그를 지원합니다.
ibatis에 비해 mybatis의 비교문태그가 간단해졌습니다.
ibatis에서 지원되는 태그들 if문과 choose문만을 이용하여 비교가 가능해 진것이죠.
일반 자바코드와 ibatis/mybatis 별로 비교문 예를 들어보도록 하겠습니다.
if(stringProperty == null) { // code here }
<!--ibatis --> <isNull property="stringProperty"> 조건문 </isNull> <!--mybatis--> <if test="stringProperty == null"> 조건문 </if>
if(stringProperty != null) { // code here }
<!--ibatis --> <isNotNull property="stringProperty"> 조건문 </isNotNull> <!--mybatis(1)--> <if test="stringProperty != null"> 조건문 </if> <!--mybatis(2)--> <choose> <when test="stringProperty == null"> NULL일경우 조건문 </when> <otherwise> NULL이 아닐경우 조건문 </otherwise> </choose>
if(stringProperty.equals("")) { //code here }
<!--ibatis--> <isEmpty property="stringProperty"> 조건문 </isEmpty> <!--mybatis--> <if test="stringProperty == ''"> 조건문 </if>
if(!stringProperty.equals("")) { //code here }
<!--ibatis--> <isNotEmpty property="stringProperty"> 조건문 </isNotEmpty> <!--mybatis(1)--> <if test="stringProperty != ''"> 조건문 </if> <!--mybatis(2)--> <choose> <when test="stringProperty == ''"> 공백일경우 조건문 </when> <otherwise> 공백 아닐경우 조건문 </otherwise> </choose>
if(numberProperty > 5) { //code here }
<!--ibatis--> <isGreaterThan property="numberProperty" compareValue="5"> 5보다 클경우 조건문 </isGreaterThan> <!--mybatis--> <if test='id > 5'> 5보다 클경우 조건문 </if>
if(numberProperty >= 5) { //code here }
<!--ibatis--> <isGreaterEqual property="numberProperty" compareValue="5"> 5보다 크거나같을경우 조건문 </isGreaterEqual> <!--mybatis--> <if test='id >= 5'> 5보다 크거나같을경우 조건문 </if>
if(numberProperty < 5) { //code here }
<!--ibatis--> <isLessThan property="numberProperty" compareValue="5"> 5보다 작을경우 조건문 </isLessThan> <!--mybatis--> <if test='id < 5'> 5보다 작을경우 조건문 </if>
if(numberProperty <= 5) { //code here }
<!--ibatis--> <isLessEqual property="numberProperty" compareValue="5"> 5보다 작거나같을경우 조건문 </isLessEqual> <!--mybatis--> <if test='id <= 5'> 5보다 작거나같을경우 조건문 </if>
if(stringProperty.equals("title")) { //code here }
<!--ibatis--> <isEqual property="stringProperty" compareValue="title"> stringProperty 속성값이 "title"일 경우 </isEqual> <!--mybatis--> <if test='stringProperty == "title"'> stringProperty 속성값이 "title"일 경우 </if>
if(!stringProperty.equals("title")) { //code here }
<!--ibatis--> <isNotEqual property="stringProperty" compareValue="title"> stringProperty 속성값이 "title"이 아닐경우 </isNotEqual> <!--mybatis--> <if test='stringProperty != "title"'> stringProperty 속성값이 "title"이 아닐경우 </if>
마지막으로 다중 조건체크에 대한 예를 들어보도록 하겠습니다.
if(stringProperty != null && !stringProperty.equals("")) { //code here }
<!--ibatis--> <isNotNull property="stringProperty"> <isNotEmpty property="stringProperty"> 조건문 </isNotEmpty> </isNotNull> <!--mybatis--> <if test='stringProperty != null and stringProperty == ""'> stringProperty 속성값이 "title"이 아닐경우 </if>
위처럼 ibatis의 경우에는 태그안에 태그를 여러번 넣어줘야해서 솔직히 번거롭습니다.
하지만 mybatis는 JSTL과 동일한 문법으로 사용이 가능하여
편하게 비교문을 다중조건을 주어서 사용할 수 있습니다.
다만 다른 점이 있다면
&& 문을 and || 문을 or 로 작성 해주셔야 합니다.
by 개발로짜
Spring3 + Mybatis 연동 후 DBMS 종류별(MySQL,MSSQL,Oracle) 데이터 insert 후 시퀀스 가져오기 (0) | 2014.11.19 |
---|---|
mybatis와 ibatis 반복문 비교하기(foreach vs iterate) (0) | 2014.11.17 |
Mybatis와 ibatis의 반복문에 대해서 알아보도록 하겠습니다.
보통 SQL 쿼리에서 IN절에 사용되는 방법입니다.
기본적으로 한 종류의 타입의 리스트 객체를 이용합니다.
Mybatis와 ibatis 태그를 나누어서 사용방법을 포스팅하겠습니다.
기본 ibatis 연동법에서 POM.XML의 IBATIS 관련 DEPENDENCY 설정부분을 빼고
포스팅을 하였습니다.
2014/11/17 - [개발에필요한연동법/스프링연동] - Spring3 + ibatis(아이바티스) 연동해보고 쿼리결과값 콘솔에 출력해보기
pom.xml에 추가해주실 DEPENDENCY 부분은 다음과 같습니다.
<dependency> <groupId>org.apache.ibatis</groupId> <artifactId>ibatis-sqlmap</artifactId> <version>2.3.4.726</version> </dependency> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring-framework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring-framework.version}</version> </dependency>
샘플테이블은 MySQL의 information_schema DB의 'TABLES' 테이블 기준으로 설명드리도록 하겠습니다.
※ 해당 샘플을 따라해보시려면 application-config.xml파일내에 존재하는
datasource태그의 url 값의 db명을 "information_schema"로 변경하시면 되겠습니다.
@RequestMapping("/list") public void list(){ try { Map<String, Object> hmap = new HashMap<String, Object>(); ArrayList<String> dbList = new ArrayList<String>(); dbList.add("mysql"); dbList.add("test"); hmap.put("dbList", dbList); studyDao.list(hmap); } catch (Exception e) { e.printStackTrace(); } }
public void list(Map<String, Object> hmap) throws SQLException;
@Override public void list(Map<String, Object> hmap) throws SQLException { query.selectList("query.list",hmap); }
@Override public void list(Map<String, Object> hmap) throws SQLException { query.queryForList("query.list",hmap); }
위코드를 보시면 DaoImpl에서 별도로 return 을 해주지 않았습니다.
그 이유는 단순하게 IN절내에 정상적인 Parameter값들이 들어가는지
쿼리로그로 확인을 하기위하여 별도의 return 타입을 작성하지 않았습니다.
마지막으로 Mybatis(foreach 태그)와 IBATIS(iterate 태그) 별 쿼리 XML 태그는 다음과 같습니다.
<select id="list" parameterType="java.util.Map" resultType="java.util.Map"> SELECT * FROM TABLES WHERE TABLE_SCHEMA IN <foreach item="item" index="index" collection="dbList" open="(" close=")" separator=","> #{item} </foreach> </select>
<select id="list" parameterClass="java.util.Map" resultClass="com.spring.study.vo.ListVo"> SELECT table_name FROM TABLES WHERE TABLE_SCHEMA IN <iterate property="dbList" open="(" close=")" conjunction=","> #dbList[]# </iterate> </select>
mybatis의 경우는 collection에 넘겨준 단일타입의 List객체명을 작성해주시면 되겠으며
ibatis의 경우는 property에 넘겨준 단일타입 List 객체명을 작성해주시면됩니다.
실행을 해보도록 하겠습니다.
List객체로 넘긴 Parameter가 정상적으로 구분자를 통하여 IN PARAMETER에 넘어왔으면
총 28개의 결과값을 출력한 것을 확인 할 수 있었습니다.
※ ibatis의 경우는 별도의 로그가 출력되지 않을것입니다.
에러가 안나면 정상적으로 쿼리조회가 완료 된것이므로 신경쓰지 않으셔도 되겠습니다.
mybatis처럼 resultClass를 Map타입으로 받아오지 못하는 관계로
임의로 VO 객체를 RESULTCLASS로 받게끔 처리해두었습니다.
by 개발로짜
Spring3 + Mybatis 연동 후 DBMS 종류별(MySQL,MSSQL,Oracle) 데이터 insert 후 시퀀스 가져오기 (0) | 2014.11.19 |
---|---|
mybatis와 ibatis별 동적태그 비교문 알아보도록 하자 (5) | 2014.11.17 |