티스토리 뷰

728x90
지금까지는 jar파일을 lib폴더에 직접 넣어서 DB와 연결했다면,
이번에는 Maven Respository 통해서 Spring framework에 적용할 수 있는

dependency를 추가해 DB와 연결해보자


XML ver

 

 

 

 

프로젝트 생성

Project Explorer에서 빈공간에 우클릭하면 Dynamic Web Project 만들 수 있다!
여기까진 할 수 있잖아

 

방금 만든 그 프로젝트를 Maven Project로 만들어주자!

혹시 다시 Maven 제거하고 싶다면, 위의 그림처럼 Disabled Maven Nature 해주믄 되니꽈

아! 메이븐 설정하고 프로젝트에 오류뜨면 그냥 alt+F5로 마무리해주십시다

 

 

 

 

 

 

Maven Repository에서 dependency 가져오기

MariaDB를 쓰고 있으니 Spring에서 mariadb를 사용할 수 있도록 해주는 dependency를 가져오자

https://mvnrepository.com/artifact/org.springframework/spring-jdbc/5.2.9.RELEASE

 

 

자바를 통해 db에 연결할 수 있는 connector인 JDBC를 Spring에서 사용할 수 있도록 Spring JDBC를 가져온다

https://mvnrepository.com/artifact/org.springframework/spring-jdbc/5.2.9.RELEASE

 

 

 

 DB와 연결할 수 있도록  Database Connection역할을 해주는 Spring DBCP를 가져오자

https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2/2.9.0

 

 

 

다음은 관계형 DB와 객체지향 애플리케이션을 쉽게 매핑해주는 MyBatis를 가져오자
이전에는 jar파일로 했었지

https://mvnrepository.com/artifact/org.mybatis/mybatis/3.5.7

 

 

MyBatis를 Spring에서 사용할 수 있도록 해주는 MyBatis-Spring도 가져오자

https://mvnrepository.com/artifact/org.mybatis/mybatis-spring

 

 

가져온 dependency를 토대로 해서 Maven 기본설정 해보자!

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>Ex26MyBatisXML</groupId>
  <artifactId>Ex26MyBatisXML</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
   <!-- 소스의 디렉토리 구조, 빌드 산출물 디렉토리 구조, 빌드시 사용할 플러긴 정보 관리 -->
  <build>
  	<!-- sourceDirectory : 자바 소스 코드를 관리하는 디렉토리 -->
  	<sourceDirectory>src/main/java</sourceDirectory>
  
	<!-- Maven제공 기능은 플러긴 기반으로 작동 따라서 설정 필요 -->  
    <plugins>
    
	  <!-- 컴파일 플러그인 설정 -->
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
        	<!-- 16>14변경 -->
          <release>14</release>
        </configuration>
      </plugin>
      
      <!-- 배포 패키징 플러긴 설정 -->
      <plugin>
        <artifactId>maven-war-plugin</artifactId>
        <version>3.2.3</version>
        <!-- configuration 추가 -->
        <configuration>
        	<!-- 배포할 위치 directory -->
        	<warSourceDirectory>src</warSourceDirectory>
        </configuration>
      </plugin>
    </plugins>
  </build>
  
  <!-- 라이브러리 버전관리 : properties -->
  <properties>
  	<javax.servlet-version>4.0.1</javax.servlet-version>
  	<javax.servlet.jsp-version>2.3.3</javax.servlet.jsp-version>
  	<javax.servlet.jsp.jstl-version>1.2</javax.servlet.jsp.jstl-version>
  	<org.springframework>5.2.2.RELEASE</org.springframework>
  </properties>
  
  <!-- 라이브러리 셋팅 : dependencies 프로그램과 의존관계인 라이브러리 관리 -->
  <dependencies>
  
  	<!-- servlet-api 라이브러리 적용 위한 설정 -->
	<dependency>
	    <groupId>javax.servlet</groupId>
	    <artifactId>javax.servlet-api</artifactId>
	    <!-- 버전관리는 properties에서 하기 때문에 변수처럼 사용하기 -->
	    <version>${javax.servlet-version}</version>
	    <scope>provided</scope>
	</dependency>
	
  	<!-- javax.servlet.jsp-api 라이브러리 적용 위한 설정 -->
	<dependency>
	    <groupId>javax.servlet.jsp</groupId>
	    <artifactId>javax.servlet.jsp-api</artifactId>
	    <!-- 버전관리는 properties에서 하기 때문에 변수처럼 사용하기 -->
	    <version>${javax.servlet.jsp-version}</version>
	    <scope>provided</scope>
	</dependency>

	<!-- javax.servlet/jstl 라이브러리 적용 위한 설정 -->
	<dependency>
	    <groupId>javax.servlet</groupId>
	    <artifactId>jstl</artifactId>
	    <!-- 버전관리는 properties에서 하기 때문에 변수처럼 사용하기 -->
	    <version>${javax.servlet.jsp.jstl-version}</version>
	</dependency>
	
	<!-- spring-webmvc 라이브러리 적용 위한 설정 -->
	<dependency>
	    <groupId>org.springframework</groupId>
	    <artifactId>spring-webmvc</artifactId>
	    <!-- 버전관리는 properties에서 하기 때문에 변수처럼 사용하기 -->
	    <version>${org.springframework}</version>
	</dependency>
	
	<!-- resource 어노테이션 안먹혀서 추가함.. 요상하군... -->
	<dependency>
		<groupId>javax.annotation</groupId>
		<artifactId>javax.annotation-api</artifactId>
		<version>1.3.2</version>
	</dependency>
	
	<!-- validation-api를 사용하기 위한 설정 -->
	<dependency>
	    <groupId>javax.validation</groupId>
	    <artifactId>validation-api</artifactId>
	    <version>2.0.1.Final</version>
	</dependency>
	
	<!-- hibernate-validator를 사용하기 위한 설정 -->
	<dependency>
  	  	<groupId>org.hibernate.validator</groupId>
  	 	<artifactId>hibernate-validator</artifactId>
 	 	<version>6.2.1.Final</version>
	</dependency>
	
	
	<!-- jar파일 사용하지 않고 라이브러리로 사용하기 -->
	<!-- mariadb를 연결하기 위한 라이브러리로 jar파일 대신 -->
	<!-- https://mvnrepository.com/artifact/org.mariadb.jdbc/mariadb-java-client -->
	<dependency>
	    <groupId>org.mariadb.jdbc</groupId>
	    <artifactId>mariadb-java-client</artifactId>
	    <version>2.7.4</version>
	</dependency>
	<!-- Spring JDBC -->
	<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
	<dependency>
	    <groupId>org.springframework</groupId>
	    <artifactId>spring-jdbc</artifactId>
	    <version>5.2.9.RELEASE</version>
	</dependency>
	<!-- Connection역할 -->
	<!-- 트랙잭션 제어 역할 -->
	<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2 -->
	<dependency>
	    <groupId>org.apache.commons</groupId>
	    <artifactId>commons-dbcp2</artifactId>
	    <version>2.9.0</version>
	</dependency>
	
	<!-- MyBatis를 사용하기 위한 라이브러리 -->
	<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis/3.5.7 -->
	<dependency>
	    <groupId>org.mybatis</groupId>
	    <artifactId>mybatis</artifactId>
	    <version>3.5.7</version>
	</dependency>
	
	<!-- MyBatis-spring을 사용하기 위한 라이브러리 -->
	<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring/2.0.6 -->
	<dependency>
	    <groupId>org.mybatis</groupId>
	    <artifactId>mybatis-spring</artifactId>
	    <version>2.0.6</version>
	</dependency>
	
	<!-- 어노테이션 사용을 위한 라이브러리 -->
	<!-- https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api -->
	<dependency>
	    <groupId>javax.annotation</groupId>
	    <artifactId>javax.annotation-api</artifactId>
	    <version>1.3.2</version>
	</dependency>
	
	<!-- aspectj사용을 위한 라이브러리 -->
	<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
	<dependency>
	    <groupId>org.aspectj</groupId>
	    <artifactId>aspectjweaver</artifactId>
	    <version>1.9.6</version>
	    <scope>runtime</scope>
	</dependency>
	
	
	
  </dependencies>
</project>

@Resource가 안먹혀서 dependency 추가함..
여기선 Validator안쓸 것 같긴 한데, 만약 쓴다면 또 가져와야 하므로 그냥 넣어뒀다~

추가로 어노테이션, ASPECTJ사용하기 위한 depencency도 넣어줌
https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api

https://mvnrepository.com/artifact/org.aspectj/aspectjweaver

 

 

 

Spring MVC XML 기본설정

일단 Spring MVC를 어떻게 구현할지 구조부터 대충 살펴보면,
전에 JSP MVC 패턴때 bean.xml 만들어서 bean을 정의해주었지
그 역할을 이젠 web.xml 이용해서 XML버전으로 만들어보자

아까 Java버전으로 치자면 ServletConfigClass의 역할을 얘가 하는거여

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
 	<!-- 현재 웹 애플리케이션에러 받아들이는 모든 요청에 대해 appServlet이란 이름으로 정의된 서블릿 사용 -->
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

	<!-- 설정 정보를 분석해 controller 선택하는 서블릿 지정 -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<!-- Spring MVC에서 저공하는 기본 서블릿 지정 -->
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<!-- Spring MVC 설정을 위한 XML파일 지정 -->
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/config/servlet-context.xml</param-value>
		</init-param>
		<!-- 로드는 딱 한 번만 시키기 : 서버 꺼질 때까지 한 번만 실행 -->
		<load-on-startup>1</load-on-startup>
	</servlet>

	<!-- Bean정의할 XML 파일 지정 -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/config/root-context.xml</param-value>
	</context-param>

	<!-- 리스너 설정 -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- 파라미터 인코딩 필터 설정 -->
	<filter>
		<filter-name>encodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
		<init-param>
			<param-name>forceEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>

	<filter-mapping>
		<filter-name>encodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
</web-app>

 

 

이제 web.xml에서 context-param을 보면 bean을 정의할 xml파일을 지정해두었잖아?
root-context.xml 그걸 한 번 만들어보자

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans 
	xmlns="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc
						http://www.springframework.org/schema/mvc/spring-mvc.xsd
						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.xsd
                 		http://www.springframework.org/schema/tx
						http://www.springframework.org/schema/tx/spring-tx.xsd
                 		http://www.springframework.org/schema/aop
						http://www.springframework.org/schema/aop/spring-aop.xsd">




	<!-- properties에 설정해둔 DB 접속 정보 파일 사용할 수 있도록 Bean 정의 -->
	<beans:bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<beans:property name="location">
			<beans:value>/WEB-INF/properties/db.properties</beans:value>
		</beans:property>
	</beans:bean>
	
	<!-- 상단에서 정의한 DB 접속 정보 파일 값을 불러와 접속 정보 관리하는 Bean 정의 -->
	<beans:bean class="org.apache.commons.dbcp2.BasicDataSource" id="basicDataSource">
		<beans:property name="driverClassName" value="${db.classname}"/>
		<beans:property name="url" value="${db.url}"/>
		<beans:property name="username" value="${db.username}"/>
		<beans:property name="password" value="${db.password}"/>
	</beans:bean>
	
	<!-- DB접속 정보와 mapper파일(쿼리문 담긴 파일) 관리하는 Bean정의  -->
	<!-- 접속정보 관리 Bean을 대입해서 DB와 연결 가능하게 함 -->
	<beans:bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSession" >
		<beans:property name="dataSource" ref="basicDataSource"/>
		<beans:property name="mapperLocations" value="/WEB-INF/mapper/*.xml"/>
	</beans:bean>
	
	<!-- 쿼리문 전달하는 Bean정의 : 이 Bean을 주입받아서 필요한 쿼리 실행 -->
	<!-- mapper파일 관리하는 Bean 대입해 쿼리문 전달 -->
	<beans:bean class="org.mybatis.spring.SqlSessionTemplate" id="sqlSessionTemplate">
		<beans:constructor-arg index="0" ref="sqlSession"></beans:constructor-arg>
	</beans:bean>
	
	
	<!-- 트랜잭션 제어 객체 bean 1 -->
	<beans:bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
		<beans:property name="dataSource" ref="basicDataSource"/>
	</beans:bean>
	
	
	<!-- 트랜잭션 제어 객체 bean 2 -->
	<beans:bean class="org.springframework.transaction.support.TransactionTemplate" id="transactionTemplate">
		<beans:property name="transactionManager" ref="transactionManager"/>
	</beans:bean>

	
</beans:beans>

분명 간단했던 Root-context.xml였는데.. 엄청난 양으로 돌아왔다!!!!

일단 상단에 beans:beans태그 안에 xml, xmlns, xsi로 필요한 springframework들을 추가해준다
mvc, beans, content, p, tx 요정도

먼저, PropertyPlaceholderConfigurer로 properties파일 내부 정보를 DB연결에 활용하기 위해 Bean으로 정의 해준다
자바 버전에서는 @PropertySource의 역할을 beans:property로 하는 것이지
beans:value안에 DB연결 정보 담은 파일을 넣어주면 DB접속 정보 bean설정 끝

이제 설정한 그 DB정보들을 관리해줄 Bean을 정의해보자
아까 pom.xml파일에서 주입한 dbcp2 라이브러리를 통해 사용할 수 있는 BasicDataSource를 사용할꾸
bean정의면서 id 명명해주면 DB연결할 때 어떤 정보를 사용할 건지 ref로 쉽게 대입할 수 있어
beans:property로 DB연결시 필요한 각 부분을 name에 설정하고,
value에 EL형식으로 db.properties파일에 등록한 내용들을 변수 활용해 끌어올 수 있다.
이게 가능해진 이유는 바로 위에서 properties파일을 bean객체로 정의해줬기 때문쓰

이제 DB를 직접 연결하고, 쿼리문이 담긴 Mapper.xml파일을 관리하는 SqlSessionFactoryBean을 정의해보자
DB접속 정보는 버로 위에서 BasicDataSource사용했던 고것!
bean 정의하면서 id 명명해두면 DB연결할 때 href로 대입해서 사용한다고 했잖아?
그게 바로 여기임!
ref에다가 명명한 id 넣으면 알아서 척척 가져다가 DB연결할 때 쓰는거야
그리고 쿼리문 담긴 파일은 이따가 만들건데 Mapper.xml이라고 할거야
name에는 앞으로 부를 이름, value에는 Mapper.xml파일을 만들 위치를 넣어줍니돠으
그리고 얘도 bean에 id를 달아주면, 쿼리 실행하는 bean에 주입할 때 id로 넣으면 되니까 달아주자구

이제 쿼리문을 받아서 직접 실행할 수 있는 Bean을 만들어보려해
SqlSessionTemplate을 이용할거야!
다른건 없고, beans:constructor-arg 태그 이용해서 어떤 파일에 있는 쿼리를 넣을 것인지를 설정해
우리는 바로 위에서 DB연결하고, 쿼리문 파일 관리하는 SqlSessionFactoryBean을 정의했잖아
id까지 줬고, 그걸 ref에 넣어주면 땡 

 

트랜잭션 제어하는 bean 객체는 총 3개를 정의할거야
여기서는 2개만 보이는데, 나머지는 servler-context에 있어

왜냐면 web.xml에 보면 servlet-context가 먼저 지정되고, 그 다음 root-context가 지정되어서
발생하는 순서때문에 @Transactonal이라는 어노테이션이 안먹히거든..
그래서 그 애는 servlet-context에 정의해줄거야
나머지 2개를 한 번 보자구 그럼 

트랜잭션 제어할 객체는 bean에 DataSourceTransactionManager와 TransactionTemplate를 주입해서 사용할거야
id를 붙여줘서 Service에서 사용할 수 있도록 해주자

DataSourceTransactionManager객체는 property로 접속정보 관리하는 bean인 basicDataSource을 넣어주고,
TransactionTemplate객체는 DataSourceTransactionManager로 정의한 bean을 property로 가져간다

 

 

 

 

properties파일에 db 연결 정보 정의
 db.classname = org.mariadb.jdbc.Driver
 db.url = jdbc:mariadb://127.0.0.1:3306/scott
 db.username = root
 db.password = 비밀이지롱

요로케 설정하면 위에서 알아서 해당하는 이름 찾아서 쏙쏙 가져간다~ 이 말썸!

 

 

 

 

 

 

 

 

이번엔 web.xml에서 servlet을 보면 설정 정보 분석해서 controller를 선택해주는 서블릿 경로를 만들어뒀어
servlet-context.xml이건데, 그걸 한 번 해보자고

<?xml version="1.0" encoding="UTF-8"?>
<!-- mvc는 beans:beans로 태그 변경해야 인식함 -->
<beans:beans
	xmlns="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc
						http://www.springframework.org/schema/mvc/spring-mvc.xsd
						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.xsd
                 		http://www.springframework.org/schema/tx
						http://www.springframework.org/schema/tx/spring-tx.xsd
                 		http://www.springframework.org/schema/aop
						http://www.springframework.org/schema/aop/spring-aop.xsd">


	<!-- 스캔한 패키지 내부 클래스 중 @Controller 있는 클래스 controller로써 로딩하도록 설정 -->
	<annotation-driven />

	<!-- 스캔할 bean들이 모여있는 패키지 지정 -->
	<context:component-scan base-package="kr.co.goodee39.controller" />
	<!-- MyBatis와 트랜잭션 제어를 위한 service 패키지 지정 -->
	<context:component-scan base-package="kr.co.goodee39.service" />

	<!-- Controller의 메서드에서 반환하는 문자열 앞, 뒤에 붙일 경로 정보 셋팅 -->
	<beans:bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>


	<!-- 정적파일(img, video, audio) 로드 설정 -->
	<resources mapping="/**" location="/resources/" />
	
		
	
	<!-- 트랜잭션 제어 객체 bean 3 -->
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<!-- txData로 시작하는 모든 메서드에 대한 -->
			<tx:method name="txData*" propagation="REQUIRED"/>
		</tx:attributes>
	</tx:advice>
	
	<aop:config>
		<aop:pointcut expression="execution( * kr.co..*.*(..))" id="transactionMethod1"/>
		<aop:advisor advice-ref="txAdvice" pointcut-ref="transactionMethod1"/>
	</aop:config>
	
	<!-- 트랜잭션 제어 객체 bean 4 : 多사용 -->
	<tx:annotation-driven/>
	
</beans:beans>

Java때랑 내용이 같은데, 표현법이 다른거야
annotaion-driven은 클래스에 @Controller달린걸 찾을 수 있게 도와주는 아이야
context:component-scan으로 controller 찾아낼 경로 설정해주고, 

beans:bean에서는 아까 Java에서 경로 자동으로 /WEB-INF/views/파일명.jsp 완성되도록 설정했어
prefix, suffix가 위치에 따른 설정인거쥐

마찬가지로 정적파일 즉 오디오, 사진, 비디오를 위한 파일을 불러오기 위한 폴더를 설정해주는데
resources로 할 수 있다.
mapping="/**"라는건 어떤 위치이든 뭐 그런 뜻일까...?ㅎㅎㅎㅎ
(이제 알았음.. 모든 경로에 위치한 파일이라는 뜻임!!!)

 

root-context에서 트랜잭션 객체 설명할 때 얘기했던, web.xml에 정의된 servlet 순서에 따라
servlet-context가 먼저 수행되면서 발생하는 문제 때문에 트랜잭션 2개를 servlet-context로 가져왔다.

tx:advice태그로 선언하는 방법이 있다.
txData로 시작하는 모든 메서드에 대해 트랜잭션 제어를 가능하게 하고, propagation은 기본값이 REQUIED이고,
다른 옵션은 REQUIRES_NEW, MANDATORY, NESTED, NEVER, SUPPORTS, NOT_SUPPORTED가 있다고 한다..
https://deveric.tistory.com/86

 

[Spring] 트랜잭션의 전파 설정별 동작

트랜잭션의 전파 설정이란 Spring에서 사용하는 어노테이션 '@Transactional'은 해당 메서드를 하나의 트랜잭션 안에서 진행할 수 있도록 만들어주는 역할을 합니다. 이때 트랜잭션 내부에서 트랜잭

deveric.tistory.com

이 분 블로그에서 봤는데 설명을 엄~청 쉽게 잘해주셨다.. 👏👏👏👏👏👏👏

propagation은 이미 존재하는 트랜잭션의 유무에 따라서 어떻게 트랜잭션을 처리할지 방법을 정해주는 것!
required설정은 기본값으로 이미 기존에 존재하는 트랜잭션이 있다면 거기 올라탄다
즉 기존에 있던 트랜잭션이 롤백되면 같이 롤백된다는 말썸~
나머지는 상단 블로그 내용 참조 ㅎㅎ

 

tx:annotation-driven태그는 @Transactional로 표기한 트랜잭션 메서드를 읽어 알아서 처리해주는 기능이다..
깔끔하니 좋다.
다만 단점이 있다면, @Transactional은 public 메서드에서만 적용되고
@Transactional 걸린 메서드가 동일한 클래스 내에서 호출되는 일이 있다면 트랜잭션이 정상작동 불가하다

 

 

Controller 클래스 만들기

아까 위에서 web.xml보면 servlet에서 appServlet이란 이름으로 설정한 controller 선택 서블릿이 있는데,
servlet-context.xml라고 파일 하나 만들었좌나,
그리고 @Controller로 지정한 파일 알 수 있도록 annotaion-driven 태그 달아줬고,
context:component-scan으로 controller 찾아낼 경로 설정까지 했으니 이제 @Controller단 클래스를 하나 만들기야

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class HomeController {
	
	//ServletAppContext에서 설정한 configureViewResolvers()메소드 통해서 
	///WEB-INF/views/index.jsp로 변환됨
	@RequestMapping(value="/", method=RequestMethod.GET)
	public String home() {
		return "index";
		
	}
}

별건 없어
그냥 무슨 역할하는지 보자고!

위에서 계속 언급했듯 이 클래스는 controller의 역할을 할 클래스이므로 어노테이션으로 이름표 달아주고,
메소드를 하나 만드는데, 이 메소드는 무어냐
첫 페이지 역할, 그러니까 home 역할을 할 페이지를 설정하는 메서드야
그래서 이름도 home이야 후후
value는 우리 JSP MVC 패턴에서 servlet만들면 맨 상단에 

@WebServlet("/블라블라")하는 공간이 있어 (ㄴㅇㄹ는 무시혀~ 걍 쓴거임)
저 블라블라는 보통 servlet이름이 들어가는데, 파일을 실행시켜서 이동한다거나 하면
url에 저기 작성된 이름이 뒤에 뜨더라고?
근데 이걸 /만 남기고 지워주면?!
그냥 RequestDispatcher rdp = request.getRequestDispatcher("");에서 설정한 jsp파일이 home으로 떠부러
servlet이라는 위치가 jsp파일 앞전에 안붙기 때문이지!
그거랑 같은 이치야 value = "/"는

아무턴, return "문자열";은 이따가 만들 home이 될 jsp파일 이름을 넣어준거야
이 controller가 실행되면 index라는 홈이름이 아까 위에서 servlet-context.xml로 설정한 beans를 통해
prefix="/WEB-INF/views/"와 suffix=".jsp"를 만나 /WEB-INF/views/문자열.jsp가 되는거지

그리고 index.jsp에 이미지가 있다면 resources태그 통해서
src 앞에 /resources/가 콱 붙어주겠지~ 

 

이 아래부터는 Java버전이랑 동일합니다!

 

 

 

 

 

 

DB에 테이블 하나 만들어 놓기

 

컬럼 3개를 갖는 springsample 테이블 하나를 생성해두었음!

 

 

 

 

 

 

HomeController에서 설정한 첫 페이지가 되어줄 index.jsp를 만들자
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<!-- SPRING + MYBATIS -->
	<h1>SPRING + MYBATIS</h1>
	<br />
	
	<a href="input_data">Input_Data</a><br />
	<a href="read_data">Read_Data</a><br />
	<br />
	<hr />
	<h3>트랜잭션</h3>
	<a href="tx_data1">트랜잭션_data1</a><br />
	<a href="tx_data2">트랜잭션_data2</a><br />
	<a href="tx_data3">트랜잭션_data3</a><br />
</body>

input_data 페이지로 이동시 DataVO1를 커맨드 객체로 받는 inputData메서드가 실행된다!
read_data 페이지로 이동시 DataVO1를 커맨드 객체로 받는 readData메서드가 실행된다!

트랜잭션은 tx_data1, tx_data3은 오류가 발생하도록 해놓은 상태고, tx_data2는 정상실행이다
tx_data1, tx_data3의 쿼리 결과가 어떻게 진행되는지 보자 

 

 

 

 

 

VO객체 만들기
public class DataVO1 {

	private String column1;
	private String column2;
	private String column3;
	
	public DataVO1() {
		// TODO Auto-generated constructor stub
	}

	public String getColumn1() {
		return column1;
	}

	public void setColumn1(String column1) {
		this.column1 = column1;
	}

	public String getColumn2() {
		return column2;
	}

	public void setColumn2(String column2) {
		this.column2 = column2;
	}

	public String getColumn3() {
		return column3;
	}

	public void setColumn3(String column3) {
		this.column3 = column3;
	}
	
	
}

요르케 DB에 맞춰서 컬럼따라 설정하고, getter, setter 메서드를 만들어서 
다른데서 가져다가 설정하고, 사용도 할 수 있도록 한다

 

 

 

 

 

 

 

 

Mapper.xml파일 만들기~
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  
  <!-- https://mybatis.org/mybatis-3/ko/getting-started.html -->
  <!-- 매핑된 SQL 구문 살펴보기에서 가져옴 -->
<mapper namespace="springsample">

  <insert id="insertSmp" parameterType="kr.co.goodee39.vo.DataVO1">
    INSERT INTO springsample(column1, column2, column3) VALUES(#{column1}, #{column2}, #{column3})
  </insert>
  
  <select id="selectSmp" resultType="kr.co.goodee39.vo.DataVO1">
  	SELECT column1, column2, column3 FROM springsample
  </select>
</mapper>

쿼리문이야 쿼리문
자바의 MapperInterface 역할을 하는 파일이지
아까 root-context에서 sqlSession라는 아이디로 db연결 정보와 쿼리문을 관리하는 bean을 정의할 때
mapperLocations라는 이름으로 정의한 프로퍼티의 /WEB-INF/mapper/*.xml라는 value를 넣었었지
걔가 얘야 얘는 지금 저 path에 위치하고 있어

만일 파일이 여러개여도 /*.xml 로  value를 먹였기 때문에 다 적용돼

 

 

 

 

 

 

Controller 만들기
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import kr.co.goodee39.service.TestService;
import kr.co.goodee39.vo.DataVO1;

@Controller
public class TestController {
	
	//TestService 주입하기
	@Autowired
	TestService service;

	@GetMapping("/input_data")
	public String inputData(DataVO1 vo1) {
		//DataVO1 커맨드 객체 받아서 form:form의 modelAttribute와 연결
		return "input_data";
	}
	
	@PostMapping("/input_pro")
	public String inputPro(DataVO1 vo1) {
		
		service.setData(vo1);
		
		return "input_pro";
	}
	
	//TestService 통해서 model에 담아둔 select문 결과를 service통해서 다시 받아주기!
	@GetMapping("/read_data")
	public String readData(Model model) {
		
		service.getData(model);
		
		return "read_data";
	}
	
	
	//트랜잭션 제어 객체1 사용한 이동
	//현재 Model은 아무런 내용 없음..
	//Serive 클래스에서 도출값 있으면 addAttribute로 설정해줘야함!
	@GetMapping("/tx_data1")
	public String txData1(Model model) {
		
		String result = service.txData1(model);
		
		return result;
		
	}
	
	//트랜잭션 제어 객체2 사용한 이동
	//현재 Model은 아무런 내용 없음..
	//Serive 클래스에서 도출값 있으면 addAttribute로 설정해줘야함!
	@GetMapping("/tx_data2")
	public String txData2(Model model) {
		
		service.txData2(model);
		
		return "tx_data2";
	}
	
	
	//트랜잭션 제어 객체3 사용한 이동
	@GetMapping("/tx_data3")
	public String txData3(Model model) {
		
		service.txData3(model);
		
		return "tx_data3"; 
	}

		
}

먼저 Bean등록한 MapperInferface / DataSourceTransactionManager / TransactionTemplate를
@Autowired로 주입해서 모두가 쓸 수 있도록 헌다

1) inputData()  메서드

input_data url타고 실행된 메서드 inputData에서 DataVO1를 주입받아줍니다으~
그래야 form:form에 modelAttribute로 설정해둔 dataVO1을 받아줄 수 있찌유~

2) inputPro() 메서드

이동한 input_data페이지에서는 JAVA버전과는 다르게 Service클래스를 만들어서
안에 메서드를 담아서 실행하는 것으로 한다 

성공적으로 수행되면 input_pro페이지로 이동되는데,
성공적 수행이라 함은 DB에 값이 잘 저장되었다 이말썸~

3)  readData()  메서드

DB를 한 번 읽어서 출력해보려는 심산이얌
마찬가지로 service를 통한 메서드 실행으로 데이터를 뽑아온다
inputPro 메서드 통해서 잘 주입되었다면 좌르륵 나오겠지?

 

 

 

그 밑에 트랜잭션을 제어하기 위한 수단으로 이번에는 service 클래스를 이용해서 할 것!
그러니 controller자체에서는 service내부 메서드 호출하는 것으로 간단히 마무리!

4)  txData1() 메서드

마찬가지로 service 내 메서드 실행
자바와 다른 점은 자바는 controller에서 try ~catch 문 통해서
트랜잭션 예외처리를 할 수 있었는데, 여기서는 controller에서도 service에서도
도통 return 페이지이름이 안먹힌다...
그래서 그냥 service측에서 return값을 주기로 했다...
에러페이지 말고 예외처리 하고 싶었어 !! 한 번쯤은!!!
아무튼 정상 처리시 tx_data1, 예외처리시 tx_error 값을 나오게 설정해뒀어 service에서
그럼 그 값따라서 return이 결정되겠지

 

5) txData2()  메서드

마찬가지로 service 내 메서드 실행
예외처리에 따른 페이지 이동 없음

 

6) txData3()  메서드

마찬가지로 service 내 메서드 실행
예외처리에 따른 페이지 이동 없음

 

 

 

 

이동될 페이지 만들기!
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<!-- SPRING + MYBATIS -->
	<h1>SPRING + MYBATIS</h1>
	<br />
	
	<form:form modelAttribute="dataVO1" action="input_pro" method="post">
		data1 : <form:input path="column1" type="text"/><br />
		data2 : <form:input path="column2" type="text"/><br />
		data3 : <form:input path="column3" type="text"/><br />
		<form:button type="submit">확인</form:button><br />
	</form:form>
	
</body>
</html>

얘가 바로 input_data페이지로 modelAtrribute를 dataVO1으로 가지고 있으며
action이 input_pro로 inputPro메서드를 실행시키게 된다
data1, 2, 3는 각각 column1, 2, 3데이터에 주입될 값이다

 

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<!-- SPRING + MYBATIS -->
	<h1>SPRING + MYBATIS</h1>
	<br />
	<h1>Input_Pro DB에 데이터 저장 완</h1>
</body>
</html>

 

성공적으로 mapper.insertData(vo1)수행되면 넘어갈 페이지고
DB에 반영이 되었다는 증거~

 

 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<!-- SPRING + MYBATIS -->
	<h1>SPRING + MYBATIS</h1>
	<br />
	<!-- readData메서드에서 처리된 model을 통해 설정한 list라는 attribute를={list} obj이란 이름으로 받아준다 -->
	<c:forEach var="obj" items="${list}">
		<!-- {명명한 이름.컬럼명}으로 출력-->
		<li>${obj.column1}, ${obj.column2}, ${obj.column3}</li>
	</c:forEach>
	

</body>
</html>

read_data 성공적으로 출력시 요기 도착해서 데이터 보여줌!

 

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<!-- SPRING + MYBATIS -->
	<h1>SPRING + MYBATIS</h1>
	<br />
	<h3>트랜잭션</h3>
	<h1>트랜잭션_data1</h1>
	<br />
	<h3>DB가 추가 완.</h3>
</body>
</html>

트랜잭션 1 성공시 이동될 페이지 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<!-- SPRING + MYBATIS -->
	<h1>SPRING + MYBATIS</h1>
	<br />
	<h3>트랜잭션</h3>
	<h1>트랜잭션_error</h1>
	<br />
	<h3>Rollback 완.</h3>

</body>
</html>

tx_data1에서 예외발생시 이동할 페이지

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<!-- SPRING + MYBATIS -->
	<h1>SPRING + MYBATIS</h1>
	<br />
	<h3>트랜잭션</h3>
	<h1>트랜잭션_data2</h1>
	<br />
	<h3>DB가 추가됐을지, Rollback일지 모르나 일단 완.</h3>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<!-- SPRING + MYBATIS -->
	<h1>SPRING + MYBATIS</h1>
	<br />
	<h3>트랜잭션</h3>
	<h1>트랜잭션_data3</h1>
	<br />
	<h3>DB가 추가됐을지, Rollback일지 모르나 일단 완.</h3>
</body>
</html>

tx_data2, tx_data3는 예외처리 없이 그냥 무조건 한 페이지로만 이동하게 설정해놓았음
따라서 예외가 발생하든, 정상 처리되든 같은 페이지로만 이동되어서 뭔지 모르겠으나 일단 완으로 적음 후후

 

 

 

 

 

 

 

 

home으로 만들었던 index페이지에서 진짜 이동 되는지 한 번 해보자!

Run on Server를 클릭해주쟈

 

결과

728x90
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
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
글 보관함