중소기업직업훈련컨소시엄 Spring & Ibatis 프레임워크과정 11.8.27 ~ 11.10.15 한국소프웨어기술진흥협회 (KOSTA) 1
Web Application 설계방식 모델 1 설계방식 모델 2 설계방식 2
모델 1 설계방식 (1/2) 모델 1 개요 JSP 만이용하여개발하는경우 JSP + Java Bean을이용하여개발하는경우 Model2의 Controller 개념이모호 1. Request Browser(Client) 4. Response JSP 2. JavaBean 호출 3. 자원사용 JavaBean Application Server Resource 3
모델 1 설계방식 (2/2) 모델 1 의장단점 장점 개발속도가빠름 개발자의기술적인숙련도가낮아도배우기쉬워빠르게적용가능 단점 JSP 페이지에서프레젠테이션로직과비즈니스로직이혼재되어복잡 로직의혼재로인해개발자와디자이너의작업분리가어려움 JSP 코드의복잡도로인해유지보수가어려워짐 웹애플리케이션이복잡해지고사용자요구가증가함에따라새로운개발방식을요구 4
모델 2 설계방식 (1/2) 모델 2 개요 GUI 개발모델인 MVC 를웹애플리케이션에적용하여구현한방식 Application 의역할을 Model View Controller 로분리 Model: Business Logic 을담당한다. Java Bean 으로구현 Business Service(Manager) Business Logic 의 workflow 를관리 DAO (Data Access Object) Database 와연동하는 Business Logic 을처리. View: Client 에게응답을처리한다. JSP 로구현 Controller: 클라이언트의요청을받아 Model과 View사이에서일의흐름을조정한다. -Servlet으로구현 Client 의요청을받아 Client 가보낸 Data 를읽고검사한다. Model에게 Business Logic을요청한다. Model의처리결과에맞는 View에게응답을요청한다. 1. Request <<Controller>> Servlet 2. instantiate BROWSER 4. Forward 5. Response <<View>> JSP <<Model>> JavaBean 3. 자원사용 Application Server Resource 5
모델 2 설계방식 (2/2) 모델 2 의장단점 장점 비즈니스로직과프리젠테이션의분리로인해어플리케이션이명료해지며유지보수와확장이용이함 디자이너와개발자의작업을분리해줌 단점 개발초기에아키텍처디자인을위한시간의소요로개발기간이늘어남 MVC 구조에대한개발자들의이해가필요함 6
Spring framework 7
Spring 이란? 오픈소스프레임워크 Rod Johnson 창시 Expert one-on-one J2EE Design - Development, 2002, Wrox Expert one-on-one J2EE Development without EJB, 2004, Wrox 엔터프라이즈어플리케이션개발의복잡성을줄여주기위한목적 EJB 사용으로수행되었던모든기능을일반 POJO(Plain Old Java Object) 를사용해서가능하게함. 경량컨테이너 (light weight container) www.springframework.org 주요개념 의존성주입 (lightweight dependency injection) 관점지향컨테이너 (aspect-oriented container) 8
Spring 장점 경량컨테이너 객체의라이프사이클관리, JEE 구현을위한다양한 API제공 DI (Dependency Injection) 지원 AOP (Aspect Oriented Programming) 지원 POJO (Plain Old Java Object) 지원 JDBC를위한다양한 API 지원 Transaction 처리를위한일관된방법제공 다양한 API와의연동지원 9
Spring Container 설치 스프링커뮤니티사이트http://www.springsource.org/ 다운로드 http://www.springsource.org/download spring-framework-2.5.6.sec01-with-dependencies.zip 을다운받는다. 10
Spring IDE 이클립스에설정및사용 (1/2) 상단메뉴 : help-install new software update site : http://springide.org/updatesite core, Extensions 체크한뒤설치한다. 11
Spring IDE 이클립스에설정및사용 (1/2) Project 생성 오른마우스메뉴 -Spring Tools-Add Spring Project Nature 선택 12
Dependency Injection ( 의존성주입 ) 13
의존성주입 (Dependency Injection, DI) 의존관계주입 (dependency injection) 객체간의의존관계를객체자신이아닌외부의조립기가수행한다. 제어의역행 (inversion of control, IoC) 이라는의미로사용되었음. Martin Fowler, 2004 제어의어떠한부분이반전되는가라는질문에 의존관계주입 이라는용어를사용 복잡한어플리케이션은비즈니스로직을수행하기위해서두개이상의클래스들이서로협업을하면서구성됨. 각각의객체는협업하고자하는객체의참조를얻는것에책임성이있음. 이부분은높은결합도 (highly coupling) 와테스트하기어려운코드를양산함. DI를통해시스템에있는각객체를조정하는외부개체가객체들에게생성시에의존관계를주어짐. 즉, 의존이객체로주입됨. 객체가협업하는객체의참조를어떻게얻어낼것인가라는관점에서책임성의역행 (inversion of responsibility) 임. 느슨한결합 (loose coupling) 이주요강점 객체는인터페이스에의한의존관계만을알고있으며, 이의존관계는구현클래스에대한차이를모르는채서로다른구현으로대체가가능 의존관계주입 DAO1 Service 의존관계주입 DAO2 14
Spring 의 DI 지원 Spring Container 가 DI 조립기를제공 스프링설정파일을통하여객체간의의존관계를설정한다. Spring Container 가제공하는 api 를이용해객체를사용한다. 15
Spring 설정파일 Application 에서사용할 Spring 자원들을설정하는파일 Spring container 는설정파일에설정된내용을읽어 Application 에서필요한기능들을제공한다. XML 기반으로작성한다. Root tag 는 <beans> 이다 파일명은상관없다. 예 ) applicationcontext.xml <?xml version="1.0" encoding="utf-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> </beans> 16
Bean 객체주입받기 설정파일설정 (1/2) 주입할객체를설정파일에설정한다. <bean> : 스프링컨테이너가관리할 Bean 객체를설정 기본속성 name : 주입받을곳에서호출할이름설정 id : 주입받을곳에서호출할이름설정 ( / 값으로못가짐 ) class : 주입할객체의클래스 factory-method : Singleton 패턴으로작성된객체의 factory 메소드호출시 <?xml version="1.0" encoding="utf-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> </beans> <bean id= dao class= spring.di.model.memberdao /> 17
Bean 객체주입받기 설정 Bean 사용 (2/2) 설정파일에설정한 bean 을 Container 가제공는주입기역할 api 를통해주입받는다. public static void main(string [] args){ } // 설정파일이어디있는지를저장하는객체 Resource resource = new ClassPathResource("applicationContext.xml"); // 객체를생성해주는 factory 객체 BeanFactory factory = new XmlBeanFactory(resource); // 설정파일에설정한 <bean> 태그의 id/name 을통해객체를받아온다. MemberDAO dao = (MemberDAO)factory.getBean("dao"); 18
DI 관련주요클래스 (1/2) Spring Container : 객체를관리하는컨테이너. 다음아래의 interface 들을구현한다. <<interface>> BeanFactory 빈객체를관리하고각빈객체간의의종관계를설정해주는기능을제공. 가장단순한컨테이너구현클래스 : XmlBeanFactory <<interface>> ApplicationContext BeanFactory 기능에다양한추가기능을제공. 추가기능 : AOP, 메시지지원, 국제화지원등주요구현클래스 : ClassPathXmlApplicationContext FileSystemXmlApplicationContext <<interface>> WebApplicationContext Web application 용 ApplicationContext. Web Application 당하나씩생성된다. 주요구현클래스 : XmlWebApplicationContext 19
DI 관련주요클래스 (2/2) Resource 구현클래스 Resource interface : 다양한종류의자원을동일한방식으로통일하여표현할수있게한다. XmlBeanFactory 는객체생성시설정파일의위치를알려줘야한다. Resource 를이용 주요구현클래스 org.springframework.core.io.filesystemresource 파일시스템의특정파일의자원을관리 org.springframework.core.io.classpathresource 클래스패스에있는자원을관리 org.springframework.web.context.support.servletcontextresource 웹어플리케이션의 Root 경로를기준으로지정한경로의자원을관리 InputStreamResource, PortletContextResource 예 ) Resource resource = new ClassPathResource("applicationContext.xml"); BeanFactory factory = new XmlBeanFactory(resource); 20
설정을통한객체주입 Constructor 를이용 (1/4) 객체또는값을생성자를통해주입받는다. <constructor-arg> : <bean> 의하위태그로설정한 bean 객체또는값을생성자를통해주입하도록설정 설정방법 : <ref>,<value> 와같은하위태그를이용하여설정, 속성을이용해설정 하위태그이용 <ref bean= bean name /> - 객체를주입시 <value> 값 </value> - 문자 (String), Primitive data 주입시 속성이용 type 속성 : 값을 1 차로 String 으로처리한다. 값의타입을명시해야하 는경우사용. ex) <value type= int >10</value> ref= bean 이름 value= 값 21
설정을통한객체주입 Constructor 를이용 (2/4) 값을주입받을객체 package vo; public class Person{ private String id, private String name, private int age; } public Person(String id){...} public Person(String id, String name){ } public Person(int age){ } //1번생성자 //2번생성자 //3번생성자 1 번생성자에주입예 <bean id= person class= vo.person > <constructor-arg> <value>abcde</value> </constructor-arg> </bean> 또는 <bean id= person class= vo.person > <constructor-arg value= abc /> </bean> 22
설정을통한객체주입 Constructor 를이용 (3/4) 2 번생성자에주입예 <bean id= person class= vo.person > <constructor-arg> <value>abcde</value> </constructor-arg> <constructor-arg> <value>hong Gil Dong</value> </constructor-arg> </bean> 또는 <bean id= person class= vo.person > <constructor-arg value= abc /> <constructor-arg value= Hong Gil Dong /> </bean> 3 번생성자에주입예 <bean id= person class= vo.person > <constructor-arg> <value type= int >30</value> </constructor-arg> </bean> 또는 <bean id= person class= vo.person > <constructor-arg value= abc type= int /> <constructor-arg value= Hong Gil Dong /> </bean> 23
설정을통한객체주입 Constructor 를이용 (4/4) bean 객체를주입 값을주입받을객체 public class BusinessService{ private Dao dao = null; public BusinessService(Dao dao){ this.dao = dao; } } <bean id= dao class= spring.di.model.oracledao /> <bean id= service class= spring.di.model.service.businessservice > <constructor-arg> <ref bean = dao /> </constructor-arg> </bean> 또는 <bean id= service class= spring.di.model.service.businessservice > <constructor-arg ref= dao > </bean> 24
설정을통한객체주입 Property 를이용 (1/5) property 를통해객체또는값을주입받는다.- setter 메소드 주의 : setter를통해서는하나의값만받을수있다. <property> : <bean> 의하위태그로설정한 bean 객체또는값을 property를통해주입하도록설정 속성 : name 값을주입할 property 이름 (setter 의이름 ) 설정방법 <ref>,<value> 와같은하위태그를이용하여설정 속성을이용해설정 xml namespace 를이용하여설정 25
설정을통한객체주입 Property 를이용 (2/5) 하위태그를이용한설정 <ref bean= bean name /> - 객체를주입시 <value> 값 </value> - 문자 (String) Primitive data 주입시 속성이용 type 속성 : 값의타입을명시해야하는경우사용. ref= bean 이름 value= 값 XML Namespace 를이용 <beans> 태그의스키마설정에 namespace 등록 xmlns:p="http://www.springframework.org/schema/p <bean> 태그에속성으로설정 기본데이터주입 : p:propertyname= value. ex)<bean p:id> bean 주입 : p:propertyname-ref= bean_id ex)<bean p:dao-ref= dao > 26
설정을통한객체주입 Property 를이용 (3/5) Primitive Data Type 주입 값을주입받을객체 package spring.vo; public class Person{ private String id, private String name, private int age; public void setid(string id) { } public void setname(string name) { } public void setage(int age) { } <bean id= person class= vo.person > <property name="name"> <value>hong</value> </property> <property name="id" value="abcde"/> <property name="age" value="20"/> </bean> 27
설정을통한객체주입 Property 를이용 (4/5) Bean 객체주입 값을주입받을객체 public class BusinessService{ private Dao dao = null; public setdao(dao dao){ } } <bean id= dao class= spring.di.model.oracledao /> <bean id= service class= spring.di.model.service.businessservice > <property name= dao > <ref bean = dao /> </property > </bean> 또는 <bean id= service class= spring.di.model.service.businessservice > < property name= dao ref= dao > </bean> 28
설정을통한객체주입 Property 를이용 (5/5) XML Namespace 를이용한주입 값을주입받을객체 public class BusinessService{ private Dao dao = null; private int waitingtime = 0; public setdao(dao dao){ } public setwaitingtime(int wt){ } } <?xml version="1.0" encoding="utf-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd" xmlns:p="http://www.springframework.org/schema/p" > <bean id= dao class= spring.di.model.oracledao /> <bean id="person" class="vo.person" p:waitingtime= 20 p:dao-ref= dao"/> </beans> 29
Collection 객체주입하기 (1/5) <property> 또는 <constructor-arg> 의하위태그로 Collection 값을설정하는태그를이용해값주입설정 설정태그 태그 Collection 종류설명 <list> java.util.list List 계열컬렉션값목록전달 <set> java.util.set Set 계열컬렉션값목록전달 <map> java.util.map Map계열컬렉션에 keyvalue 의값목록전달 <props> java.util.properties Properties 에 key(string)- value(string) 의값목록전달 Collection에값을설정하는태그 <ref> : <bean> 으로등록된객체 <value> : 기본데이터 <bean> : 임의의 bean <list>,<map>,<props>, <set> : 컬랙션 <null> : null 30
Collection 객체주입하기 (2/5) <list> List 계열컬렉션이나배열에값들을넣기. <ref>, <value> 태그를이용해값설정 <ref bean= bean_id /> : bean 객체 list 에추가 <value [type= type ]> 값 </value> : 문자열 (String), Primitive 값 list 에추가 public void setmylist(list list){ } <bean id= otherbean class= vo.otherbean /> <bean id= mybean class= vo.myvo > <property name= mylist > <list> <value>10</value> ->String으로저장됨 <value type= java.lang.integer >20</value> ->Integer 로저장됨 <ref bean= otherbean /> </list> </property> </bean> 31
Collection 객체주입하기 (3/5) <map> Map 계열의 Collection 에객체들을넣기 속성 : key-type, value-type : key 와 value 의타입을고정시킬경우사용 <entry> 를이용해 key-value 를 map 에등록 속성 key, key-ref : key 설정 value, value-ref : 값설정 public void setmymap(map map){ } <bean id= otherbean class= vo.otherbean /> <bean id= mybean class= vo.myvo > <property name= mymap > <map> <entry key= id value= abc /> <entry key= other value-ref= otherbean /> </map> </property> </bean> 32
Collection 객체주입하기 (4/5) <props> java.util.properties 값 ( 문자열 ) 을넣기 <prop> 를이용해 key-value 를 properties 에등록 속성 key : key 값설정 값은태그사이에넣는다. : <prop key= id >abcde</prop> public void setjdbcproperty (Properties props){ } <bean id= mydao class= vo.dao > <property name= jdbcproperty > <props> <prop key= driver >JDBC Driver</prop> <prop key= url >jdbc:url://127.0.0.1/mydb</prop> <prop key= user >dbuser</prop> <prop key= pwd >dbpassword</prop> </props> </property> </bean> 33
Collection 객체주입하기 (5/5) <set> java.util.set 에객체를넣기 속성 : value-type : value 타입설정 <value>, <ref> 를이용해값을넣는다. public void setmyset(set props){ } <bean id= otherbean class= vo.otherbean /> <bean id= mybean class= vo.bean > <property name= myset> <set> <value>10</value> <value>20<value> <ref bean= otherbean /> </set> </property> </bean> 34
Bean 객체의생성단위 (1/2) BeanFactory 를통해 Bean 을요청시객체생성의범위 ( 단위 ) 를설정 <bean> 의 scope 속성을이용해설정 scope 의값 값 singleton 컨테이너는하나의빈객체만생성한다. - default prototype 빈을요청할때마다생성한다. request session global-session Http 요청마다빈객체생성 HttpSession 마다빈객체생성 글로벌 http 세션에대해빈객체생성 - 포틀릿관련 request, session 은 WebApplicationContext 에서만적용가능 35
빈 (bean) 생성제어 (2/2) 빈 (bean) 범위지정 singleton 과 prototype <bean id= dao class= dao.oracledao scope= prototype /> prototype은 Spring 어플리케이션컨텍스트에서 getbean으로빈 (bean) 을사용시마다새로운인스턴스를생성함. singleton 은 Spring 어플리케이션컨텍스트에서 getbean 으로빈 (bean) 을사용시동일한인스턴스를생성함. 36
빈 (bean) 생성제어 (3/3) Factory 메소드로부터빈 (bean) 생성 public class OracleDAO{ private OracleDAO() {} private static OracleDAO instance; public static OracleDAO getinstance(){ if(instance==null) instance = new OracleDAO(); return instance; } } Singleton 클래스는 static factory 메소드를통해서인스턴스생성이가능하면단하나의인스턴스만을생성함. <bean id= dao class= OracleDAO factory-method= getinstance /> * 주 : getbean() 으로호출시 private 생성자도호출하여객체를생성한다. 그러므로위의상황에서 factory 메소드로만호출해야객체를얻을수있는것은아니다. 37
Spring AOP 38
Spring AOP 개요 (1/2) 핵심관심사항 (core concern) 과공통관심사항 (cross-cutting concern) 기존 OOP 에서는공통관심사항을여러모듈에서적용하는데중복된코드를양산과같은한계가존재 - 이를극복하기위해 AOP 가등장 Aspect Oriented Programming은문제를해결하기위한핵심관심사항과전체에적용되는공통관심사항을기준으로프로그래밍함으로써공통모듈을손쉽게적용할수있게해준다. 39
Spring AOP 개요 (2/2) 핵심관심사항 : CourseService, StudentService, MiscService 공통관심사항 : Security, Transactions, Other - 핵심관심사항에공통관심사항을어떻게적용시킬것인가 40
Spring AOP 용어 Aspect - 여러객체에서공통으로적용되는공통관심사항 (ex: 트랜잭션, 로깅, 보안 ) JoinPoint Aspect가적용될수있는지점 (ex: 메소드, 필드 ) Pointcut 공통관심사항이적용될 Joinpoint Advice 어느시점 (ex: 메소드수행전 / 후, 예외발생후등 ) 에어떤공통관심기능 (Aspect) 을적용할지정의한것. Weaving 어떤 Advice를어떤 Pointcut( 핵심사항 ) 에적용시킬것인지에대한설정 (Advisor) 41
Spring 에서 AOP 구현방법 AOP 구현의세가지방법 POJO Class를이용한 AOP구현 스프링 API를이용한 AOP구현 어노테이션 (Annotation) 을이용한 AOP 구현 42
POJO 기반 AOP 구현 XML 스키마확장기법을통해설정파일을작성한다. POJO 기반 Advice 클래스작성 43
POJO 기반 AOP 구현 - 설정파일작성 (1/5) XML 스키마를이용한 AOP 설정 aop 네임스페이스와 XML 스키마추가 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> </beans> 44
POJO 기반 AOP 구현 - 설정파일작성 (2/5) XML 스키마를이용한 AOP 설정 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <bean id= writelog class= org.kosta.spring.logaspect /> <aop:config> <aop:pointcut id= publicmethod expression= execution(public * org.kosta.spring..*(..)) /> <aop:aspect id= logingaspect ref= writelog > <aop:around pointcut-ref= publicmethod method= logging /> </aop:aspect> </aop:config> <bean id= targetclass class= org.kosta.spring.targetclass /> </beans> 45
POJO 기반 AOP 구현 - 설정파일작성 (3/5) AOP 설정태그 1. <aop:config> : aop설정의 root 태그. weaving들의묶음. 2. <aop:aspect> : Aspect 설정 하나의 weaving에대한설정 3. <aop:pointcut> : Pointcut 설정 4. Advice 설정태그들 A. <aop:before> - 메소드실행전실행될 Advice B. <aop:after-returning> - 메소드정상실행후실행될 Advice C. <aop:after-throwing> - 메소드에서예외발생시실행될 Advice D. <aop:after> - 메소드정상또는예외발생상관없이실행될 Advice finally E. <aop:around> - 모든시점에서적용시킬수있는 Advice 구현 46
POJO 기반 AOP 구현 - <aop:aspect> (4/5) 한개의 Aspect ( 공통관심기능 ) 을설정 ref 속성을통해공통기능을가지고있는 bean 을연결한다. id 는이태그의식별자를설정 자식태그로 <aop:pointcut> advice 관련태그가올수있다. <aop:config> <aop:aspect id= logingaspect ref= writelog > <aop:pointcut id= publicmethod expression= execution(public * public * org.myspring..*.* (..)) /> <aop:around pointcut-ref= publicmethod method= logging /> </aop:aspect> </aop:config> 47
POJO 기반 AOP 구현 - <aop:pointcut> (5/5) Pointcut( 공통기능이적용될곳 ) 을지정하는태그 <aop:config> 나 <aop:aspect> 의자식태그 <aop:config> 전역적으로사용 <aop:aspect> 내부에서사용 AspectJ 표현식을통해 pointcut 지정 속성 : id : 식별자로 advice 태그에서사용됨 expression : pointcut 지정 <aop:pointcut id= publicmethod expression= execution(public * org.myspring..*.*(..)) /> <aop:config> <aop:aspect id= logingaspect ref= writelog > <aop:pointcut id= publicmethod expression= execution(public * org.myspring..*.*(..)) /> <aop:around pointcut-ref= publicmethod method= logging /> </aop:aspect> </aop:config> 48
POJO 기반 AOP 구현 - AspectJ 표현식 (1/3) AspectJ 에서지원하는패턴표현식 스프링은메서드호출관련명시자만지원 명시자 ( 제한자패턴? 리턴타입패턴패키지패턴? 이름패턴 ( 파라미터패턴 )) -? 는생략가능 명시자 execution : 실행시킬메소드패턴을직접입력하는경우 within : 메소드가아닌특정타입에속하는메서드들을설정할경우 bean : 2.5 버젼에추가됨. 설정파일에지정된빈의이름 (name 속성 ) 을이용해 pointcut 설정 49
POJO 기반 AOP 구현 - AspectJ 표현식 (2/3) 표현 명시자 ( 수식어패턴? 리턴타입패턴패키지패턴? 클래스이름패턴. 메소드이름패턴 ( 파라미터패턴 )) -? 는생략가능예 ) execution(public * abc.def..*service.set*(..) 수식어패턴에는 public, protected 또는생략한다. * : 1 개의모든값을표현 argument에서쓰인경우 : 1개의 argument package에쓰인경우 : 1개의하위 package.. : 0개이상 argument에서쓰인경우 : 0개이상의 argument package에쓰인경우 : 0개의이상의하위 package 위예설명적용하려는메소드들의패턴은 public 제한자를가지며리턴타입에는모든타입이다올수있다. 이름은 abc.def 패키지와그하위패키지에있는모든클래스중 Service로끝나는클래스들에서 set으로시작하는메소드이며 argument는 0개이상오며타입은상관없다. 50
POJO 기반 AOP 구현 - AspectJ 표현식 (3/3) 예 execution(* test.spring.*.*()) execution(public * test.spring..*.*()) execution(public * test.*.*.get*(*)) execution(string test.spring.memberservice.registmember(..)) execution(* test.spring..*service.regist*(..)) execution(public * test.spring..*service.regist*(string,..)) within(test.spring.service.memberservice) within(test.spring..memberservice) within(test.spring.aop..*) bean(memberservice) bean(*service) 51
POJO 기반 AOP 구현 - Advice 작성 POJO 기반 Aspect 클래스작성 설정파일의 advice 관련태그에맞게작성한다. <bean> 으로등록하며 <aop:aspect> 의 ref 속성으로참조한다. 공통기능메소드 : advice 관련태그들의 method 속성의값이메소드의이름이된다. 52
POJO 기반 AOP 구현 - Advice 정의관련태그 속성 pointcut-ref : <aop:pointcut> 태그의 id 명을넣어 pointcut 지정 pointcut : 직접 pointcut 을설정한다. method : Aspect bean 에서호출할메소드명지정 <bean id= writelog class= org.kosta.spring.logaspect /> <aop:config> <aop:aspect id= logingaspect ref= writelog > <aop:pointcut id= publicmethod expression= execution(public * org.my.spring..*.*(..)) /> <aop:before pointcut-ref= publicmethod method= logging /> </aop:aspect> </aop:config> 53
POJO 기반 AOP 구현 - Aspect 클래스작성 (1/4) POJO 기반의클래스로작성한다. 클래스명이나메서드명에대한제한은없다. 메소드구문은호출되는시점에따라달라질수있다. 메소드의이름은 advice 태그 (<aop:before/>) 에서 method 속성의값이메소드명이된다. before 메소드 대상객체의메소드가실행되기전에실행됨 return type : void argument : 없거나 JoinPoint 객체를받는다. ex) public void beforelogging(joinpoint jp){ } 54
POJO 기반 AOP 구현 - Aspect 클래스작성 (2/4) After Returning Advice 대상객체의메소드실행이정상적으로끝난뒤실행됨 return type : void argument : 없거나 JoinPoint 객체를받는다. JoinPoint는항상첫 argument 로사용된다. 대상메소드에서리턴되는값을 argument로받을수있다. <aop:after-returning pointcut-ref= publicmethod method= returnlogging returning= retvalue /> public void returnlogging(object retvalue){ // 대상객체에서리턴되는값을받을수는있지만수정할수는없다. } 55
POJO 기반 AOP 구현 - Aspect 클래스작성 (3/4) After Throwing Advice 대상객체의메소드실행중예외가발생한경우실행됨 return type : void argument : 없거나 JoinPoint 객체를받는다. JoinPoint는항상첫 argument 로사용된다. 대상메소드에서전달되는예외객체를 argument로받을수있다. <aop:after-throwing pointcut-ref= publicmethod method= returnlogging throwing= ex /> public void returnlogging(myexception ex){ } // 대상객체에서리턴되는값을받을수는있지만수정할수는없다. 56
POJO 기반 AOP 구현 - Aspect 클래스작성 (4/4) Around Advice 위의네가지 Advice 를다구현할수있는 Advice. return type : Object argument org.aspectj.lang.proceedingjoinpoint 를반드시첫 argument 로지정한다. <aop:around pointcut-ref= publicmethod method= returnlogging /> public Object returnlogging(proceedingjoinpoint joinpoint) throws Throwable{ } // 대상객체의메소드호출전해야할전처리코드 try{ Object retvalue = joinpoint.proceed(); // 대상객체의메소드호출 // 대상객체처리이후해야할후처리코드 return retvalue; // 호출한곳으로리턴값넘긴다. 넘기기전수정가능 }catch(throwable e){ } throw e; // 예외처리 57
JoinPoint 대상객체에대한정보를가지고있는객체로 Spring container로부터받는다. org.aspectj.lang 패키지에있음 받듯이 Aspect 메소드의첫 argument로와야한다. 메소드들 Object gettarget() : 대상객체를리턴 Object[] getargs() : 파라미터로넘겨진값들을배열로리턴. 넘어온값이없으면빈배열개체가 return 됨. Signature getsignature () : 호출되는메소드의정보 Signature : 호출되는메소드에대한정보를가진객체 String getname() : 메소드명 String tolongstring() : 메서드전체 syntax 를리턴 String toshorstring() : 메소드를축약해서 return 기본은메소드이름만리턴 58
@Aspect 어노테이션을이용한 AOP @Aspect 어노테이션을이용하여 Aspect 클래스에직접 Advice 및 Pointcut 등을직접설정 설정파일에 <aop:aspectj-autoproxy/> 를추가필요 Aspect class 를 <bean> 으로등록 어노테이션 (Annotation) @Aspect : Aspect 클래스선언 @Before( pointcut ) @AfterReturning(pointcut=, returning= ) @AfterThrowing(pointcut=, throwing= ) @After( pointcut ) @Around( pointcut ) Around 를제외한나머지메소드들은첫 argument 로 JoinPoint 를가질수있다. Around 메소드는 argument로 ProceedingJoinPoint를가질수있다. 59
Spring MVC 60
Spring MVC 흐름 (1/2) Spring MVC MVC 패턴기반웹개발프레임워크 2 Handler Mapping Client 1 Dispatcher Servlet ModelAndView 3 4 Controller 5 ViewResolver 6 View 61
Spring MVC 흐름 (2/2) 요청처리순서 1 DispatcherServlet 이요청을수신 단일 front controller servlet 요청을수신하여처리를다른컴포넌트에위임 어느컨트롤러에요청을전송할지결정 2 DispatcherServlet 은 HandlerMapping 에어느컨트롤러를사 용할것인지문의 URL과매핑 3 DispatcherServlet은요청을컨트롤러에게전송하고컨트롤러는요청을처리한후결과리턴 비즈니스로직수행후결과정보 (Model) 가생성되어 JSP와같은뷰에서사용됨 4 ModelAndView 오브젝트에수행결과가포함되어 DispatcherServlet에리턴 5ModelAndView는실제 JSP정보를갖고있지않으며, ViewResolver가논리적이름을실제 JSP이름으로변환 6View는결과정보를사용하여화면을표현함. 62
Spring MVC 구현 Step Spring MVC 를이용한어플리케이션작성스텝 1.web.xml 에 DispacherServlet 등록및 Spring 설정파일등록 2. 설정파일에 HandlerMapping 설정 3. 컨트롤러구현및 Spring 설정파일에등록 4. 컨트롤러와 JSP 의연결위해 View Resolver 설정 5.JSP 코드작성 Web Request Response Dispatcher Servlet Request Response Controller dosomething() Model 63
DispatcherServlet 설정과 ApplicationContext (1/3) DispatcherServlet 설정 web.xml 에등록 스프링설정파일 : <servlet-name>-servlet.xml 이고 WEB-INF\ 아래추가한다. <url-pattern> 은 DispatcherServlet 이처리하는 URL 매핑패턴을정의 <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.dispatcherservlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>*.htm</url-pattern> </servlet-mapping> Spring Container는설정파일의내용을읽어 ApplicationContext 객체를생성한다. 설정파일명 : dispatcher-servlet.xml MVC 구성요소 (HandlerMapping, Controller, ViewResolver, View) 설정과 bean, aop 설정들을한다. 64
DispatcherServlet 설정과 ApplicationContext (2/3) Spring 설정파일등록하기 <servlet> 의하위태그인 <init-param> 에 contextconfiglocation 이름으로등록 경로는 Application Root부터절대경로로표시 여러개의경우, 또는공백으로구분 <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.dispatcherservlet</servlet-class> <load-on-startup>1</load-on-startup> <init-param> <param-name>contextconfiglocation</param-name> <param-value>/web-inf/server-service.xml, dao-service.xml</param-value> </init-param> </servlet> 65
DispatcherServlet 설정과 ApplicationContext (3/3) DispatcherServlet 여러개설정시공통 Spring 설정파일등록 컨텍스트설정파일 ( 스프링설정파일 ) 들을로드하기위해리스너 (ContextLoaderListener) 설정 설정파일 <context-param> 으로등록 <listener> <listener-class>org.springframework.web.context.contextloaderlistener</listener-class> </listener> <context-param> <param-name>contextconfiglocation</param-name> <param-value>/web-inf/service-service.xml /WEB-INF/dao-data.xml </param-value> </context-param> 66
HandlerMapping Client 요청과 Controller 를연결을설정 다양한 HandlerMapping 클래스를 Springframework 가제공하며 Spring 설정파일에 <bean name= HandlerMapping > 으로등록하여설정한다. BeanNameUrlHandlerMapping bean 의이름과 url 을 mapping SimpleUrlHandlerMapping url pattern 들을 properties 로등록해처리 67
HandlerMapping BeanNameUrlHandlerMapping 설정 <bean id="handlermapping" class="org.springframework.web.servlet.handler.beannameurlhandlermapping"/> <bean name="/hello.do" class="controller.hellocontroller"/> <bean name="/welcome.do" class="controller.welcomecontroller"/> SimpleUrlHandlerMapping 설정 <bean id="handlermapping" class="org.springframework.web.servlet.handler.simpleurlhandlermapping"> <property name="mappings"> <props> <prop key= /register.do">registercontoller</prop> <prop key= /delete.do >deletecontroller</prop> </props> </property> </bean> <!-- 컨트롤러 bean 으로등록 --> <bean name= registercontoller../> <bean name= deletecontroller./> 68
Controller 작성 Controller 종류 Controller (interface) AbstractController AbstractComandController MultiActionController 위의 interface/class 를상속하여 Controller 작성한다. 69
AbstractController (1/2) 가장기본이되는 Controller 작성 AbstractController 상속한다. public ModelAndView HandlerequestInternal (HttpServletRequest request, HttpServletResponse response) throws Exception 오버라이딩하여코드구현 ModelAndView 에 view 가사용할객체와 view 에대한 id 값을넣어생성후 return 70
AbstractController (2/2) public class HelloworldAbstractController extends AbstractController{ protected ModelAndView HandlerequestInternal( HttpServletRequest request, HttpServletResponse response) throws Exception { //Model 호출 Business Logic 처리 //ModelAndView를통해 view로수행넘김 return new ModelAndView("hello","message",helloVO); } } 71
AbstractCommandController (1/2) HttpServletRequest 로받아온 form data(parameter) 를동적 으로특정데이터객체 (VO-Command 지칭 ) 로바인드하는 controller. Struts 의 ActionForm 의기능과유사 Spring 의경우 Strutrs 처럼데이터객체가 framework-specific 인터페이스를 implement 하지않아도된다. 생성된 Command 객체는 requestscope 에속성으로 binding 된다. 작성 데이터객체는 java beans 규약에맞게생성 (setter). parameter 의이름과데이터객체의 property 이름이동일해야한다. AbstractCommandController 를상속하여클래스작성 Data 객체에설정을위해아래두메소드생성자에서호출한다. setcommandclass(class commandclass) : Command 클래스 setcommandname(string commandname) : requestscope 에 Command 객체를넣을때사용할이름, 생략가능 protected ModelAndView handle(httpservletrequest request, HttpServletResponse response, Object command, BindException be) throws Exception{} 메소드를 overriding 하여구현 72
AbstractCommandController (2/2) Command class(vo) public class PersonCommand{ private String id; private String name;. setter/getter } Controller (VO) public class RegisterController extends AbstractCommandController{ public RegisterController(){ setcommandclass(personcommand.class); setcommandname( personcommand ); } protected ModelAndView handle(httpservletrequest req, HttpServletResponse res, Object command, BindException error){ PersonCommand cmd = (PersonCommand)command; //Business Logic 처리 ModelAndView mv = new ModelAndView( show_content ); return mv; } } 73
MultiActionController (1/3) 하나의 Controller 에서여러개의요청을수행할경우사용 struts 의 DispatcherAction 과동일한역할 연관된 request 를하나의 controller 로묶을경우 사용. 작성 MultiActionController 상속 client 의요청을처리할메소드구현 public [ModelAndView Map void] 메소드이름 ( HttpServletRequest req, HttpServletResponse res [HttpSession Command]) [throws Exception]{} return type : ModelAndView, Map, void 중하나 argument : 1 번 - HttpServletRequest, 2 번 - HttpServletResponse 3 번 선택적이며 HttpSession 또는 Command 74
MultiActionController (2/3) MethodNameResolver 등록 역할 : 어떤메소드가클라이언트의요청을처리할것인지결정 Spring 설정파일에 <bean> 으로등록 controller 에서는 property 로주입받는다. 종류 ParameterMethodNameResolver : parameter 로메소드이름전송 InternalPathMethodNameResolver : url 마지막경로메소드이름으 로사용 PropertiesMethodNameResolver : URL 과메소드이름 mapping 을 property 로설정 75
MultiActionController (3/3) Controller class public class MemberController extends MultiActionController{ public ModelAndView registermember(httpservletrequest request, HttpServletResponse response) throws Exception{ //Business Logic 구현 ModelAndView mv = new ModelAndView(); mv.setviewname("register_ok"); return new ModelAndView(); } }<bean id="methodnameresolver" class="org.springframework.web.servlet.mvc.multiaction.parametermethodnameresolver"> <property name="paramname" value="mode"></property> </bean> <bean id= membercontroller" class="controller.multiaction.membercontroller"> <property name="methodnameresolver"> <ref bean="methodnameresolver"/> </property> </bean> 호출 : http://ip:port/applname/member?mode=registermember 76
ModelAndView (1/2) Controller 처리결과후응답할 view 와 veiw 에전달할값을저장. 생성자 ModelAndView(String viewname) : 응답할 view 설정 ModelAndView(String viewname, Map values) : 응답할 view 와 view 로전달할값들을저장한 Map 객체 ModelAndView(String viewname, String name, Object value) : 응답할 view 이름, view 로넘길객체의 name-value 주요메소드 setviewname(string view) : 응답할 view 이름을설정 addobject(string name, Object value) : view 에전달할값을설정 requestscope 에설정됨 addallobjects(map values) : view 에전달할값을 Map 에 namevalue 로저장하여한번에설정 - requestscope 에설정됨 Redirect 방식전송 view 이름에 redirect: 접두어붙인다. ex) mv.setviewname( redirect:/welcome.html ); 77
ModelAndView (2/2) protected ModelAndView HandlerequestInternal(HttpServletRequest req, HttpServletResponse res) throws Exception{ //Business Logic 처리 ModelAndView mv = new ModelAndView(); mv.setviewname( /hello.jsp ); mv.addobject( greeting, hello world ); return mv; } 78
ViewResolver Controller 가넘긴 view 이름을통해알맞은 view 를찾는역할 1. Controller 는 ModelAndView 객체에응답할 view 이름을넣어 return. 2. DispatchServlet 은 ViewResolver 에게응답할 view 를요청한다. 3. ViewResolver 는 View 이름을이용해알맞는 view 객체를찾는다. 다양한 ViewResolver 를 SpringFramework 는제공한다. InternalResourceViewResolver : 뷰의이름을 JSP, HTML 등과연동한 View 를 return ViewResolver Spring 설정파일에등록한다. 79
ViewResolver Spring 설정파일에설정 <bean id= viewresolver class= org.springframework.web.servlet.view.internalresourceviewresolver > <property name= prefix value= /WEB-INF/jsp/ > <property name= suffix value=.jsp /> </bean> Controller ModelAndView mv = new ModelAndView(); mv.setviewname( hello ); 위의경우 /WEB-INF/jsp/hello.jsp 를찾는다. 80
Spring 과 DB 81
Spring 의데이터접근방식 (1/4) Spring 에서의 JDBC 프로그래밍 데이터접근템플릿제공 JDBC 프로그래밍을쉽게할수있는템플릿 DAO 지원클래스제공 Template 을쉽게사용할수있도록지원하는 class 데이터접근템플릿 템플릿메소드 (template method) 패턴 템플릿메소드는프로세스에대한틀 (skeleton) 을정의함. 전반적인프로세스 ( 의흐름 ) 는고정되어있고, 변하지않음. 특정시점의프로세스는특정상황에따라세부적인구현내용이달라짐. Spring 의데이터접근은템플릿메소드패턴을적용 데이터접근단계에서연결을얻고, 자원을해제하는부분은고정 데이터접근방법은각각다름. 두가지클래스 템플릿 (template) 프로세스의고정된부분을담당 82
Spring 의데이터접근방식 (2/4) 데이터접근템플릿화 Spring 의템플릿클래스 템플릿클래스 (org.springframework.*) 사용목적 jdbc.core.jdbctemplate jdbc.core.namedparam.namedparameterjdbc Template jdbc.core.simple.simplejdbctemplate org.ibatis.sqlmapclienttemplate org.hibernate.hibernatetemplate org.hibernate3.hibernatetemplate orm.jdo.jdotemplate orm.jpa.jpatemplate orm.toplink.toplinktemplate jca.cci.core.ccitemplate JDBC 연결 명명된 (named) 파라미터에대한지원과함께사용하는 JDBC 연결 Java 5 구조와함께단순화된 JDBC 연결 ibatis SqlMap 클라이언트 Hibernate 2.x 세션 Hibernate 3.x 세션 Java Data Object 구현 Java Persistence API 엔티티관리자 오라클의 TopLink JCA CCI 연결 83
Spring 의데이터접근방식 (3/4) DAO 지원클래스사용 Spring 의 DAO 지원클래스 DAO Support 데이터접근템플릿 Persistence Framework 어플리케이션 DAO DB 어플리케이션에대한 DAO 구현시 Spring 의 DAO 지원클래스를상속받음. 내부의데이터접근템플릿에바로접근하려면템플릿조회메소드를호출 JdbcDaoSupport 클래스를상속받고, getjdbctemplate() 을호출해서 작업수행 저장플랫폼을접근하려면 DB 와통신하기위해사용되는클래스를접근함. JdbcDaoSupport 의 getconnection() 메소드 84
Spring 의데이터접근방식 (4/4) DAO 지원클래스사용 Spring 의 DAO 지원클래스 DAO 지원클래스 (org.springframework.*) 사용목적 jdbc.core.support.jdbcdaosupport jdbc.core.namedparam.namedparameterjdbcd aosupport jdbc.core.simple.simplejdbcdaosupport org.ibatis.support.sqlmapclientdaosupport org.hibernate.support.hibernatedaosupport org.hibernate3.support.hibernatedaosupport orm.jdo.support.jdodaosupport orm.jpa.support.jpadaosupport orm.toplink.support.toplinkdaosupport jca.cci.support.ccidaosupport JDBC 연결 명명된 (named) 파라미터에대한지원과함께사용하는 JDBC 연결 Java 5 구조와함께단순화된 JDBC 연결 ibatis SqlMap 클라이언트 Hibernate 2.x 세션 Hibernate 3.x 세션 Java Data Object 구현 Java Persistence API 엔티티관리자 오라클의 TopLink JCA CCI 연결 85
데이터소스설정 (1/4)-JNDI 데이터소스사용 (1) JNDI 데이터소스사용 Spring 어플리케이션이 JEE 어플리케이션서버내에배포될때사용 장점 어플리케이션외부에전적으로관리를맡김. 어플리케이션서버는우수한성능으로데이터소스를관리하고시스템관리자는데이터소스를제어할수있음. JndiObjectFactoryBean 이용 <bean id="datasource" class="org.springframework.jndi.jndiobjectfactorybean" scope="singleton"> <property name="jndiname" value="/jdbc/oracle"/> <property name="resourceref" value="true"/> </bean> jndiname 속성은 JNDI 에서자원의이름을지정 어플리케이션이자바어플리케이션서버내에서구동하면 resourceref 값을 true 로세팅 원래의 jndiname 값에 java:comp/env 가붙음. java:/comp/env/jdbc/oracle 86
데이터소스설정 (2/4)-JNDI 데이터소스사용 (2) JNDI 데이터소스사용 - 2 Spring 2.0 이상에서의 JNDI 데이터소스 Spring 설정파일에 jee 네임스페이스등록하여처리 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:jee="http://www.springframework.org/schema/jee" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd"> <jee:jndi-lookup id="datasource" jndi-name="/jdbc/oracle" resource-ref="true"/> </beans> 87
데이터소스설정 (3/4)-DBCP 사용 DBCP 사용 Spring 이기본으로제공하는 DBCP 사용할수있다. Jakarta Commons Database Connection Pools (DBCP) http://commons.apache.org/dbcp/ BasicDataSource 사용 DataSource 를 bean 으로등록한다. <bean id="datasource" class="org.apache.commons.dbcp.basicdatasource"> <property name="driverclassname" value="oracle.jdbc.driver.oracledriver"/> <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521/xe"/> <property name="username" value= hr"/> <property name="password" value= hr"/> <property name="initialsize" value="5"/> <property name="maxactive" value="10"/> </bean> 설정항목 http://commons.apache.org/dbcp/configuration.html 참고 88
데이터소스설정 (4/4)-JDBC DataSource 사용 JDBC 드라이버기반한데이터소스 DriverManagerDataSource 요청된연결에대해서매번새로운연결을제공. DBCP 의 BasicDataSource 와달리 DriverManagerDataSource 에의해제공되는연결은풀링되지않음. SingleConnectionDataSource 요청된연결에대해서매번동일한연결을제공. 정확하게풀링된데이터소스는아니지만, 단하나의연결을풀링하는데이터소스라고보면됨. <bean id="datasource" class="org.springframework.jdbc.datasource.drivermanagerdatasource"> <property name="driverclassname" value="org.hsqldb.jdbcdriver"/> <property name="url" value=" jdbc:oracle:thin:@127.0.0.1:1521/xe "/> <property name="username" value="sa"/> <property name="password" value=""/> </bean> 멀티쓰레드환경에서사용이제약됨. 89
Spring 에서 JDBC 사용예 (1/2) 기본 JDBC 코드 DataSource 를주입받아 JDBC 코딩 public class MemberDAO{ private DataSource datasource; public void insertmember(membervo mvo) { Connection conn = null; PreparedStatement pstmt = null; String sql = insert ; try { conn = datasource.getconnection(); pstmt = conn.preparestatement(sql); pstmt.setstring(1, mvo.getid()); pstmt.setstring(2, mvo.getpassword()); pstmt.setstring(3, mvo.getname()); pstmt.setstring(4, mvo.getaddress()); pstmt.executeupdate(); } } catch (SQLException e) { // 오류처리 } finally { try { if (stmt!= null) pstmt.close(); if (conn!= null) conn.close(); } catch (SQLException e) {} } // 주입받는다. public void setdatasource(datasource ds) { this.datasource = ds; } } 90
Spring 에서 JDBC 사용 (2/2) JDBC 코드 저장 Spring 설정파일 <bean id="datasource class="org.springframework.jdbc.datasource.drivermanagerdatasource"> <property name="driverclassname" value="oracle.jdbc.driver.oracledriver"/> <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:xe"/> <property name="username" value="hr"/> <property name="password" value="hr"/> </bean> <bean id="memberdao" class="dao.memberdao"> <property name="datasource" ref="datasource"/> </bean> 91
JDBC Template 을이용 (1/4) JDBC 템플릿사용 세가지템플릿클래스 JdbcTemplate Spring 의 JDBC 템플릿중에가장기본클래스로 JDBC 를통한데 이터베이스에대한단순한연결과단순한인덱싱파라미터쿼리를 제공 NamedParameterJdbcTemplate 인덱싱된파라미터가아닌 SQL 에명명된 (named) 파라미터로값 을세팅하는쿼리를수행하게함. SimpleJdbcTemplate Autoboxing 이나, generics, 가변 (variable) 파라미터리스트와 같은 Java 5 기능을사용하여 JDBC 템플릿사용방법을단순화시 켜서제공 92
JDBC Template 을이용 (2/4) JDBC 템플릿사용 update 계열 JdbcTemplate 를사용한데이터접근 public interface DAO { void insert(membervo mvo); } public class MemberDAO implements DAO { private JdbcTemplate jdbctemplate; public void setjdbctemplate(jdbctemplate jdbctemplate) { this.jdbctemplate = jdbctemplate; } @Override public void insert(membervo mvo) { jdbctemplate.update(member_insert, new Object[]{mvo.getId(), mvo.getpassword(), mvo.getname(), mvo.getaddress()}); } } Spring 설정파일에서주입 JdbcTemplate 을사용한실행구문 쿼리의인덱싱된파라미터값 실행할 SQL 구문 93
Spring 에서 JDBC 사용 (5/6) JDBC 템플릿사용 JdbcTemplate 를사용한데이터접근 <bean id="jdbctemplate" class="org.springframework.jdbc.core.jdbctemplate"> <property name="datasource" ref="datasource"/> </bean> <bean id="dao" class="dao.memberdao"> <property name="jdbctemplate" ref="jdbctemplate"/> </bean> DB 연결, statement 생성, SQL 실행등은 JdbcTemplate 이대신수행함. SQLException 은 JdbcTemplate 에서 catch 하여 throw 함. 일반적인 SQLException 을세부적인데이터접근에러로변경하여 throw 함. Spring 의템플릿메소드들이제공하는예외는 Runtime 계열의메소드 이므로따로예외를잡을필요없다. 94
Spring 에서 JDBC 사용 (6/6) JDBC 템플릿사용 - select JdbcTemplate 를사용한데이터접근 실행할 SQL 구문 public Motorist selectmemberbyid(string id) { List matches = jdbctemplate.query(member_select_by_id, new Object[] {id}, new RowMapper() { 쿼리의인덱싱된파라미터값 @Override public Object maprow(resultset rs, int rownum) throws SQLException { return new Motorist(rs.getInt(1), rs.getstring(2), rs.getstring(3), rs.getstring(4), rs.getstring(5)); } }); return matches.size() > 0? (Motorist)matches.get(0) : null; } ResultSet 에서값을추출하여도메인객체를만들어냄. 쿼리실행으로부터결과인모든행 (row) 에대해서 JdbcTemplate 은 RowMapper 의 maprow() 메소드를호출 RowMapper 내에서 VO(DTO) 객체를생성하고 ResultSet 에서값을세팅함. 95
Struts 와 Spring 통합 96
통합의두가지방법 contextloaderplugin를사용하여 Spring이 Action들을 bean들로관리하도록설정하고 Action들의의존성을 Spring 컨텍스트파일에세팅하는방법 Spring 의 ActionSupport 클래스를상속해서 getwebapplicationcontext() 메소드를사용하여 Spring 관리되는 bean들을명시적으로가로채는방법 97
ContextLoaderPlugin 이용한연동 (1/3) ContextLoaderPlugin : Struts ActionServlet 을위해 Spring 설정파일 (context file) 을읽도록하는 Plugin. 읽어들인 (loading) 설정파일은 ContextLoaderListener 에의해로드된 WebApplicationContext 를부모클래스로참조 Spring 설정파일명 : [ActionServlet 이름 ] -servlet.xml web.xml 설정에서 ActionServlet 의 name 이 action 인경우 action-servlet.xml 이 Spring 설정파일명 작성 struts-config.xml 에 plug-in 설정 <plug-in classname="org.springframework.web.struts.contextloaderplugin"> <set-property property="contextconfiglocation" value="/web-inf/action-servlet.xml.xml,/web-inf/applicationcontext.xml"/> </plug-in> 98
ContextLoaderPlugin 이용한연동 (2/3) Spring 설정을사용할 Action 들은 <action-mapping> 의 type 속성에 DelegatingActionProxy 클래스를설정. DelegatingActionProxy 역할 : Struts 액션에대한요청이들어오면 Spring 설정파일에등록된 Action 을실행 <action path="/searchmember" type="org.springframework.web.struts.delegatingactionproxy" name= memberform"> <forward name="success" path="/web-inf/pages/detail.jsp"/> <forward name="failure" path="/web-inf/pages/search.jsp"/> </action> 99
ContextLoaderPlugin 이용한연동 (3/3) Struts 의 Action class 를 Spring 설정파일에 <bean> 으로등록 ACtion 의 path Struts Action 클래스 <bean name="/searchmember" class="member.actions.searchmemberaction"> <property name= memberservice"> </property> </bean> <ref bean=" memberservice "/> 100
ActionSupport 을이용한연동 (1/2) ActionSupport : Spring 에서 Struts 의 Action 을지원하기위해제공되는 Action Class ActionSupport 를상속받은 struts Action 은 WebApplicationContext 객체를사용할수있다. 종류 ActionSupport DispatchActionSupport Struts 에서 Action class 들을만들때 Action 이아닌 ActionSupport 를상속받도록한다. ActionSupport 제공메소드 getwebapplicationcontext() WebApplicationContext return 함 101
ActionSupport 을이용한연동 (2/2) public class MemberSearchAction extends ActionSupport { } public ActionForward execute(actionmapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { WebApplicationContext ctx = getwebapplicationcontext(); MemberService ms = (MemberService) ctx.getbean("memberservice"); //Business Logic 처리 return mapping.findforward("success"); } 102
ibatis 103
개요 JDBC 코드의패턴 Connection -> Statement -> 쿼리전송 -> 연결 close 모든 JDBC 코드는위의패턴을가진다. 이패턴을캡슐화하여 JDBC 코드를간편하게사용할수있도록 Framework 화가능 ibatis 란 SQL 실행결과를자바빈즈혹은 Map 객체에매핑해주는 Persistence 솔루션으로 SQL 을소스코드가아닌 XML 로따로분리해관리하도록지원 장점 SQL 문장과프로그래밍코드의분리 JDBC 라이브러리를통해매개변수를전달하고결과를추출하는일을간단히처리가능 자주쓰이는데이터를변경되지않는동안에임시보관 (Cache) 가능 트랜잭션처리제공 104
ibatis 설치 http://ibatis.apache.org/java.cgi 에서받는다. 압축을풀면 lib 디렉토리에 api가있다. API를 Application에설치 Standalone Application 어플리케이션 start 스크립트에클래스패스정의 java -cp ibatis-2.3.0.677.jar:... MyMainClass Web Application WEB-INF/lib 에추가 주 ) 다른경로에추가하면설정파일을찾지못하는문제가발생할수있다. 105
ibatis Quick Start (1/3) ibatis SqlMap Config(sqlmap-config.xml) 작성 ibatis framework 에대한설정 <?xml version="1.0" encoding="euc-kr"?> <!DOCTYPE sqlmapconfig PUBLIC "-//ibatis.apache.org//dtd SQL Map Config 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-config-2.dtd"> <sqlmapconfig> <transactionmanager type="jdbc"> <datasource type="simple"> <property name="jdbc.driver" value= oracle.jdbc.driver.oracledriver" /> <property name="jdbc.connectionurl" value="jdbc:oracle:thin:@127.0.0.1:1521:xe" /> <property name="jdbc.username" value= hr" /> <property name="jdbc.password" value= hr" /> </datasource> </transactionmanager> <sqlmap resource="user.xml" /> </sqlmapconfig> 106
ibatis Quick Start (2/3) SqlMap 파일작성 (User.xml) SQL 문을등록하는설정파일 <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE sqlmap PUBLIC "-//ibatis.apache.org//dtd SQL Map 2.0//EN "http://ibatis.apache.org/dtd/sql-map-2.dtd"> <sqlmap namespace="user"> <typealias alias="user" type="myibatis.domain.user"/> <resultmap id="usermap" class="user"> <result property="userid" column="userid"/> <result property="password" column="password"/> <result property="name" column="name"/> <result property="email" column="email"/> <result property="usertype" column="usertype"/> </resultmap> <select id="selectallusers" resultmap="usermap"> select USER_ID as userid, PASSWORD as password, NAME as name, EMAIL as email from USER order by USER_ID ASC </select> </sqlmap> 107
ibatis Quick Start (3/3) ibatis Data Access Object 작성 UserIBatisDao.java package myibatis.dao import java.io.ioexception; import java.io.reader; import java.sql.sqlexception; import java.util.list; import com.ibatis.common.resources.resources; import com.ibatis.sqlmap.client.sqlmapclient; import com.ibatis.sqlmap.client.sqlmapclientbuilder; import myibatis.domain.user; public class UserIBatisDao { private static final String resource = "sqlmap-config.xml"; private SqlMapClient client; } public UserIBatisDao() { try { Reader reader = Resources.getResourceAsReader(resource); this.client = SqlMapClientBuilder.buildSqlMapClient(reader); } catch (IOException e) { throw new RuntimeException("SqlMapClient 생성중오류발생 ", e); } } public List<User> findallusers() { try { List<User> users = client.queryforlist("selectallusers", null); return users; } catch (SQLException e) { throw new RuntimeException(" 사용자조회중오류발생 ", e); } } 108
ibatis 실행흐름도 SqlMapConfig SqlMaps SqlMaps Sql Map 파일 SqlMapConfig : 전역정보설정파일 SqlMaps : SQL 문설정파일 MappedStatement : 설정된쿼리를실행하는 ibatis 객체 input : SQL 문실행시필요한값 output : select 실행결과 Input HashMap POJO Primitive Mapped Statement Output HashMap POJO Primitive Database 109
ibatis 설정파일 설정파일은 XML 기반으로작성 SqlMapConfig 전역설정위한파일 : ibatis 에 JDBC 처리를하기위해필요한사항들을설정한다. Transaction 관리정보, DataSource Factory 를위한설정정보, SqlMap 파일의위치등 SqlMap SQL 문을등록 SQL 문을실행하기위해필요한 input Data 와 Output Data 에대한설정을한다. 설정파일들은작성후 classpath 내저장한다. 110
SqlMapConfig 설정 (1/4) SQLMapConfig 설정파일 (SqlMapConfig.xml) <?xml version="1.0" encoding="euc-kr"?> <!DOCTYPE sqlmapconfig PUBLIC "-//ibatis.apache.org//dtd SQL Map Config 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-config-2.dtd"> 프러퍼티파일설정전역설정옵션트랜잭션관리 SqlMap 파일참조 <sqlmapconfig> <properties resource="sqlmap-config.properties"/> <settings usestatementnamespaces="false" cachemodelsenabled="true" enhancementenabled="true" lazyloadingenabled="true" maxrequests="${maxrequests}" maxsessions="${maxsessions}" maxtransactions="${maxtransactions}" /> <transactionmanager type="${transactionmanager}"> <datasource type="${datasource}"> <property name="datasource" value="${dsname}" /> <property name="jdbc.driver" value="${driver}" /> <property name="jdbc.connectionurl" value="${url}" /> <property name="jdbc.username" value="${user}" /> <property name="jdbc.password" value="${pword}" /> </datasource> </transactionmanager> <sqlmap resource= "sample/config/user.xml" /> </sqlmapconfig> 111
SqlMapConfig 설정 (2/4) <typealias> 요소 설정파일에서사용할클래스의별칭 (alias) 설정 ibatis 는정의된 alias 로언제든지원래 type 에접근가능 SqlMapConfig 에설정하면모든 SqlMap 에서사용가능 <typealias alias= Category type= my.ibatis.category /> 미리정의된 typealias Transaction manager : JDBC, JTA, EXTERNAL Data types : string, int, long, double, boolean, hashmap arraylist, object 등 Data source factory : SIMPLE, DBCP, JNDI Cache controller : FIFO, LRU, MEMORY, OSCACHE XML result : Dom, domcollection, Xml, XmlCollection 112
SqlMapConfig 설정 (3/4) <transactionmanager> 요소 Transaction Manager 타입설정 JDBC : 단순 JDBC 기반의 Transaction Manager 를제공함 JTA : application 이동작하는컨테이너기반의 Transaction Manager 를제공함 EXTERNAL : 트랜잭션관리를 ibatis 에서하지않음 <datasource> : ibatis 에서사용할 DataSource 를생성하는 DataSource Factory 지정 SIMPLE : ibatis 자체제공하는 DataSourceFactory 사용 DBCP : Jakarta Commons Database Connection Pool 구현함 JNDI : Naming 서버에등록된 DataSource 를사용함보통 Container 가제공하는것을사용 하위태그를이용하여필요한 property 들을설정한다. driver, url, 계정정보등 113
SqlMapConfig 설정 (4/4) <sqlmap> 요소 SQL 문을가지고있는설정파일인 SQL Map 파일의위치지정 resource 속성 : class path 상의 SQL Map 파일 114
ibatis 를통한 SQL 문실행 ibatis의 JavaBean select insert update delete Parameter 매핑 Result 매핑 115
JavaBeans 기초 ibatis 의 Java property 접근 Property 구성 private instance variable 과 public setter, getter 메소드 private String name; public String getname(); public void setname(string name); property 타입이 boolean 일경우 private boolean isstudent; public boolean isstudent(); public void setstudent(boolean isstudent); Beans 탐색 Java code anorder.getaccount().getusername() anorder.getorderitem().get(0).getproductid() anobject.getid() anobject.getname() Dot 표기법 anorder.account.username anorder.orderitem[0].productid anobject.id anobject.name 116
ibatis 를통한 SQL 실행 - 개요 Sql Map SQL문설정, Input Data, Output Data를설정하는 xml 기반설정파일 Sql Map 파일은 SqlConfigMap에등록한다. SqlMapClient interface : SQL문실행메소드를 정의 package : com.ibatis.sqlmap.client SqlMapClientBuilder 를통해얻어온다. //ibatis Framework 가실행할때필요한 SqlMapConfig Reader reader = Resources.getResourceAsReader( config/sqlmapconfig.xml ); //SqlMapConfig 의내용을적용하여실행할 SqlMapClient 생성 SqlMapClient sqlmap = SqlMapClientBuilder.buildSqlMapClient(reader); Sql Map 에 SQL 문을등록하고프로그램에서는 SqlMapClient 의메소드를이용해등록한쿼리를실행시킨다. 117
Sql Map (1/3) 주요태그 SQL 문등록태그 <select> 태그명속성하위요소용도 id, parameterclass, parametermap, resultclass, resultmap, cachemodel 모든 dynamic 요소 <insert> id, parameterclass, parametermap 모든 dynamic 요소, selectkey <update> id, parameterclass, parametermap 모든 dynamic 요소수정 <delete> id, parameterclass, parametermap 모든 dynamic 요소삭제 외부 Parameter, Result 매핑설정 태그명속성하위요소용도 <parametermap> id, class <parameter> 외부 Parameter Map 설정의 Root 태그 <parameter> property, javatype, jdbctype, nullvalue N/A 하나의 Parameter Map 설정 <resultmap> id, class <result> 외부 Result Map 설정 조회 입력 <result> property, column, jdbctype, javatype, nullvalue N/A 하나의 Result Map 설정 118
Sql Map (2/3) 주요태그 SQL 문생성태그 태그명속성하위요소용도 <sql> id 모든 dynamic 요소재사용가능한 SQL 문등록 <include> refid 모든 dynamic 요소 SQL 등록태그에서 sql 에등록한태그를재사용 <sql id="select"> select * from order </sql> <select id= selectorderbyid resultclass="map"> <include refid="select" /> where order_id = #orderid# </select> 119
Sql Map (3/3) member.xml <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE sqlmap PUBLIC "-//ibatis.com//dtd SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd"> <sqlmap namespace="member"> <insert id="insertmember" parameterclass="mvo"> INSERT INTO MEMBER (ID, PASSWORD, NAME, ADDRESS, MILEAGE) VALUES(#id#, #password#, #name#, #address#, #mileage#) </insert> <update id="updatemember" parameterclass="mvo"> UPDATE MEMBER SET PASSWORD=#password#, NAME=#name#, ADDRESS=#address#, MILEAGE=#mileage# WHERE ID=#id# </update> <delete id="deletemember"> DELETE FROM MEMBER WHERE ID=#value# </delete> <select id="getmemberbyid" resultclass="mvo"> SELECT ID, PASSWORD, NAME, ADDRESS, MILEAGE FROM MEMBER WHERE ID=#value# </select> </sqlmap> 120
Parameter mapping (1/3) Sql Map 에쿼리등록시세가지요소설정필요 SQL 문 Parameter : Input Data Select 문의경우 Result : Output Data Parameter Mapping Parameter : SQL 문에넣을값 인라인 Parameter, 외부 Parameter 매핑두가지방식이있다. 인라인 값과값을넣을위치를 SQL 안에설정 외부 parameter mapping SQL 문에는? 로설정하고넣을 parameter는 SQL문밖에서설정 SqlMapClient의메소드를통해받은값과 SQL 문에값이들어갈곳을 Mapping 한다. mapping 방법 #parameter name# $parameter name#? 외부파라미터매핑 parameter name VO : getter 와 matching Map : key 와 matching 인라인파라미터 121
Parameter mapping (2/3) # 지시자로인라인 parameter 사용? 로바꾼뒤값을치환한다. PreparedStatement 형식 String 일경우 생성 (LIKE Query 문에서적용어려움 ) <select id="selectuser" resultmap="usermap"> select USER_ID as userid, PASSWORD as password, NAME as name, EMPLOYEE_NO as employeeno, EMAIL as email, PHONE_NUM as phonenumber, ZIP_CODE as zipcode, ADDRESS, GRADE as grade from USER where USER_ID = #value# </select>... where USER_ID = abc ; User user = (User)client.queryForObject("selectUser", "abc"); 122
Parameter mapping (3/3) $ 지시자로인라인 parameter 사용 전달받은값을바로치환한다. copy & paste 개념 String 일경우 로감싸주어야한다. <select id="selectuser" resultmap="usermap"> select USER_ID as userid, PASSWORD as password, NAME as name, EMPLOYEE_NO as employeeno, EMAIL as email, PHONE_NUM as phonenumber, ZIP_CODE as zipcode, ADDRESS, GRADE as grade from USER where USER_ID = %$value$% </select>... where user.name like % 송 % ; List<User> allusers = client.queryforlist("selectallusers", 송 ); 123
Parameter 매핑 외부매핑 (1/2) Parameter 매핑의두가지방안 인라인매핑 SqlMap Mapping 문내부에서바로기술함 매핑이복잡한경우명시적이지못함 외부매핑 외부에서정의됨 보다명시적임 인라인매핑과외부매핑은같이사용할수없다.? 와매칭되어값이할당된다. 인라인매핑의예 외부매핑의예 <insert id="createcategory" parameterclass="category"> insert into CATEGORY_TB ( CAT_ID, CAT_NAME, CAT_DESC ) values ( #id#, #name#, #description# ) </insert> <parametermap class= dvo" id="deptparammap"> <parameter property="deptid"/> <parameter property="deptname"/> <parameter property="managerid"/> <parameter property="loc.locationid"/> </parametermap> <insert id= insert" parametermap="deptparammap" > INSERT INTO DEPARTMENTS VALUES(?,?,?,?) </insert> 124
Parameter 매핑 외부매핑 (1/2) 외부 Parameter 매핑 속성 property javatype jdbctype nullvalue typehandler 설명 매핑문에전달할 JavaBean property 명칭또는 Map value 의 key. 들어갈이름을매핑문에필요한만큼반복해서정의할수있음. 예 ) update 문에서 set 절과 where 절에동일한이름이반복적으로들어갈수있음. 세팅될 parameter 의 Java property 타입을명시적으로정의 세팅될 parameter의데이터베이스타입을명시적으로정의예 ) Java 타입이 Date( java.util.date) 인경우 jdbctype 을 DATE 인지 DATETIME 인지명시할필요가있음 nullvalue 에명시된값이 JavaBean property 에서넘어오면 null 을대체할 Default 값 javatype 및 jdbctype 이일치되는경우 typehandler 가적용되나그것없이직접 typehandler 를지정할수있음 외부 Parameter 매핑이유용한경우 인라인 Parameter 매핑이잘동작하지않을경우 성능을향상시킬경우 명시적매핑을할경우 125
Parameter 매핑 - 정리 인라인 Parameter 매핑 인라인 Parameter 에데이터베이스타입명시 #value:[jdbctype]# (#id:[varchar]) Primitive Parameter int 또는 long 같은 Primitive 타입은 ibatis 에서자동으로 Integer, Long으로 Wrapping 됨 JavaBean 과 Map Parameter 의차이점 JavaBean : property 가정해져있으므로 load time 에매핑오류발견가능 Map : property 가 Runtime 에정해지므로 load time 에매핑오류발견불가 126
Result 매핑 (1/3) 명시적 Result 매핑 속성 property column 설명 결과객체의 JavaBean property 또는 Map 내용 JDBC ResultSet 의 column columnindex ResultSet 의 column 명대신 index 를주어결과값매핑이가능. 약간의성능향상이있으며필수사항은아님. jdbctype ResultSet column 의타입을명시함. java.util.date의경우해당되는 jdbctype이여러가지 (DATE, DATETIME) 이므로정확한매핑을위해명시하는것이좋음. JDBC driver에따라정의할필요가없는것도있음. javatype 세팅될 Java 타입을명시함. nullvalue select 데이터베이스에서 null 이넘어온경우 null 을대신할 default 값지정 객체관계를표현하며복잡한 property 타입을로드할수있음들어갈값은반드시다른매핑문의이름이어야함. 127
Result 매핑 (2/3) Primitive result ibatis 는 primitive 형태의결과를허용하지않음 (int, long, double,..) Wrapping 된형태의타입을리턴 (Integer, Long, Double,..) <select id= getallordercount" resultclass= int"> select count(*) as value from order </select> Integer allcount = client.queryforobject( getallordercount", null); JavaBean 타입으로 Wrapping 할경우 primitive 형태의결과를얻을수있음 public class PrimitiveResult { private int ordercount; public int getordercount() { return ordercount; } public void setordercount(int ordercount) { this.ordercount = ordercount; } } <resultmap id="primitiveresultmapexample" class="primitiveresult"> <result property="ordercount" column="ordercount" /> </resultmap> 128
Result 매핑 (3/3) JavaBean 과 Map Result 의장단점 Bean 방식장점단점 성능향상컴파일타임의이름체크 IDE에서 Refactoring 지원가능 Type casting 이적음 get, set 메소드필요 Map 코드량이적음 느리다컴파일타임체크불가런타임오류가많음 Refactoring 지원이없음 129
SELECT 구문실행 (1/4) SqlMap : <select> 태그이용 속성 id : 프로그램에서호출할이름 resultclass, resultmap : SELECT 문실행결과를담을객체 parameterclass, parametermap : PARAMETER 를받아올객체 SqlMapClient queryforobject() : 0또는 1개의 row 를가져올때사용 unique 한값으로조회시 Object queryforobject(string id, Object parameter) throws SQLException; Object queryforobject(string id, Object parameter, Object result) throws SQLException; 첫번째메소드 : SQL Map 에정의된 select 문 id 와해당파라미터로사용 두번째메소드 : 결과결과를담을객체를넣음. no-argument 생성자가없는 resultclass 를사용해야하는경우사용 1 개이상의 row 가리턴된경우 Exception 발생 130
SELECT 구문실행 (2/4) SqlMapClient queryforlist() 메소드 1개이상의 row가리턴될경우사용 결과를 List로리턴함 select 결과의 1개의 row resultclass의객체 resultclass 객체들 List List queryforlist(string id, Object parameter) throws SQLException; List queryforlist(string id, Object parameter, int skip, int max) throws SQLException; 첫번째메소드 : 사용법이앞과동일 두번째메소드 : DB 에서가져온전체 row 중일부만사용하고싶은경우사용 예 ) DB 에서 100 건을가져올때이중앞의 10 건만취하고싶으면 skip=0, max=10 131
SELECT 구문실행 (3/4) queryformap() 메소드 여러건을 Map 형태로리턴함 Map queryformap(string id, Object parameter, String key) throws SQLException; Map queryformap(string id, Object parameter, String key, String value) throws SQLException; 첫번째메소드 : key map의 key값으로들어갈 property 또는 key를입력 결과 Map의 value는 resultclass에지정한클래스의객체가들어간다. 두번째메소드 : key map의 key값으로들어갈 property 또는 key를입력 결과 Map의 value는지정한 property 또는 key의데이터만들어간다. queryformap() 사용예 Map accountmap = sqlmap.queryformap("account.getall,null,"accountid"); Map accountmap = sqlmap.queryformap("account.getall,null,"accountid,"username"); 132
SELECT 구문실행 결과매핑 (4/4) 자동 Result Map select문실행결과를자동으로객체에매핑가능함 단일 column 매핑 count(id) 값이 Integer 타입으로자동매핑된다. <select id= getallaccountidvalues" resultclass="int"> select count(id) from Account </select> 다중 column 매핑 Integer cnt = (Integer) client.queryforobject("getallaccountidvalues", null); select 문의 column 명과결과객체의 Bean property 명이일치해야함 <select id="selectallcategories" resultclass="category"> select cat.cat_id as id, cat.cat_name as name, cat.cat_desc as description from CATEGORY cat </select> public class Category{ setid(string id){} setname(string name){} setdescription(string desc){} } 133
INSERT SqlMap : <insert> 태그사용 속성 id : 프로그램에서호출할이름 parameterclass, parametermap : PARAMETER 를받아올객체 Sub tag : <selectkey> - PK 객체 return 시 SqlMapClient insert() 사용 Object insert(string id) throws SQLException; Object insert(string id, Object parameter) throws SQLException; return value : PK 객체 - <selectkey> 를사용한경우 134
UPDATE SqlMap : <update> 태그사용 속성 id : 프로그램에서호출할이름 parameterclass, parametermap : PARAMETER 를받아올객체 SqlMapClient update() 사용 int update (String id) throws SQLException; int update(string id, Object parameter) throws SQLException; return value : int update 가적용된 record 개수 135
DELETE SqlMap : <delete> 태그사용 속성 id : 프로그램에서호출할이름 parameterclass, parametermap : PARAMETER 를받아올객체 SqlMapClient delete() 사용 int delete(string id) throws SQLException; int delete(string id, Object parameter) throws SQLException; return value : int 삭제가적용된 record 개수 136
Dynamic SQL 동적 WHERE 절처리 Dynamic 태그 137
동적 WHERE 절처리 언제사용하는가? where 절의비교구문이경우에따라달라질경우 예 ) 카테고리조회시부모카테고리 ID 가 null 일수도있는데 null 인경우조회방식이바뀐다. parentcategoryid=#parentcategoryid# 또는 parentcategoryid IS NULL <select id="getchildcategories" parameterclass="category" resultclass="category"> SELECT * FROM category <dynamic prepend="where "> <isnull property="parentcategoryid"> parentcategoryid IS NULL </isnull> <isnotnull property="parentcategoryid"> parentcategoryid=#parentcategoryid# </isnotnull> </dynamic> </select> 파라미터 Category 의부모아이디가 null 인경우 파라미터 Category 의부모아이디가 null 이아닌경우 138
Dynamic 태그 Dynamic 태그에대하여 5 가지카테고리 dynamic, binary, unary, parameter, iterate 공통속성 prepend, open, close 앞뒤를 ( ) 으로감싼다. <dynamic prepend="where "> WHERE 구문을앞에추가 <isnotempty property="y">y=#y#</isnotempty> <isnotnull property="x" removefirstprepend="true" prepend= AND" open="(" close=")"> <isnotempty property="x.a" prepend="or">a=#x.a#</isnotempty> <isnotempty property="x.b" prepend="or">a=#x.b#</isnotempty> <isnotempty property="x.c" prepend="or">a=#x.c#</isnotempty> </isnotnull> </dynamic> 첫번째하위요소의 prepend 인 OR 을제거한다. 139
Dynamic 태그 <dynamic> 태그 가장상위의태그 다른태그에포함될수없음 접두 / 접미구문을위한수단제공 (prepend, open, close) prepend ( 옵션 ) open ( 옵션 ) close ( 옵션 ) 맨앞에접두구문을붙인다. ( 예 : WHERE ) Body 에내용이없을경우접두구문도생략된다. Body 의내용앞에붙여짐. Body 의내용이없을경우생략된다. prepend 와동시에정의될경우 prepend 다음에나타난다. Body 의내용뒤에붙여짐. Body 의내용이없을경우생략된다. 140
Dynamic 태그 Binary 태그 주어진 Parameter 객체간의 property 값을비교 태그의조건이충족되는경우 Body 내용이나타남 Binary 태그속성 property( 필수 ) Parameter 객체의 property. comparevalue 또는 compareproperty 에서비교하는데쓰인다. prepend( 옵션 ) 맨앞에접두구문을붙인다. 이구문이생략되는경우 1. Body의내용이없는경우 2. 부모태그속성이 removefirstprepend= true 이고현재태그가부모 Body의첫번째요소인경우 open( 옵션 ) Body 의내용앞에붙여짐. Body 의내용이없을경우생략된다. prepend 와동시에정의될경우 prepend 다음에나타난다. close( 옵션 ) Body 의내용뒤에붙여짐. Body 의내용이없을경우생략된다. removefirstprepend ( 옵션 ) compareproperty 첫번째자식태그의 prepend 를생략시킴 property 와비교할 property 이름 comparevalue property 속성에의해비교되는값 ( 상수 ) 141
Dynamic 태그 Binary 태그 ( 계속 ) Binary 태그종류 <isequal> <isnotequal> <isgreaterthan> <isgreaterequal> <islessthan> <islessequal> property 속성과 compareproperty/comparevalue 속성이같은지비교 property 속성과 compareproperty/comparevalue 속성이다른지비교 property 속성이 compareproperty/comparevalue 속성보다큰지비교 property 속성이 compareproperty/comparevalue 속성보다크거나같은지비교 property 속성이 compareproperty/comparevalue 속성보다작은지비교 property 속성이 compareproperty/comparevalue 속성보다작거나같은지비교 142
Dynamic 태그 Binary 태그 ( 계속 ) Binary 태그예제 <select id="getshippingtype" parameterclass="cart" resultclass="shipping"> SELECT * FROM Shipping <dynamic prepend="where "> <isgreaterequal property="weight" comparevalue="100"> shippingtype='freight' </isgreaterequal> <islessthan property="weight" comparevalue="100"> shippingtype='st-ard' </islessthan> </dynamic> </select> Cart.getWeight() >= 100 인지체크 Cart.getWeight() < 100 인지체크 143
Dynamic 태그 Unary 태그 비교를수행하지않고 Bean property 상태를체크한다. 태그의조건이충족되는경우 Body 내용이나타남 Unary 태그속성 property( 필수 ) 상태를체크하기위한 Parameter 객체의 property prepend( 옵션 ) 맨앞에접두구문을붙인다. 이구문이생략되는경우 1. Body의내용이없는경우 2. 부모태그속성이 removefirstprepend= true 이고현재태그가부모 Body의첫번째요소인경우 open( 옵션 ) Body 의내용앞에붙여짐. Body 의내용이없을경우생략된다. prepend 와동시에정의될경우 prepend 다음에나타난다. close( 옵션 ) Body 의내용뒤에붙여짐. Body 의내용이없을경우생략된다. removefirstprepend ( 옵션 ) 첫번째자식태그의 prepend 를생략시킴 144
Dynamic 태그 Unary 태그 ( 계속 ) Unary 태그종류 <ispropertyavailable> 특정 property 가존재하는지체크. Map 의경우 key 가존재하는지체크함. <isnotpropertyavailable> 특정 property 가존재하지않는지체크. Map 의경우 key 가존재하지않는지체크함. <isnull> 특정 property 가 null 인지체크. <isnotnull> 특정 property 가 null 이아닌지체크. <isempty> 특정 property 가 null 이거나비어있는지체크. <isnotempty> 특정 property 가 null 이아니고비어있지않는지체크. <select id="getproducts" parameterclass="product" resultclass="product"> SELECT * FROM Products <dynamic prepend="where "> <isnotempty property="producttype"> producttype=#producttype# </isnotempty> </dynamic> </select> Product.getProductType!= null 이고 Product.getProductType.length() > 0 인지체크 145
Dynamic 태그 Parameter 태그 Parameter 가매핑문에들어왔는지체크하는태그 태그속성 : prepend, open, close, removefirstprepend 태그종류 <isparameterpresent> <isnotparameterprese nt> Parameter 가존재하는지체크 Parameter 가존재하지않는지체크 <select id="getproducts" resultclass="product"> SELECT * FROM Products <isparameterpresent prepend="where "> <isnotempty property="producttype"> producttype=#producttype# </isnotempty> </isparameterpresent> </select> 이 select 매핑문에들어오는어떤 Parameter 든지존재하는지체크 146
Dynamic 태그 <iterate> 태그 Collection 형태의 property 로 SQL 문의반복적인구간생성 각각의구간은 conjunction 속성으로분리됨 태그속성 : property( 필수 ), prepend, open, close, conjunction, removefirstprepend conjunction 반복되는 SQL 구문사이에구분자로들어감 ( 예 :, ) <select id="getproducts" parameterclass="product" resultclass="product"> SELECT * FROM Products <dynamic prepend="where > <iterate property= producttype" open="(" close=") conjunction="or" > producttype=#producttype[]# </iterate> </dynamic> </select> Product의 Collection 형태의 property 반복구간이 OR 로구분됨 147
Transaction 관리 148
ibatis Transaction 관리 Auto Transaction Local Transaction 149
Auto Commit ibatis 의자동트랜잭션지원 Statement 를수행하기만해도적용됨 별다른설정이없음 public void runstatementsusingautomatictransactions() { SqlMapClient sqlmapclient = SqlMapClientConfig.getSqlMapClient(); Person p = (Person) sqlmapclient.queryforobject("getperson", new Integer(9)); p.setlastname("smith"); sqlmapclient.update("updateperson", p); } 150
Local Transaction 가장일반적인형태의 Transaction JDBC Transaction Manager 사용 sqlmap-config.xml 에설정 <transactionmanager type="jdbc"> <datasource type="simple"> <property /> <property /> <property /> </datasource> </transactionmanager> Application Start Commit End Database Local 트랜잭션 Manager 설정 151
Local Transaction Local Transaction 적용예 public void runstatementsusinglocaltransactions() { SqlMapClient sqlmapclient = SqlMapClientConfig.getSqlMapClient(); try { sqlmapclient.starttransaction(); Person p = (Person) sqlmapclient.queryforobject("getperson", new Integer(9)); p.setlastname("smith"); sqlmapclient.update("updateperson", p); Department d = (Department) sqlmapclient.queryforobject("getdept", new Integer(3)); p.setdepartment(d); sqlmapclient.update("updatepersondept", p); sqlmapclient.committransaction(); } finally { sqlmapclient.endtransaction(); } } Transaction 시작 Commit Transaction 종료 152
Spring 에서 Transaction 관리 Spring 의트랜잭션관리에대한지원 프로그램적인관리와선언적인관리지원 Spring 의프로그램적인트랜잭션관리는 EJB 와다름. EJB 는 Java Transaction API(JTA) 구현에종속됨. Spring 은트랜잭션을필요로하는코드로부터실질적인트랜잭션구현을추상화하는 콜백 (callback) 메커니즘을사용. Spring 은 JTA 구현이필요하지않음. 단일저장리소스인경우, 저장메커니즘 (JDBC, Hibernate, JDO, OJB 등 ) 에서제공하는 트랜잭션지원사용이가능 다중리소스인경우, 3rd party JTA 구현도구를사용해서분산트랜잭션 (XA) 지원가능 프로그램적인트랜잭션은코드에서트랜잭션영역을세밀하게정의하는데유연성을제공 선언적인트랜잭션은트랜잭션규칙과오퍼레이션의결합도를없애줌. Spring 의선언적인트랜잭션에대한지원은 EJB 의 CMT(container-managed transaction) 과 비슷함. Spring 의선언적인트랜잭션은 CMT 에서지원하지않는 isolation level 과 timeout 과같은 추가적인속성선언이가능 프로그램적인트랜잭션과선언적인트랜잭션관리에대한선택은세밀한통제 (fine-grained control) 와편이성 (convenience) 에대한결정임. Spring 트랜잭션 manager 는플랫폼에특화된트랜잭션구현과인터페이싱이가능. 153
트랜잭션 Manager (1/3) Spring 제공트랜잭션 Manager 트랜잭션 Manager (org.springframework.*) jdbc.datasource. DataSourceTransactionManager jca.cci.connection.ccilocaltransactionmanager jms.connection.jmstransactionmanager jms.connection.jmstransactionmanager102 orm.hibernate.hibernatetransactionmanager orm.hibernate3.hibernatetransactionmanager orm.jdo.jdotransactionmanager orm.jpa.jpatransactionmanager orm.toplink.toplinktransactionmanager transaction.jta.jtatransactionmanager transaction.jta.oc4jtatransactionmanager transaction.jta. WebLogicJtaTransactionManager 사용목적 Spring 의 JDBC 추상화지원. ibatis 사용시에도사용가능 J2EE Connector Architecture (JCA) 와 Common Client Interface(CCI) 를위한 Spring 지원 JMS 1.1+ 사용시 JMS 1.0.2 사용시 Hibernate 2 사용시 Hibernate 3 사용시 JDO 사용시 Java Persistence API(JPA) 사용시 오라클의 TopLink 사용시 분산트랜잭션이필요하거나맞는트랜잭션 manager 가없는경우 오라클의 OC4J JEE 컨테이너사용시 분산트랜잭션이필요하거나 WebLogic 내에서어플리케이션이실행되는경우 154
트랜잭션 Manager 선택 (2/3) Spring 의트랜잭션 manager 들은플랫폼에특화된트랜잭션구현들에게트랜잭션관리에대한책임을위임함. Spring 제공트랜잭션 Manager Platform TransactionManager Spring 이제공하는트랜잭션 Manager Root DataSource Jdo Jta TransactionManager TransactionManager TransactionManager Hibernate TransactionManager Jpa TransactionManager JDBC Hibernate JDO JPA JTA 플랫폼에특화된트랜잭션구현들 155