Spring framework 1
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 주요개념 의존성주입 (Dependency Injection) 관점지향프로그래밍 (Aspect-Oriented Programming) 2
Spring 장점 경량컨테이너 객체의라이프사이클관리, Java EE 구현을위한다양한 API제공 DI (Dependency Injection) 지원 AOP (Aspect Oriented Programming) 지원 POJO (Plain Old Java Object) 지원 다양한 API와의연동지원을통한 Java EE 구현가능 3
Spring Container 설치 스프링커뮤니티사이트http://www.springsource.org/ 다운로드 http://www.springsource.org/download/community spring-framework-xxx-with-dependencies.zip 을다운받는다. 4
Spring IDE 이클립스 Plugin 설정 (1/2) 상단메뉴 : help-install new software update site : http://dist.springframework.org/release/ide 5
Spring IDE 이클립스 Plugin 설정 (2/2) Project 생성 오른마우스메뉴 -Spring Tools-Add Spring Project Nature 선택 6
Dependency Injection ( 의존성주입 ) 7
의존성주입 (Dependency Injection, DI) 의존관계주입 (dependency injection) 객체간의의존관계를객체자신이아닌외부의조립기가수행한다. 제어의역행 (inversion of control, IoC) 이라는의미로사용되었음. Martin Fowler, 2004 제어의어떠한부분이반전되는가라는질문에 의존관계주입 이라는용어를사용 복잡한어플리케이션은비즈니스로직을수행하기위해서두개이상의클래스들이서로협업을하면서구성됨. 각각의객체는협업하고자하는객체의참조를얻는것에책임성이있음. 이부분은높은결합도 (highly coupling) 와테스트하기어려운코드를양산함. DI 를통해시스템에있는각객체를조정하는외부개체가객체들에게생성시에의존관계를주어짐. 즉, 의존이객체로주입됨. 객체가협업하는객체의참조를어떻게얻어낼것인가라는관점에서책임성의역행 (inversion of responsibility) 임. 느슨한결합 (loose coupling) 이주요강점 객체는인터페이스에의한의존관계만을알고있으며, 이의존관계는구현클래스에대한차이를모르는채서로다른구현으로대체가가능 의존관계주입 DAO1 Service 의존관계주입 DAO2 8
Spring 의 DI 지원 Spring Container 가 DI 조립기 (Assembler) 를제공 스프링설정파일을통하여객체간의의존관계를설정한다. Spring Container 가제공하는 api 를이용해객체를사용한다. 9
Spring 설정파일 Spring Container 가어떻게일할지를설정하는파일 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> 10
Bean 객체주입받기 설정파일설정 (1/2) 주입할객체를설정파일에설정한다. <bean> : 스프링컨테이너가관리할 Bean 객체를설정 기본속성 name : 주입받을곳에서호출할이름설정 id : 주입받을곳에서호출할이름설정 ( / 값으로못가짐 ) class : 주입할객체의클래스 factory-method : 객체를생성해주는 factory 메소드호출시» 주로 Singleton 패턴구현클래스객체호출시 <?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 /> 11
Bean 객체주입받기 설정 Bean 사용 (2/2) 설정파일에설정한내용을바탕으로 Spring API 를통해객체를주입받는다. 설정파일이어디있는지설정 객체를만들어주는 (Assembler) 객체생성 public static void main(string [] args){ } // 스프링컨테이너객체생성 ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); // 설정파일에설정한 <bean> 태그의 id/name 을통해객체를받아온다. MemberDAO dao = (MemberDAO)ctx.getBean("dao"); 12
Spring Container 객체 Spring Container : 객체를관리하는컨테이너. 다음아래의 interface 들을구현한다. <<interface>> BeanFactory 빈객체를관리하고각빈객체간의의존관계를설정해주는기능을제공. 가장단순한컨테이너구현클래스 : XmlBeanFactory <<interface>> ApplicationContext BeanFactory 기능에다양한추가기능을제공. 추가기능 : AOP, 메시지지원, 국제화지원등주요구현클래스 : ClassPathXmlApplicationContext <<interface>> WebApplicationContext Web application 용 ApplicationContext. Web Application 당하나씩생성된다. 주요구현클래스 : XmlWebApplicationContext AnnotationConfigWebApplicationContext 13
설정을통한객체주입 Constructor 를이용 (1/4) 객체또는값을생성자를통해주입받는다. <constructor-arg> : 하나의 argument 지정 <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= 값 14
설정을통한객체주입 Constructor 를이용 (2/4) 값을주입받을객체 package to; public class PersonTO{ 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= to.personto > <constructor-arg> <value>abcde</value> </constructor-arg> </bean> 또는 <bean id= person class= to.personto > <constructor-arg value= abc /> </bean> 15
설정을통한객체주입 Constructor 를이용 (3/4) 2 번생성자에주입예 <bean id= person class= to.personto > <constructor-arg> <value>abcde</value> </constructor-arg> <constructor-arg> <value>hong Gil Dong</value> </constructor-arg> </bean> 또는 <bean id= person class= to.personto > <constructor-arg value= abc /> <constructor-arg value= Hong Gil Dong /> </bean> 3 번생성자에주입예 <bean id= person class= to.personto > <constructor-arg> <value type= int >30</value> </constructor-arg> </bean> 또는 <bean id= person class= to.personto > <constructor-arg value= 30 type= int /> </bean> 16
설정을통한객체주입 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> 17
설정을통한객체주입 Property 를이용 (1/5) property 를통해객체또는값을주입받는다.- setter 메소드 주의 : setter 를통해서는하나의값만받을수있다. <property> : <bean> 의하위태그. 설정한 bean 객체또는값을 property 를통해주입하도록설정 속성 : name 값을주입할 property 이름 (setter 의이름 ) 설정방법 <ref>,<value> 와같은하위태그를이용하여설정 속성을이용해설정 xml namespace 를이용하여설정 18
설정을통한객체주입 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= a > bean 주입 : p:propertyname-ref= bean_id ex)<bean p:dao-ref= dao > 19
설정을통한객체주입 Property 를이용 (3/5) Primitive Data Type 주입 값을주입받을객체 package spring.to; 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= to.person > <property name="name"> <value>hong</value> </property> <property name="id" value="abcde"/> <property name="age" value="20"/> </bean> 20
설정을통한객체주입 Property 를이용 (4/5) Bean 객체주입 값을주입받을객체 public class BusinessService{ private Dao dao = null; public void 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> 21
설정을통한객체주입 Property 를이용 (5/5) XML Namespace 를이용한주입 값을주입받을객체 public class BusinessService{ private Dao dao = null; private int waitingtime = 0; public void 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 name= dao class= spring.di.model.oracledao /> <bean name= service" class= service.businessservice" p:waitingtime= 20 p:dao-ref= dao"/> </beans> 22
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 23
Collection 객체주입하기 (2/5) <list> List 계열컬렉션이나배열에값들을넣기. 속성 : value-type 값들의 type 지정. Fullyname 으로지정한다. <ref>, <value> 태그를이용해값설정 <ref bean= bean_id /> : bean 객체 list 에추가 <value [type= type ]> 값 </value> : 문자열 (String), Primitive 값 list 에추가 public void setmylist(list list){ } <bean id= otherbean class= to.otherbean /> <bean id= mybean class= to.myto > <property name= mylist > <list> <value>10</value> ->String 으로저장됨 <value type= java.lang.integer >20</value>->Integer 로저장됨 <ref bean= otherbean /> </list> </property> </bean> 24
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= to.otherbean /> <bean id= mybean class= to.myto > <property name= mymap > <map> <entry key= id value= abc /> <entry key= other value-ref= otherbean /> </map> </property> </bean> 25
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= dao.mydao > <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> 26
Collection 객체주입하기 (5/5) <set> java.util.set 에객체를넣기 속성 : value-type : value 타입설정 <value>, <ref> 를이용해값을넣는다. public void setmyset(set props){ } <bean id= otherbean class= to.otherbean /> <bean id= mybean class= to.bean > <property name= myset> <set> <value>10</value> <value>20<value> <ref bean= otherbean /> </set> </property> </bean> 27
Bean 객체의생성단위 (1/2) BeanFactory 를통해 Bean 을요청시객체생성의범위 ( 단위 ) 를설정 <bean> 의 scope 속성을이용해설정 scope 의값 값 singleton 컨테이너는하나의빈객체만생성한다. - default prototype 빈을요청할때마다생성한다. request session Http 요청마다빈객체생성 HttpSession 마다빈객체생성 request, session 은 WebApplicationContext 에서만적용가능 28
Bean 객체의생성단위 (2/2) 빈 (bean) 범위지정 singleton 과 prototype <bean id= dao class= dao.oracledao scope= prototype /> prototype 은 Spring 어플리케이션컨텍스트에서 getbean 으로빈 (bean) 을사용시마다새로운인스턴스를생성함. singleton 은 Spring 어플리케이션컨텍스트에서 getbean 으로빈 (bean) 을사용시동일한인스턴스를생성함. 29
Factory 메소드를통한 Bean 주입 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 메소드로만호출해야객체를얻을수있는것은아니다. 30
Spring AOP 31
Spring AOP 개요 (1/2) Application 을두가지관점에따라구현 핵심관심사항 (core concern) 공통관심사항 (cross-cutting concern) 기존 OOP 보완 공통관심사항을여러모듈에서적용하는데한계가존재 AOP 는핵심관심사항과공통관심사항분리하여구현 32
Spring AOP 개요 (2/2) 핵심관심사항 : CourseService, StudentService, MiscService 공통관심사항 : Security, Transactions, Other - 핵심관심사항에공통관심사항을어떻게적용시킬것인가 -> AOP 33
Spring AOP 용어 Target 핵심사항 ( Core) 가구현된객체 JoinPoint 공통관심사항이적용될수있는지점 (ex: 메소드호출시, 객체생성시등 ) Pointcut JoinPoint 중실제공통사항이적용될대상을지정. Advice 공통관심사항 (Cross-Cutting) 구현코드 + 적용시점. 적용시점 : 핵심로직실행전, 후, 정상종료후, 비정상종료후, 전 / 후가있다. Aspect Advice + Pointcut Weaving Proxy를생성하는것. ( 컴파일시점, Class Loading 시점, 런타임시점 Weaving이있다.) 34
Spring 에서 AOP 구현방법 AOP 구현 POJO Class 를이용한 AOP 구현 Spring 설정파일을이용한설정 어노테이션 (Annotation) 을이용한설정 스프링 API 를이용한 AOP 구현 35
POJO 기반 AOP 구현 설정파일에 AOP 설정. XML 스키마확장기법을통해설정파일을작성한다. POJO 기반공통관심사항로직클래스작성 36
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> 37
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> 38
POJO 기반 AOP 구현 - 설정파일작성 (3/5) AOP 설정태그 1. <aop:config> : aop 설정의 root 태그. Aspect 설정들의묶음 2. <aop:aspect> : Aspect 설정 하나의 Aspect 설정 Aspect 가여러개일경우 <aop:aspect> 태그가여러개온다. 3. <aop:pointcut> : Advice 에서참조할 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 구현 39
POJO 기반 AOP 구현 - <aop:aspect> (4/5) 한개의 Aspect (advice + pointcut) 을설정 속성 ref : 공통관심사항을설정한 Bean(Advice 빈 ) 참조 id : 식별자 다른 Aspect 태그와구별하기위한식별자 자식태그 <aop:pointcut> : pointcut 지정 advice 관련태그가올수있다. <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> 40
POJO 기반 AOP 구현 - <aop:pointcut> (5/5) Pointcut( 공통기능이적용될곳 ) 을지정하는태그 <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> 41
POJO 기반 AOP 구현 - AspectJ 표현식 (1/3) AspectJ에서지원하는패턴표현식 스프링은메서드호출관련명시자만지원 명시자 (pattern) -? 는생략가능 명시자 execution : 메소드구문을기준으로지정 within : Class 명을기준으로지정 bean : 설정파일에지정된빈의이름 (name 속성 ) 을이용해지정. 2.5 버전에추가됨. 42
POJO 기반 AOP 구현 - AspectJ 표현식 (2/4) 표현 명시자 ( 패턴 ) - 패턴은명시자마다다름. 예 ) execution(public * abc.def..*service.set*(..) 패턴문자. * : 1 개의모든값을표현 argument 에서쓰인경우 : 1 개의 argument package 에쓰인경우 : 1 개의하위 package 이름 ( 메소드, 클래스 ) 에쓰일경우 : 모든글자들.. : 0 개이상 argument 에서쓰인경우 : 0 개이상의 argument package 에쓰인경우 : 0 개의이상의하위 package execution execution( 수식어패턴? 리턴타입패턴패키지패턴?. 클래스명패턴. 메소드명패턴 (argument 패턴 )) 수식어패턴 : public, protected, 생략 argument 에 type 을명시할경우객체타입은 fullyname 으로넣어야한다. java.lang 은생략가능 위예설명적용하려는메소드들의패턴은 public 제한자를가지며리턴타입에는모든타입이다올수있다. 이름은 abc.def 패키지와그하위패키지에있는모든클래스중 Service 로끝나는클래스들에서 set 으로시작하는메소드이며 argument 는 0 개이상오며타입은상관없다. 43
POJO 기반 AOP 구현 - AspectJ 표현식 (3/4) within within( 패키지패턴. 클래스명패턴 ) bean bean(bean 이름패턴 ) 44
POJO 기반 AOP 구현 - AspectJ 표현식 (4/4) 예 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) 45
POJO 기반 AOP 구현 POJO 기반 Advice 클래스작성 설정파일에 AOP 설정 Advice class 를 Bean 으로설정 <aop:aspect> 태그를이용해 Advice, Pointcut 을설정한다. 46
POJO 기반 AOP 구현 - Advice 설정관련태그 시점에따른 5 가지태그 before, after-returning, after-throwing, after, around 공통속성 pointcut-ref : pointcut 참조. <aop:pointcut> 태그의 id 명을넣어 pointcut 지정 pointcut : 직접 pointcut 을설정한다. method : Advice 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> 47
POJO 기반 AOP 구현 Advice 클래스작성 (1/6) POJO 기반의클래스로작성한다. 클래스명이나메서드명에대한제한은없다. 설정파일에서 Advice 등록시메소드명을등록한다. Advice 태그의 method 속성에서설정한다. 메소드구문은호출되는시점에따라달라질수있다. 48
POJO 기반 AOP 구현 Advice 클래스작성 (2/6) Before Advice 핵심관심사항메소드가실행되기전에실행됨 return type : 상관없으나 void로한다. argument : 없거나 JoinPoint 객체를받는다. <aop:before pointcut-ref= publicmethod method= beforelogging /> public void beforelogging(){ } 49
POJO 기반 AOP 구현 Advice 클래스작성 (3/6) After Returning Advice 핵심관심사항메소드실행이정상적으로끝난뒤실행됨 return type : 상관없으나 void 로한다. argument : 없거나 JoinPoint 객체를받는다. JoinPoint 는항상첫 argument 로사용된다. 대상메소드에서리턴되는값을 argument 로받을수있다. type : Object 또는대상메소드에서 return 하는 value 의 type <aop:after-returning pointcut-ref= publicmethod method= returnlogging returning= retvalue /> public void returnlogging(object retvalue){ } 50
POJO 기반 AOP 구현 Advice 클래스작성 (4/6) After Throwing Advice 핵심관심사항메소드실행중예외가발생한경우실행됨 return type : 상관없으나 void 로한다. argument : 없거나 JoinPoint 객체를받는다. JoinPoint 는항상첫 argument 로사용된다. 대상메소드에서전달되는예외객체를 argument 로받을수있다. <aop:after-throwing pointcut-ref= publicmethod method= throwinglogging throwing= ex /> public void throwinglogging(myexception ex){ // 대상객체에서리턴되는값을받을수는있지만수정할수는없다. } 51
POJO 기반 AOP 구현 Advice 클래스작성 (5/6) After Advice 핵심관심사항메소드실행이종료된뒤오류발생여부와상관없이무조건실행된다. return type : 상관없으나 void 로한다. argument : 없거나 JoinPoint 객체를받는다. <aop:after pointcut-ref= publicmethod method= afterlogging /> public void afterlogging(){ } 52
POJO 기반 AOP 구현 Advice 클래스작성 (6/6) Around Advice 앞의네가지 Advice 를다구현할수있는 Advice. return type : Object 또는 void argument [ 없거나 ] org.aspectj.lang.proceedingjoinpoint 를 argument 로지정한다. <aop:around pointcut-ref= publicmethod method= aroundlogging /> public Object aroundlogging(proceedingjoinpoint joinpoint) throws Throwable{ } //before 코드 try{ Object retvalue = joinpoint.proceed(); // 대상객체의메소드호출 //after-returning 코드 return retvalue; // 호출한곳으로리턴값넘긴다. 넘기기전수정가능 }catch(throwable e){ //after-throwing 코드 throw e; }finally{ } //after 코드 53
JoinPoint 대상객체에대한정보를가지고있는객체로 Spring container로부터받는다. org.aspectj.lang 패키지에있음 반드시 Advice 메소드의첫 argument로와야한다. 메소드들 Object gettarget() : 대상객체를리턴 Object[] getargs() : 파라미터로넘겨진값들을배열로리턴. 넘어온값이없으면빈배열개체가 return 됨. Signature getsignature () : 호출되는메소드의정보 Signature : 호출되는대상객체에대한구문정보를가진객체 String getname() : 대상메소드명리턴 String toshortstring() : 대상메소드명리턴 String tolongstring() : 대상메서드전체 syntax 를리턴 String getdeclaringtypename() : 대상메소드가포함된 type 을 return. (package 명.type 명 ) 54
@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 를가질수있다. 55
Web 에서 Spring ContextLoaderListener 설정파일 <context-param> 으로등록된설정파일을바탕으로 WebApplicationContext객체를생성해 ApplicationScope에속성으로 binding <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> 56
Web 에서 Spring WebApplicationContextUtil 를통해 WebApplicationContext 조회 getwebapplicationcontext(servletcontext) : WebApplicationContext 57
Spring MVC 58
Spring MVC 구성주요컴포넌트 DispatcherServlet Front Controller Controller 클라이언트요청처리를수행하는 Controller. HandlerMapping 클라이언트의요청을처리할 Controller 를찾는작업처리 View 응답하는로직을처리 ViewReslover 응답할 View 를찾는작업을처리 ModelAndView 응답할 View 와 View 에게전달할값을저장하는용도의객체 59
Spring MVC 흐름 (1/2) Spring MVC MVC 패턴기반웹개발프레임워크 2 Handler Mapping Client 1 Dispatcher Servlet ModelAndView 3 4 Controller 5 ViewResolver 6 View 60
Spring MVC 흐름 (2/2) 요청처리순서 1DispatcherServlet 이요청을수신 단일 Front controller servlet 요청을수신하여처리를다른컴포넌트에위임 어느컨트롤러에요청을전송할지결정 2DispatcherServlet 은 HandlerMapping 에어느컨트롤러를사용할것인지문의 3DispatcherServlet 은요청을컨트롤러에게전송하고컨트롤러는요청을처리한후결과리턴 비즈니스로직수행후결과정보 (Model) 가생성되어 JSP 와같은뷰에서사용됨 4ModelAndView 를생성하여 DispatcherServlet 에리턴 5ModelAndView 정보를바탕으로바탕으로 ViewResolver 에게 View 를요청 6View 는결과정보를사용하여화면을표현함. 61
Spring MVC 구현 Step Spring MVC 를이용한어플리케이션작성스텝 1.web.xml 에 DispacherServlet 등록및 Spring 설정파일등록 2.Spring 설정파일에 HandlerMapping 설정 3. 컨트롤러구현및 Spring 설정파일에등록 4. 컨트롤러와 JSP 의연결위해 View Resolver Spring 설정파일에등록 5.JSP(or View 작성후설정 ) 코드작성 Client Request Response Dispatcher Servlet Request Response Controller dosomething() Model 62
DispatcherServlet 설정과 ApplicationContext (1/2) 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>*.do</url-pattern> </servlet-mapping> Spring Container 는설정파일의내용을읽어 ApplicationContext 객체를생성한다. 설정파일명 : dispatcher-servlet.xml MVC 구성요소 (HandlerMapping, Controller, ViewResolver, View) 설정과 bean, aop 설정들을한다. 63
DispatcherServlet 설정과 ApplicationContext (2/2) Spring 설정파일등록하기 <servlet> 의하위태그인 <init-param> 에 contextconfiglocation 이름으로등록 경로는 Application Root부터절대경로로표시 여러개의경우, 또는공백으로구분 <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.dispatcherservlet</servlet-class> <init-param> <param-name>contextconfiglocation</param-name> <param-value>/web-inf/server-service.xml /WEB-INF/dao-service.xml </param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> 64
HandlerMapping Client 요청을처리할 Controller 를찾는역할 다양한 HandlerMapping 클래스를 Springframework 가제공하며 Spring 설정파일에 <bean> 으로등록하여설정한다. 종류 BeanNameUrlHandlerMapping bean 의이름과 url 을 mapping SimpleUrlHandlerMapping url pattern 들을 properties 로등록해처리 DefaultAnnotationHandlerMapping Annotation 기반 Controller 처리 65
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./> 66
Controller 작성 Controller 종류 Controller (interface) AbstractController MultiActionController Annotation기반 Controller 위의 interface/class 를상속하여 Controller 작성한다.(Annotation 기반 Controller 제외 ) 67
AbstractController (1/2) 가장기본이되는 Controller 작성 AbstractController 상속한다. public ModelAndView handlerequestinternal (HttpServletRequest request, HttpServletResponse response) throws Exception 오버라이딩하여코드구현 ModelAndView 에 view 가사용할객체와 view 에대한 id 값을넣어생성후 return 68
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", " 안녕 "); } } 69
MultiActionController (1/3) 하나의 Controller 에서여러개의요청처리지원 연관된 request 들을처리하는 controller 로직을하나의 controller 로묶을경우사용. 작성 MultiActionController 상속 client 의요청을처리할메소드구현 public [ModelAndView Map String void] 메소드이름 ( HttpServletRequest req, HttpServletResponse res [HttpSession Command]) [throws Exception]{} return type : ModelAndView, Map, void 중하나 argument : 1 번 - HttpServletRequest, 2 번 - HttpServletResponse 3 번 선택적이며 HttpSession 또는 Command or 3 번 HttpSession, 4 번 - Command 70
MultiActionController (2/3) MethodNameResolver 등록 역할 : 어떤메소드가클라이언트의요청을처리할것인지결정 Spring 설정파일에 <bean> 으로등록 controller에서는 property로주입받는다. 종류 ParameterMethodNameResolver : 요청 parameter로메소드이 름전송 InternalPathMethodNameResolver : url 마지막경로메소드이름으로사용 PropertiesMethodNameResolver : URL과메소드이름 mapping을 property로설정 71
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 name= /member.do" class="controller.multiaction.membercontroller"> <property name="methodnameresolver"> <ref bean="methodnameresolver"/> </property> </bean> 호출 : http://ip:port/applname/member.do?mode=registermember 72
Annotation 기반 Controller @Controller 컨트롤러클래스표시 @RequestMapping 요청 URL 등록, 처리할요청방식지정 구문 RequestMapping( 요청 url ) RequestMapping(value= 요청 URL method= 요청방식 ) Controller 클래스에등록 Controller 메소드에등록 Controller 클래스스프링설정파일에등록 1. <bean> 을이용해등록 2. 자동스캔 <context:component-scan base-package= package /> 73
Annotation 기반 Controller Controller 메소드에서요청파라미터처리 Transfer Object(Command) 이용 요청파라미터와매칭되는이름의 property 를가진 TO 요청파라미터 name 을이용한매개변수사용 같은이름으로여러개값이넘어올경우 String[] 사용 @RequestParam Annotation 사용 속성 value : 요청파라미터이름설정 required : 필수여부. 안넘어오면 400오류발생. 기본 : false defaultvalue : 값이안넘어올경우설정할기본값 74
Annotation 기반 Controller Controller 메소드이용가능매개변수타입 HttpServletRequest HttpServletResponse HttpSession 요청파라미터연결변수 요청파라미터를설정할 Transfer Object 객체 @CookieValue 적용매개변수 쿠키값매핑 @CookieValue(value= name, required=false) Map, Model, ModelMap View 에전달할모델데이터설정시사용 75
Annotation 기반 Controller Controller 메소드설정가능 return type ModelAndView : View 정보와응답데이터설정 View에전달할값설정 Map Model View는요청 URL로결정됨 String : View의이름리턴 View 객체 void Controller 메소드내에서응답을직접처리시사용 76
ModelAndView (1/2) Controller 처리결과후응답할 view 와 view 에전달할값을저장. 생성자 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 에 name-value 로저장하여한번에설정 - 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 (1/3) Controller 가넘긴 view 이름을통해알맞은 view 를찾는역할 1. Controller 는 ModelAndView 객체에응답할 view 이름을넣어 return. 2. DispatchServlet 은 ViewResolver 에게응답할 view 를요청한다. 3. ViewResolver 는 View 이름을이용해알맞는 view 객체를찾아 DispatcherServlet 에게전달. ViewResolver Spring 설정파일에등록한다. 79
ViewResolver (2/3) 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
ViewResolver (3/3) InternalResourceViewResolver JSP 나 HTML 등의내부자원을이용해뷰생성 InternalResourceView 를기본뷰로사용 BeanNameViewResolver 뷰의이름과동일한이름을가지는빈을 View 로사용 사용자정의 View 객체를사용하는경우주로사용 XmlViewResolver BeanNameViewResolver 와동일하나뷰객체를 Xml 파일에설정해놓는것이차이. Bean 등록시 location 프라퍼티에 xml 파일을지정 81
FileUpload - 파일업로드요청페이지 호출 JSP( 또는 HTML) 요청방식 : post <form enctype= multipart/form-data > input tag : <input type= file name= upfile /> name 속성의값은 upload 정보를저장할 TO(VO) 의 Attribute 와매칭된다. 여러개의파일을업로드할때 name 속성의값은이름 [0], 이름 [1] 형식으로작성 <input type= file name= upfile[0] /> <input type= file name= upfile[1] /> 82
FileUpload - Spring 설정파일 multipartresolver 빈으로등록 upload 를처리해주는 bean id/name 은반드시 multipartresolver 로등록 <bean id= multipartresolver class= org.springframework.web. multipart.commons. CommonsMultipartResolver /> Property defaultencoding 기본인코딩설정 maxuploadsize 업로드허용최대 size 를 byte 단위로지정. -1 은무제한 uploadtempdir 업로드파일일이저장될임시경로지정 maxinmemorysize 업로드파일을저장할최대메모리크기 83
FileUpload Controller 에서처리 Transfer Object 를통해받기 파일요청파라미터의이름과매칭되는 property 작성 파일의정보를저장할 property 는 MultipartFile 타입으로작성 @RequestParam 을통해받기 Controller 메소드의 MultipartFile 타입의매개변수사용 MultipartHttpServletRequest 이용 Controller 메소드의매개변수로 MultipartHttpServletRequest 를선언 주요메소드 getfilenames() : Iterator<String>- 업로드된파일명들조회 getfile(string name) : MultipartFile 업로드된파일정보조회 getfiles(string name):list<multipartfile>- 업로드된파일정보들조회 84
FileUpload - MultipartFile org.springframework.web.multipart.multipart File 업로드된파일정보를저장하는객체 getname() : String 요청파라미터의 name getoriginalfilename() : String upload 된파일명 getsize() : long 파일의크기 transferto(file dest) upload 된파일을특정경로로이동 isempty() : boolean upload 된파일이없으면 true getinputstream() : InputStream 업로드된파일과연결된 InputStream 리턴 85
ibatis 86
개요 JDBC 코드의패턴 Connection -> Statement -> 쿼리전송 -> 연결 close 모든 JDBC 코드는위의패턴을가진다. 이패턴을캡슐화하여 JDBC 코드를간편하게사용할수있도록 Framework 화가능 ibatis 란 SQL 실행결과를자바빈즈혹은 Map 객체에매핑해주는 Persistence 솔루션으로 SQL 을소스코드가아닌 XML 로따로분리해관리하도록지원 장점 SQL 문장과프로그래밍코드의분리 JDBC 라이브러리를통해매개변수를전달하고결과를추출하는일을간단히처리가능 자주쓰이는데이터를변경되지않는동안에임시보관 (Cache) 가능 트랜잭션처리제공 87
ibatis 설치 http://blog.mybatis.org 에서받는다. ibatis2.x.x 다운로드 88
ibatis 설치 압축을풀면 lib 디렉토리에 api가있다. API를 Application에설치 Standalone Application 어플리케이션 start 스크립트에클래스패스정의 java -cp ibatis-2.3.0.677.jar:... MyMainClass Web Application WEB-INF/lib 에추가 주 ) 다른경로에추가하면설정파일을찾지못하는문제가발생할수있다. 89
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> 90
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> 91
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); } } 92
ibatis 실행흐름도 SqlMapConfig SqlMaps SqlMaps Sql Map 파일 SqlMapConfig : 전역정보설정파일 SqlMaps : SQL 문관련설정파일 MappedStatement : 설정된쿼리를실행하는 ibatis 객체 input : SQL 문실행시필요한값 output : select 실행결과 Input HashMap TO(VO) Literal Mapped Statement Output HashMap TO(VO) Literal Database 93
ibatis 설정파일 설정파일은 XML 기반으로작성 SqlMapConfig 전역설정위한파일 : ibatis Framework 가실행되는데필요한여러설정들을한다. Transaction 관리정보, DataSource 생성을위한설정정보, SqlMap 파일의위치등 SqlMap SQL 문을등록 SQL 문을실행하기위해필요한 input Data 와 Output Data 에대한설정을한다. 설정파일들은작성후 classpath 내저장한다. 94
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"> 전역설정옵션 <sqlmapconfig> <settings usestatementnamespaces="false" cachemodelsenabled="true"/> 트랜잭션관리 DataSource 설정 SqlMap 파일참조 <transactionmanager type="jdbc"> <datasource type="simple"> <property name="jdbc.driver" value= " DriverClassName" /> <property name="jdbc.connectionurl" value="url" /> <property name="jdbc.username" value="user" /> <property name="jdbc.password" value="password" /> </datasource> </transactionmanager> <sqlmap resource= "sample/config/sqlmap.xml" /> </sqlmapconfig> 95
SqlMapConfig 설정 (2/4) <typealias> 요소 설정파일에서사용할클래스의별칭 (alias) 설정 SqlMap 에서도설정가능 ibatis 는정의된 alias 로언제든지원래 type 에접근가능 SqlMapConfig 에설정하면모든 SqlMap 에서사용가능 <typealias alias= mto type= member.to.memberto /> Framework 에서미리정의하여제공하는 typealias Transaction manager : JDBC, JTA, EXTERNAL Data types : string, int, long, double, boolean, hashmap arraylist, object 등 Data source factory : SIMPLE, DBCP, JNDI 96
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, 계정정보등 97
SqlMapConfig 설정 (4/4) <sqlmap> 요소 SQL 문을가지고있는설정파일인 SQL Map 파일의위치지정 resource 속성 : class path 상의 SQL Map 파일 여러파일지정가능 98
ibatis 를통한 SQL 문실행 ibatis의 JavaBean select insert update delete Parameter 매핑 Result 매핑 99
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() Dot 표기법 anorder.account.username anorder.getorderitem().get(0).getproductid() anorder.orderitem[0].productid anobject.getid() anobject.getname() anobject.id anobject.name 100
ibatis 를통한 SQL 실행 - 개요 Sql Map SQL 문설정, Input Data, Output Data 를설정하는 xml 기반설정파일 Sql Map 파일은 SqlMapConfig 에등록한다. 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 의메소드를이용해등록한쿼리를실행시킨다. 101
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 설정 102
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> 103
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"> <typealias type="member.to.memberto" alias="mto"> <insert id="insertmember" parameterclass="mto"> INSERT INTO MEMBER (ID, PASSWORD, NAME, ADDRESS, MILEAGE) VALUES(#id#, #password#, #name#, #address#, #mileage#) </insert> <update id="updatemember" parameterclass="mto"> 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="mto"> SELECT ID, PASSWORD, NAME, ADDRESS, MILEAGE FROM MEMBER WHERE ID=#value# </select> </sqlmap> 104
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 한다. SQL 문내 mapping 방법 #parameter name# $parameter name$ 인라인파라미터 parameter name» Transfer Object(TO, VO): getter 와 matching» Map : key 와 matching? 외부파라미터매핑 105
Parameter mapping (2/3) # 지시자로인라인 parameter 사용? 로바꾼뒤값을치환한다. PreparedStatement 형식 타입에맞게치환처리 (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_ID = abc ; User user = (User)client.queryForObject("selectUser", "abc"); 106
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_NAME LIKE %$value$% </select>... where user.name like % 송 % ; List<User> allusers = client.queryforlist("selectallusers", 송 ); 107
Parameter 매핑 외부매핑 (1/2) Parameter 매핑의두가지방안 인라인매핑 SqlMap Mapping문내부에서바로기술함 매핑이복잡한경우명시적이지못함 외부매핑 외부에서정의됨 보다명시적임 인라인매핑과외부매핑은같이사용할수없다.? 와매칭되어값이할당된다. 인라인매핑의예 외부매핑의예 <insert id="createcategory" parameterclass="deptto"> insert into departments values( #deptid#, #deptname#, #managerid#,#loc.locationid# ) </insert> <parametermap class= deptto" 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> 108
Parameter 매핑 외부매핑 (2/2) 외부 Parameter 매핑 속성 property javatype jdbctype 설명 매핑문에전달할 JavaBean property 명칭또는 Map value 의 key. 들어갈이름을매핑문에필요한만큼반복해서정의할수있음. 예 ) update 문에서 set 절과 where 절에동일한이름이반복적으로들어갈수있음. 세팅될 parameter 의 Java property 타입을명시적으로정의 세팅될 parameter 의데이터베이스타입을명시적으로정의예 ) Java 타입이 Date( java.util.date) 인경우 jdbctype 을 DATE 인지 DATETIME 인지명시할필요가있음 nullvalue nullvalue 에명시된값이 JavaBean property 에서넘어오면 null 값을넣어준다. 외부 Parameter 매핑이유용한경우 인라인 Parameter 매핑이잘동작하지않을경우 성능을향상시킬경우 명시적매핑을할경우 109
Result 매핑 (1/3) 명시적 Result 매핑 <resultmap> : 하나의 resultclass 에대한설정 속성 : id, class <result> : 하나의 property 와 resultset 의 Column 매핑 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 타입을로드할수있음들어갈값은반드시다른매핑문의이름이어야함. 110
Result 매핑 (2/3) Primitive result ibatis 는 primitive 형태의결과를허용하지않음 (int, long, double,..) Wrapping 된형태의타입을리턴 (Integer, Long, Double,..) <select id= getallordercount" resultclass= int"> select count(*) as cnt from order </select> Integer allcount = (Integer)client.queryForObject( getallordercount ); JavaBean(TO) 타입으로 Wrapping 할경우 primitive 형태의결과를얻을수있음 public class ResultTO{ private int ordercount; public int getordercount() { return ordercount; } public void setordercount(int ordercount) { this.ordercount = ordercount; } } <resultmap id="primitiveresultmapexample" class= ResultTO > <result property="ordercount" column= cnt" /> </resultmap> 111
Result 매핑 (3/3) JavaBean 과 Map Result 의장단점 Bean 방식장점단점 성능향상컴파일타임의이름체크 IDE 에서 Refactoring 지원가능 Type casting 이적음 get, set 메소드필요 Map 코드량이적음 느리다컴파일타임체크불가런타임오류가많음 Refactoring 지원이없음 112
SELECT 구문실행 (1/4) SqlMap : <select> 태그이용 속성 id : 프로그램에서호출할이름 resultclass, resultmap : SELECT 문실행결과를담을객체 parameterclass, parametermap : PARAMETER 를받아올객체 SqlMapClient queryforobject() : 0 또는 1 개의 row 를가져올때사용 unique 한값으로조회시 Object queryforobject(string id) throws SQLException; Object queryforobject(string id, Object parameter) throws SQLException; Object queryforobject(string id, Object parameter, Object result) throws SQLException; 첫번째메소드 : parameter 없이조회 두번째메소드 : SQL Map 에정의된 select 문 id 와해당파라미터로사용 두번째메소드 : 결과결과를담을객체를넣음. no-argument 생성자가없는 resultclass 를사용해야하는경우사용 1 개이상의 row 가리턴된경우 Exception 발생 113
SELECT 구문실행 (2/4) SqlMapClient queryforlist() 메소드 1개이상의 row가리턴될경우사용 결과를 List로리턴함 select 결과의 1개의 row resultclass의객체 resultclass 객체들 List List queryforlist(string id) throws SQLException; List queryforlist(string id, Object parameter) throws SQLException; List queryforlist(string id, Object parameter, int skip, int max) throws SQLException; 첫번째, 두번째메소드 : queryforobject 와동일 세번째메소드 : DB 에서가져온전체 row 중일부만사용하고싶은경우사용 예 ) DB 에서 100 건을가져올때이중앞의 10 건만취하고싶으면 skip=0, max=10 114
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( selectaccountlist,null,"accountid"); Map accountmap = sqlmap.queryformap( selectaccountlist,null,"accountid", "ownername"); 115
SELECT 구문실행 결과매핑 (4/4) 자동 Result Map select 문실행결과를자동으로객체에매핑가능함 단일 column 매핑 count(id) 값이 Integer 타입으로자동매핑된다. <select id= selectaccountcnt resultclass="int"> select count(accountid) from Account </select> Integer cnt = (Integer) client.queryforobject( selectaccountcnt ); 다중 column 매핑 select 문의 column 명과결과객체의 Bean property 명이일치해야함 <select id="selectaccountlist" resultclass= AccountTO > select account_id as id, owner_name as name, balance from account </select> public class AccountTO{ setid(string id){} setname(string name){} setbalance(long balance){} } 116
INSERT SqlMap : <insert> 태그사용 속성 id : 프로그램에서호출할이름 parameterclass, parametermap : PARAMETER 를받아올객체 Sub tag <selectkey> : insert 시사용할파라미터를조회할경우사용 속성 : resultclass, keyproperty SqlMapClient insert() 사용 Object insert(string id) throws SQLException; Object insert(string id, Object parameter) throws SQLException; return value : Object <selectkey> 를통해조회한 result 객체 117
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 개수 118
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 개수 119
Dynamic SQL 개요 Dynamic 태그 120
개요 언제사용하는가? 하나의 sql 태그에서쿼리구문을조건에따라동적으로만들때사용 예를들어 where 절의비교구문이파라미터객체의조건에따라달라질경우 예 ) 조회시제약조건에사용할검색키워드가있을수도 null 일수도있을경우. name=#name# 또는 name IS NULL <select id= selectmember" parameterclass= to.memberto" resultclass= to.memberto"> SELECT * FROM member <dynamic prepend="where "> <isnull property="name"> name IS NULL </isnull> <isnotnull property="name"> writer =#name# </isnotnull> </dynamic> </select> 파라미터로넘어온 wirter 에값이없는경우 (null 인경우 ) 파라미터넘어온 wirter 에값이있는경우 121
Dynamic 태그 Dynamic 태그종류및속성 dynamic : Root 태그 4 가지카테고리 binary, unary, parameter, iterate 공통속성 prepend, open, close WHERE 구문을앞에추가 <dynamic prepend="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 가첫번째로 Add 되는경우는생략한다. 122
Dynamic 태그 <dynamic> 태그 Dynamic 태그의가장상위태그 (Root 태그 ) 다른 dynamic 태그안에포함될수없음 접두 / 접미구문을위한수단제공 (prepend, open, close) prepend ( 옵션 ) open ( 옵션 ) close ( 옵션 ) 맨앞에접두구문을붙인다. ( 예 : WHERE ) Body 에내용이없을경우접두구문은생략된다. Body 의내용앞에붙여짐. Body 의내용이없을경우생략된다. prepend 와동시에정의될경우 prepend 다음에나타난다. Body 의내용뒤에붙여짐. Body 의내용이없을경우생략된다. 123
Dynamic 태그 Binary 태그 주어진 Parameter 객체간의 property 값을비교 태그의조건이충족되는경우 Body내용이나타난다. 태그속성 property( 필수 ) Parameter 객체의 property. comparevalue 또는 compareproperty 에서비교하는데쓰인다. prepend( 옵션 ) 맨앞에접두구문을붙인다. 이구문이생략되는경우 1. Body 의내용이없는경우 2. 부모태그속성이 removefirstprepend= true 이고현재태그가부모 Body 의첫번째요소인경우 open( 옵션 ) Body 의내용앞에붙여짐. Body 의내용이없을경우생략된다. prepend 와동시에정의될경우 prepend 다음에나타난다. close( 옵션 ) Body 의내용뒤에붙여짐. Body 의내용이없을경우생략된다. removefirstprepend( 옵션 ) 첫번째자식태그의 prepend 를생략시킴 compareproperty property 와비교할 property 이름 comparevalue property 속성에의해비교되는값 ( 상수 ) 124
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 속성보다작거나같은지비교 125
Dynamic 태그 Binary 태그 ( 계속 ) Binary 태그예제 <select id="getshippingtype" parameterclass="cartto" resultclass="shippingto"> SELECT * FROM Shipping <dynamic prepend="where "> <isgreaterequal property="weight" comparevalue="100"> shippingtype='freight' </isgreaterequal> <islessthan property="weight" comparevalue="100"> shippingtype='standard' </islessthan> </dynamic> </select> CartTO.getWeight() >= 100 인지체크 CartTO.getWeight() < 100 인지체크 126
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 를생략시킴 127
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 <isnotempty property="producttype"> producttype=#producttype# </isnotempty> </select> Product.getProductType!= null 이고 Product.getProductType.length() > 0 인지체크 128
Dynamic 태그 Parameter 태그 Parameter 가매핑문에들어왔는지체크하는태그 태그속성 : prepend, open, close, removefirstprepend 태그종류 <isparameterpresent> Parameter 가존재하는지체크 <isnotparameterpresent> Parameter 가존재하지않는지체크 <select id="getproducts" resultclass="product"> SELECT * FROM Products <isparameterpresent prepend="where "> <isnotempty property="producttype"> producttype=#producttype# </isnotempty> </isparameterpresent> </select> 이 select 매핑문에들어오는어떤 Parameter 든지존재하는지체크 129
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 로구분됨 130
Transaction 관리 131
ibatis Transaction 관리 Auto Transaction Local Transaction 132
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); } 133
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 설정 134