(출처:http://www.dil.univ-mrs.fr/~massat/docs/hibernate-3.1/reference/ko/html_single/)
하이버네이트의 기본 개념은 위와 같다.
orm(object relation mapping )기반 이며, spring data의 jpa 역시 내부적으로 hibernate를 감싸서 만들었다.
예제들은 아파치에서 무료로 제공하는 derby 를 사용한다. 사실 머 db는 상관없다.
먼저 pom파일을 보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>3.4.0.GA</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>3.3.2.GA</version> </dependency> <dependency> <groupId>org.apache.derby</groupId> <artifactId>derbyclient</artifactId> <version>10.12.1.1</version> </dependency> | cs |
hibernate를 추가하고 derby database client를 추가한다.
context.xml을 살펴보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="configLocation" > <value>hibernate.cfg.xml</value> </property> </bean> <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"> <property name="sessionFactory"> <ref bean="sessionFactory" /> </property> </bean> </beans> | cs |
hibernate.cfg.xml이라는 설정파일이 보이고 hibernateTemplate이라는 객체가 보인다. 위와 같이 설정해주자.
다음은 hibernate.cfg.xml 설정이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="connection.driver_class">org.apache.derby.jdbc.ClientDriver</property> <property name="connection.url">jdbc:derby://localhost:1527/hibernateDb</property> <property name="connection.username">user</property> <property name="connection.password">password</property> <!-- SQL dialect --> <property name="dialect">org.hibernate.dialect.DerbyDialect</property> <property name="hibernate.default_schema">TESTSCHEMA</property> <!-- session을 사용하기 위한 정의 없으면 No CurrentSessionContext configured! 요에러 뜬다. --> <property name="current_session_context_class">thread</property> <!-- JDBC connection pool (use the built-in) --> <property name="connection.pool_size">2</property> <!-- Echo all executed SQL to stdout --> <property name="show_sql">true</property> <!-- Drop and re-create the database schema on startup <property name="hbm2ddl.auto">create</property>--> </session-factory> </hibernate-configuration> | cs |
여기서 중요한 건 dialect이다. 모든 db마다 dialect가 있고 아마도 저넘이 database마다 존재 하는 것으로 봐선 sql문으로 변환을 해주는 느낌이다. 그리고 마지막 부분의 hdm2ddl.auto 라는 넘이 있는데 저 구분을 활성화 하면 할때마다 기존 것들을 지우고 다시 만든다. derby는 설치하기 쉬우니 생략~
모든 설정이 끝났다. 다음 글에서 부터 예제를 만들어보자.
pom.xml은 바뀐게 없다. 저번에 설명을 못한 부분이 있는데 weaving이라는 것이다. 이부분은
http://najuung.tistory.com/65 이분의 사이트를 참조하라
바로 소스로 들어가자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"> <context:annotation-config></context:annotation-config> <context:component-scan base-package="com.gno.sample"></context:component-scan> <aop:aspectj-autoproxy /> <bean id="simpleCalcService" class="com.gno.sample.service.SimpleCalcServiceImpl"></bean> <bean id="calcDao" class="com.gno.sample.dao.CalcDaoImpl"></bean> <bean id="loggingAspect" class="com.gno.sample.aop.SimpleAopAspect"></bean> </beans> | cs |
기존 aop:config에서 scan과 annotation-config, autoproxy 가 추가 되었다. 그리고 기존 pointcut과 expression등은 사라졌다. simpleAppAspect 클래스를 살펴보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | package com.gno.sample.aop; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; @Aspect public class SimpleAopAspect { @Before("execution(* com.gno.sample.dao.CalcDAO.*(..)) ") public void before(JoinPoint joinPoint) { System.out.println("before!"); Signature signature = joinPoint.getSignature(); Object target = joinPoint.getTarget(); Object[] args = joinPoint.getArgs(); System.out.println("Signature : " + signature.toString()); System.out.println("target : " + target.toString()); System.out.println("name : " + signature.getName()); System.out.println("longName : " + signature.toLongString()); System.out.println("shortName : " + signature.toShortString()); } @After("execution(* com.gno.sample.dao.CalcDAO.*(..))") public void after(JoinPoint joinPoint) { System.out.println("after!"); Signature signature = joinPoint.getSignature(); Object target = joinPoint.getTarget(); Object[] args = joinPoint.getArgs(); System.out.println("Signature : " + signature.toString()); System.out.println("target : " + target.toString()); System.out.println("name : " + signature.getName()); System.out.println("longName : " + signature.toLongString()); System.out.println("shortName : " + signature.toShortString()); } } | cs |
Aspect oriented Programming 관점 지향 프로그래밍... 이다.
(출처:http://ezquest.tistory.com/entry/Spring)
위 그림처럼 logging이라던가 security(login 관련) 또는 transaction 이라던가를 횡단으로 특정한 곳을 보는 관점 지향 하는 프로그래밍이다. 여기에 사족을 좀 덧 붙이자면, 관점 지향이라고 해서 무언가 autowired된 객체를 변환한다던가 또는 기존 객체를 변환한다던가는 하지 못한다. 단지. 내가 보고자 하는 부분에 대해 지정한 일을 한다는 것이다.
예를 들면, 이런 이런 객체에 로깅을 한다. 또는 exception에 대해 로그를 남긴다. 또는 전체 세션에 대해 로그인을 감지한다. 마지막으로 트랜잭션에 대해 처리를 한다. 이런 일들을 도맡아 한다. 멤캐쉬 redis캐쉬, ehcached 역시 aop로 처리를 한다.
그럼 바로 aop 관련 예제를 보자.
1 2 3 4 5 6 7 8 9 10 11 | <!-- Aspectj --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.6.11</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.6.11</version> </dependency> | cs |
pom.xml 설정은 위에 두가지를 선언한다.
다음은 context.xml 설정이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd"> <bean id="simpleCalcService" class="com.gno.sample.service.SimpleCalcServiceImpl"></bean> <bean id="calcDao" class="com.gno.sample.dao.CalcDaoImpl"></bean> <bean id="loggingAspect" class="com.gno.sample.aop.SimpleAopAspectXML"></bean> <!-- aspect: 관점. 걍 aspect에 이용할 클래스로 라고 지정 advice: 어느 시점에 실행 될지 정하는 구분자 (before, after, throw, around) pointcut: 쳐다보고 있는 기준 함수 정의 expression: pointcut 에 입력하는 문법 (<리턴타입> <클래스>.<메소드><(매개변수)>) --> <aop:config> <aop:aspect id="aspect" ref="loggingAspect"> <aop:pointcut expression="execution(* com.gno.sample.dao.CalcDAO.*(..))" id="pointCut"/> <aop:before method="before" pointcut-ref="pointCut"/> <aop:after method="after" pointcut-ref="pointCut"/> </aop:aspect> </aop:config> </beans> | cs |
마지막 부분에 aop:config 라는 설정이 있다.
pointcut은 어느 객체를 횡단간 관심을 주냐는 거다. 이후 특정 메소드에 before,after, after-returning, after-throwing등 설정을 하여 pointcut의 id를 넘겨준다.
그리고 미리 설정해놓은 loggingAspect를 aop:config에 전달한다.
그럼 loggingAspect 소스를 보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | package com.gno.sample.aop; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import com.gno.sample.service.SimpleCalcService; //@ContextConfiguration(locations={"file:src/main/resources/aop-context.xml"}) @ContextConfiguration(locations={"file:src/main/resources/aop-context_xml.xml"}) @RunWith(SpringJUnit4ClassRunner.class) public class AopTest { @Autowired public SimpleCalcService simpleCalcService; @Test public void test(){ int returnVal = simpleCalcService.add(1, 1); assertThat(returnVal, is(2)); } } | cs |