이번포스팅은 Spring3 + Mybatis 연동에서 INSERT 쿼리 실행 후시퀀스값을 가져오는 방법에 대해서 포스팅을 해보도록 하겠습니다.먼저 시퀀스 자동증가를 지원해주는 MySQL,MSSQL 버전에 대하여 예를 들도록 해보겠습니다.MySQL의 경우는 자동증가 시켜주고자 하는 컬럼에 auto_increment 옵션을 적용해주고MSSQL의 경우는IDENT..
질문)팝업창에서 데이터 처리후 해당값을 부모창에 넘겨주는 것을 만드는데요. 공통팝업이다보니, 호출이 필요한 화면에서는 호출될 동일한 메소드명을 만들고 해당 팝업은 그냥 그 메소드명을 호출하는것으로 처리하려는데, 해당 메소드들을 못찾습니다.. 어떻게 해야 팝업 윈도우에서 부모 창의 메소드를 호출할수 있을까요? (--> 팝업창의 gr..
우선 mybatis와 ibatis에서는 동적태그를 기본적으로 지원을 합니다.즉, 프로시저로 짜여져 있는 로직을 동적태그를 사용하여 쿼리로 변경할 수 있습니다.장점이 있을수도 있지만 자칫 잘못 사용하면 큰 문제를 일으킬수 있다는 단점이있을수 있다는...양날의 칼날과 같다는것만 알아두시면 되겠습니다. ibatis 비교문 지원 태그 isNull :"널일경우"is..
이번포스팅은 Spring3 + Mybatis 연동에서 INSERT 쿼리 실행 후
시퀀스값을 가져오는 방법에 대해서 포스팅을 해보도록 하겠습니다.
먼저 시퀀스 자동증가를 지원해주는 MySQL,MSSQL 버전에 대하여 예를 들도록 해보겠습니다.
MySQL의 경우는 자동증가 시켜주고자 하는 컬럼에 auto_increment 옵션을 적용해주고
MSSQL의 경우는 IDENTITY(초기값,증가값) 에 대한 옵션을 적용해주면 되겠습니다.
1 2 3 4 | CREATE TABLE increment ( seq bigint (20) NOT NULL PRIMARY KEY AUTO_INCREMENT, title varchar (100) NOT NULL ) |
MSSQL에 경우는 상단 쿼리에서 AUTO_INCREMENT 를 IDENTITY(1,1)로 변경해주시면 되겠습니다.
제일먼저 컨트롤러에 들어갈 샘플코드입니다.
1 2 3 4 5 6 7 8 9 10 | @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 부분 샘플 코드입니다.
1 | public void savedata(Map<String, Object> map) throws SQLException; |
1 2 3 4 5 6 | @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 부분에 대한 샘플코드입니다.
1 | public Integer savedata(Map<String, Object> map) throws SQLException; |
1 2 3 4 | @Override public Integer savedata(Map<String, Object> map) throws SQLException { return query.insert( "query.savedata" ,map); } |
마지막으로 Mybatis INSERT 쿼리 xml 코드부분입니다.
1 2 3 | < 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값을 보내주는 방식인대
다음처럼 선택하여 적용하시면 되겠습니다.
1 2 3 4 5 6 | < 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 > |
1 2 3 4 5 6 | < 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('테이블명')을 작성해주시면 되겠습니다.
1 2 3 4 5 6 7 | < 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 |
질문) 팝업창에서 데이터 처리후 해당값을 부모창에 넘겨주는 것을 만드는데요.
공통팝업이다보니, 호출이 필요한 화면에서는 호출될 동일한 메소드명을 만들고 해당 팝업은 그냥 그 메소드명을 호출하는것으로 처리하려는데,
해당 메소드들을 못찾습니다..
어떻게 해야 팝업 윈도우에서 부모 창의 메소드를 호출할수 있을까요?
(--> 팝업창의 grid 선택하고 적용버튼 누름, 해당 grid 를 넘겨서.. 선택된 row 의 값들을 각 화면에서 처리하는것입니다.)
답변) 위에 대한 내용만으로는 어떠한 결과를 원하시는지 이해가 되지 않아 2가지 경우를 예를들어 답변드리도록 하겠습니다.
1 2 | < div id = "panel1" ></ div > < div id = "panel2" ></ div > |
제일먼저 임의의 폼패널 2개를 생성하기 위하여 각각 div 2개를 작성하였습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | Ext.onReady( function (){ Ext.create( "Ext.form.Panel" ,{ renderTo : document.getElementById( "panel1" ), title : '주소검색 샘플예제(1)' , width: 600, items : [{ fieldLabel: '우편번호' , name : 'zipcode' , xtype : 'textfield' , },{ fieldLabel: '기본주소' , name : 'default_address' , xtype : 'textfield' },{ fieldLabel: '상세주소' , name : 'detail_address' , xtype : 'textfield' }], fbar : [{ xtype : 'button' , text : '검색' , handler : function (btn){ if (Ext.getCmp( "addrWindow" ) == undefined) { showWindow(btn); } } }] }); Ext.create( "Ext.form.Panel" ,{ renderTo : document.getElementById( "panel2" ), title : '주소검색 샘플예제(2)' , width: 600, items : [{ fieldLabel: '우편번호' , name : 'zipcode' , xtype : 'textfield' , },{ fieldLabel: '기본주소' , name : 'default_address' , xtype : 'textfield' },{ fieldLabel: '상세주소' , name : 'detail_address' , xtype : 'textfield' }], fbar : [{ xtype : 'button' , text : '검색' , handler : function (btn){ if (Ext.getCmp( "addrWindow" ) == undefined) { showWindow(btn); } } }] }) }) function showWindow(btn){ Ext.create( 'Ext.window.Window' ,{ id : 'addrWindow' , width : 700, height : 300, title : '주소검색창' , items : [{ xtype : 'grid' , columns : [{ text : '우편번호' , flex : 1, dataIndex : 'zipcode' },{ text : '주소' , flex : 1, dataIndex : 'address' }], store : Ext.create( "Ext.data.Store" ,{ fields : [ 'zipcode' , 'address' ], data : [{ zipcode : '111-222' , address : '서울 종로구 삼청동' },{ zipcode : '333-444' , address : '경기 안양시 만안동' },{ zipcode : '333-454' , address : '경기 광주시 태전종' }], proxy : { type : 'memory' } }) }], fbar : [{ xtype : 'button' , text : '적용' , handler : function (btn2){ var gridObj = Ext.getCmp( "addrWindow" ).down( "grid" ); var selectgrid = gridObj.getSelectionModel().getSelection()[0]; var zipcode = selectgrid.get( "zipcode" ); var address = selectgrid.get( "address" ); var zipcodeObj = btn.up( "form" ).down( "textfield[name=zipcode]" ) var addressObj = btn.up( "form" ).down( "textfield[name=default_address]" ) //부모창 호출함수 setPanel(gridObj,zipcode,address,zipcodeObj,addressObj); } }] }).show(); } function setPanel(obj,zipcode,address,parent_zipcode,parent_address){ parent_zipcode.setValue(zipcode); parent_address.setValue(address); obj.up( "window" ).close(); } |
showWindow() 함수
그리드패널을 자식컴포넌트로 가지는 윈도우 컴포넌트를 폼패널의 검색버튼 클릭시 화면에 출력시키며
윈도우화면의 적용버튼 클릭시 선택된 그리드 ROW의 각 값을 setPanel 함수로 보내주는 기능을 가진
컴포넌트출력 + 기능함수입니다.
setPanel() 함수
각 선택된 값들을 폼패널의 입력컴포넌트에 대입을 하며
윈도우창을 CLOSE 해주는 기능을 가진 함수입니다.
실행을 해보도록 하겠습니다.
우선 요청 주셨던 함수 하나로 검색버튼 위치에 따라
그리드내에 선택값이 해당 폼필드로 적용되는것을 확인 할 수 있습니다.
1 2 3 4 | < form action = "/전송URL" method = "post" name = "frm" > 우편번호 : < input type = "text" name = "zipcode" />< input type = "button" onclick = "popuptest()" value = "검색" />< br /> 기본주소 : < input type = "text" name = "default_address" />< br /> </ form > |
위와같이 일반 HTML 소스코드 작성후 FUNCTION 2개를 SCRIPT 태그내에 정의합니다.
1 2 3 4 5 6 7 | function popuptest(){ window.open( "/pop.html" , "test" , "'scrollbars=yes,toolbar=yes,resizable=yes,width=500,height=500,left=0,top=0" ); } function setadderss(zipcode,address) { document.frm.zipcode.value = zipcode; document.frm.default_address.value = address; } |
window.open으로 호출해준 pop.html 페이지다 하단 스크립트 코드를 적용합니다.
※ 부모창에는 ExtJS 연동을 할필요가 없으므로 ExtJS 관련 CSS 및 JS 파일을 INCLUDE 할 필요가 없습니다.
대신 WINDOW.OPEN 호출한 pop.html 파일에는 ExtJS관련 파일들을 include 해주어야 합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | Ext.onReady( function (){ Ext.create( 'Ext.panel.Panel' ,{ renderTo : Ext.getBody(), title : '그리드샘플' , width : 500, height : 500, items : [{ xtype : 'grid' , columns : [{ text : '우편번호' , flex : 1, dataIndex : 'zipcode' },{ text : '주소' , flex : 1, dataIndex : 'address' }], store : Ext.create( "Ext.data.Store" ,{ fields : [ 'zipcode' , 'address' ], data : [{ zipcode : '111-222' , address : '서울 종로구 삼청동' },{ zipcode : '333-444' , address : '경기 안양시 만안동' },{ zipcode : '333-454' , address : '경기 광주시 태전종' }], proxy : { type : 'memory' } }) }], fbar : [{ xtype : 'button' , text : '적용' , handler : function (btn){ var gridObj = btn.up( "panel" ).down( "grid" ); var selectgrid = gridObj.getSelectionModel().getSelection()[0]; var zipcode = selectgrid.get( "zipcode" ); var address = selectgrid.get( "address" ); opener.setadderss(zipcode,address); self.close(); } }] }) }) |
실행결과를 보도록 하겠습니다.
위처럼 정상적으로 팝업창의 선택 그리드 ROW 값이 부모입력화면에 대입이 되었습니다.
by 개발로짜
"ExtJS_OS" 님께서 질문주신 dataview 관련 답변 코드 입니다. (0) | 2014.11.14 |
---|
우선 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 별로 비교문 예를 들어보도록 하겠습니다.
1 2 3 | if (stringProperty == null ) { // code here } |
1 2 3 4 5 6 7 8 | <!--ibatis --> < isNull property = "stringProperty" > 조건문 </ isNull > <!--mybatis--> < if test = "stringProperty == null" > 조건문 </ if > |
1 2 3 | if (stringProperty != null ) { // code here } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <!--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 > |
1 2 3 | if (stringProperty.equals( "" )) { //code here } |
1 2 3 4 5 6 7 8 | <!--ibatis--> < isEmpty property = "stringProperty" > 조건문 </ isEmpty > <!--mybatis--> < if test = "stringProperty == ''" > 조건문 </ if > |
1 2 3 | if (!stringProperty.equals( "" )) { //code here } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <!--ibatis--> < isNotEmpty property = "stringProperty" > 조건문 </ isNotEmpty > <!--mybatis(1)--> < if test = "stringProperty != ''" > 조건문 </ if > <!--mybatis(2)--> < choose > < when test = "stringProperty == ''" > 공백일경우 조건문 </ when > < otherwise > 공백 아닐경우 조건문 </ otherwise > </ choose > |
1 2 3 | if (numberProperty > 5 ) { //code here } |
1 2 3 4 5 6 7 8 | <!--ibatis--> < isGreaterThan property = "numberProperty" compareValue = "5" > 5보다 클경우 조건문 </ isGreaterThan > <!--mybatis--> < if test='id > 5'> 5보다 클경우 조건문 </ if > |
1 2 3 | if (numberProperty >= 5 ) { //code here } |
1 2 3 4 5 6 7 8 | <!--ibatis--> < isGreaterEqual property = "numberProperty" compareValue = "5" > 5보다 크거나같을경우 조건문 </ isGreaterEqual > <!--mybatis--> < if test='id >= 5'> 5보다 크거나같을경우 조건문 </ if > |
1 2 3 | if (numberProperty < 5 ) { //code here } |
1 2 3 4 5 6 7 8 | <!--ibatis--> < isLessThan property = "numberProperty" compareValue = "5" > 5보다 작을경우 조건문 </ isLessThan > <!--mybatis--> < if test = 'id < 5' > 5보다 작을경우 조건문 </ if > |
1 2 3 | if (numberProperty <= 5 ) { //code here } |
1 2 3 4 5 6 7 8 | <!--ibatis--> < isLessEqual property = "numberProperty" compareValue = "5" > 5보다 작거나같을경우 조건문 </ isLessEqual > <!--mybatis--> < if test = 'id <= 5' > 5보다 작거나같을경우 조건문 </ if > |
1 2 3 | if (stringProperty.equals( "title" )) { //code here } |
1 2 3 4 5 6 7 8 | <!--ibatis--> < isEqual property = "stringProperty" compareValue = "title" > stringProperty 속성값이 "title"일 경우 </ isEqual > <!--mybatis--> < if test = 'stringProperty == "title"' > stringProperty 속성값이 "title"일 경우 </ if > |
1 2 3 | if (!stringProperty.equals( "title" )) { //code here } |
1 2 3 4 5 6 7 8 | <!--ibatis--> < isNotEqual property = "stringProperty" compareValue = "title" > stringProperty 속성값이 "title"이 아닐경우 </ isNotEqual > <!--mybatis--> < if test = 'stringProperty != "title"' > stringProperty 속성값이 "title"이 아닐경우 </ if > |
마지막으로 다중 조건체크에 대한 예를 들어보도록 하겠습니다.
1 2 3 | if (stringProperty != null && !stringProperty.equals( "" )) { //code here } |
1 2 3 4 5 6 7 8 9 10 | <!--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 |
내 블로그 - 관리자 홈 전환 |
Q
Q
|
---|---|
새 글 쓰기 |
W
W
|
글 수정 (권한 있는 경우) |
E
E
|
---|---|
댓글 영역으로 이동 |
C
C
|
이 페이지의 URL 복사 |
S
S
|
---|---|
맨 위로 이동 |
T
T
|
티스토리 홈 이동 |
H
H
|
단축키 안내 |
Shift + /
⇧ + /
|
* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.