[SPRING] 강의초급 : 스프링 MVC 하루만에 배우기 2 xml 셋팅/SQL 쿼리문

jychae·2022년 11월 22일
0

스프링

목록 보기
2/12
post-thumbnail

pom.xml

\SampleSpringYse\pom.xml

<!-- Database 설정 시작 -->
		<!--
    		mybatis 는 xml로 쿼리를 작성하게 해주는 라이브러리입니다.
			쿼리를 문자열로 코딩하지 않고 xml을 사용해서 관리하게 해줍니다.
		 -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.5.4</version>
		</dependency>
        

		<!-- 
			mybatis-spring은 스프링과 mybatis를 연동하게 해주는 라이브러리입니다.
		 -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
			<version>2.0.4</version>
		</dependency>
        
        
		<!-- 
			jdbc는 자바에게 데이터베이스에 접속하기 위한 api
			spring-jdbc는 스프링에서 jdbc를 통해 데이터베이스와 연결할 수 있게 해줍니다.
		 -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>${org.springframework-version}</version> 
            <!-- <properties> 에 있는 버전을 사용하는 것임! -->
		</dependency>
        
        
		<!-- 
			dbcp2는 데이터베이스 커넥션 풀
			데이터베이스 서버와 웹 서버는 서로 다른 프로그램이고,
			실무에서는 전혀 다른 컴퓨터에 설치되어 있을 가능성이 높습니다.
			서로 다른 컴퓨터와 프로그램이 통신을 하기 위해서는 서로 연결을 맺는 과정이 필요합니다.
			미리 데이터 베이스와 연동하기 위한 길을 만들어 놓는 라이브러리입니다.
			최근들어 dbcp2보다 hikaricp를 자주 사용하기도 하지만 dbcp2를 추천
		 -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-dbcp2</artifactId>
			<version>2.7.0</version> 
		</dependency>
        
        
		<!-- 
			로깅을 위한 라이브러리
			데이터베이스에 연동하는 쿼리를 콘솔이나 파일 로그로 볼 수 있게 해줍니다.
		 -->
		<dependency>
			<groupId>org.bgee.log4jdbc-log4j2</groupId>
			<artifactId>log4jdbc-log4j2-jdbc4</artifactId>
			<version>1.16</version> 
		</dependency>
        
        
		<!-- 
			https://mvnrepository.com/artifact/com.oracle.database.jdbc/ojdbc8
			oracle 데이터 베이스 연동 라이브러리
		 -->
		<dependency>
			<groupId>com.oracle.database.jdbc</groupId>
			<artifactId>ojdbc8</artifactId>
			<version>21.1.0.0</version> 
		</dependency>

이클립스 셋팅에 추가로 넣어준 아이들


log4j.xml

\SampleSpringYse\src\test\resources\log4j.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

	<!-- Appenders -->
	<appender name="console" class="org.apache.log4j.ConsoleAppender">
		<param name="Target" value="System.out" />
		<layout class="org.apache.log4j.PatternLayout">
			<param name="ConversionPattern" value="%-5p: %c - %m%n" />
		</layout>
	</appender>
	
	<!-- Application Loggers -->
	<logger name="kr.or.ddit">
		<level value="info" />
	</logger>
	
	<!-- 3rdparty Loggers -->
	<logger name="org.springframework.core">
		<level value="info" />
	</logger>	
	
	<logger name="org.springframework.beans">
		<level value="info" />
	</logger>
	
	<logger name="org.springframework.context">
		<level value="info" />
	</logger>

	<logger name="org.springframework.web">
		<level value="info" />
	</logger>

	<!-- Root Logger -->
	<root>
		<priority value="debug" />
		<appender-ref ref="console" />
	</root>
	
</log4j:configuration>

web.xml

\SampleSpringYse\src\main\webapp\WEB-INF\web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

   <!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
   <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/spring/root-context.xml</param-value>
   </context-param>
   
   <!-- Creates the Spring Container shared by all Servlets and Filters -->
   <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
   </listener>
   
   <!--
      스프링 프레임워크에서 한글 처리 즉, UTF-8 인코딩 처리를 도와주는 필터를 제공한다 
      브라우저에서 보내는 요청 (request)과 응답 (response)을 모두 UTF-8로 고정하기 위해 인코딩 필터를 설정한다 
   -->
   <filter>
      <filter-name>encodingFileter</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>encodingFileter</filter-name>
      <url-pattern>/*</url-pattern>
   </filter-mapping>

   <!-- Processes application requests -->
   <servlet>
      <servlet-name>appServlet</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <init-param>
         <param-name>contextConfigLocation</param-name>
         <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
      </init-param>
      <load-on-startup>1</load-on-startup>
   </servlet>
      
   <servlet-mapping>
      <servlet-name>appServlet</servlet-name>
      <url-pattern>/</url-pattern>
   </servlet-mapping>

</web-app>

스프링 프레임워크에서 한글 처리 -> UTF-8 인코딩 처리를 도와주는 필터


root-context.xml

\SampleSpringYse\src\main\webapp\WEB-INF\spring\root-context.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 https://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<!-- Root Context: defines shared resources visible to all other web components -->
		
	<!-- 
		데이터소스
		- 데이터베이스 관련 정보를 데이터 소스 (dataSource)라고 한다.
		
		jdbc:oracle:thin:@localhost:1521:xe
		- jdbc를 이용하여 oracle 드라이버로 현재 localhost 데이터베이스에 접속합니다.
		  username은 데이터 베이스 사용자명, password는 데이터베이스 비밀번호 입니다.
	 -->
	<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
		<property name="url" value="jdbc:oracle:thin:@localhost:1521:xe"/> 
		<property name="username" value="사용자명"/>
		<property name="password" value="비밀번호"/>
	</bean>	
	
	<!-- 
		sqlSessinFactory는 데이터베이스와 연결을 맺고 끊어질 때까지의 라이프 사이클을 관리하는 sqlSession 객체를 만듭니다.
		sqlSessinFactory 객체의 프로퍼티는 총 두가지입니다.
		1) 데이터 소스를 설정하는 프로퍼티
		2) mapper 파일의 위치를 지정하는 프로퍼티
		   mapper 파일은 실제 쿼리 내용이 담겨있는 파일들입니다.
	-->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource"/>
		<property name="mapperLocations" value="classpath:/sqlmap/**/*_SQL.xml"/>
	</bean>
	
	<!-- 
		sqlSessionTemplat은 데이터 베이스에 개별적으로 쿼리를 실행시키는 객체
		sqlSessionTemplate을 소스코드에서 사용하여 쿼리를 실행시킨다
		sqlSessionTemplate빈은 sqlSessinFactory객체를 생성자로 받고
		sqlSession객체가 가지고 있는 데이터베이스 접속 정보와mapper 파일의 위치를 알 수 있다.
		
		ex) SqlSessionTemplate sqlSessionTemplate = new SqlSessionFactory();
	 -->
	<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg index="0" ref="sqlSessionFactory"/>
	</bean>
</beans>

dataSource / sqlSessinFactory / sqlSessionTemplat


book_SQL.xml

\SampleSpringYse\src\main\resources\sqlmap\book_SQL.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!-- 
	[참고 사이트] 마이바티스
	- https://mybatis.org/mybatis-3/ko/getting-started.html
	
	마이바티스는 무엇인가요?
	- 마이바티스는 개발자가 지정한 SQL, 저장 프로시저 그리고 몇가지 고급 매핑을 지원하는 퍼스스턴스 프레임워크입니다.
	  마이바티스는 JDBC로 처리하는 상당 부분의 코드와 파라미터 설정 및 결과 매핑을 대신해줍니다.
	  마이바티스는 데이터 베이스 레코드에 원시타입과  Map 인터페이스 그리고 자바 POJO를 설정해서
	  매핑하기 위해 XML과 어노테이션을 사용할 수 잇습니다.
	  
	  *** POJO란?
	  -  POJO(Plain Old Java Object)란, 순수한 자바 객체를 말합니다.
	  그리고, 객체지향적인 원리에 충실하면서, 환경과 기술에 종속되지 않고 필요에 따라 재활용될 수 있는 방식으로 설계되 오브젝트
	  객체지향원리를 기반으로 설계된 오브젝트 (getter/setter를 이용한 VO들)
	  
	  namespace 항목은 쿼리가 여러개 일 때 이름 공간 (namespace)을 분리하는 역할을 한다.
	  쿼리 XML 파일은 보통 여러개 생성되기 때문에 이를 구별하는 용도로 사용합니다.
 -->

<mapper namespace="Book">
	
	 <!-- 
	 	데이터 입력을 SQL쿼리 작성방법
	 	
	 	INSERT INTO 테이블명(컬럼1, 컬럼2,,,) VALUES(값1, 값2,,,,)
	 	id항목은 namespace  안에서 쿼리를 구분하는 유일한 식별자 역할을 합니다.
	 	parameterType은 쿼리에 적용할 파라미터타입(현재 Map타입을 사용합니다.)
	 	useGeneratedKeys와 keyProperty는 하나의 쌍으로 작성됩니다.
	 	useGeneratedKeys가 true로 설정되면 mybatis는 insert 쿼리 실행 후 생성된 pk를 파라미터 객체의
	 	keyProperty 속성에 넣어줍니다.(예제를 통해 dao에서 확인할 수 있습니다.)
	 	
	 	useGeneratedKeys : 시퀀스로 증가된 번호값을 가져올 것인지에 대한 여부 설정( 번호값은 우리 프로젝트에서 사용되어지는 틀)
	 	keyProperty  : 여부 true 설정시, 어떤 필드 값으로 받을 것인지 설정
	 	
	 	mybatis는 쿼리를 실행할 때 파라미터를 치환하는데 #{title}은 파라미터로 입력된 키를 값으로 치환합니다.
	 	map.get("title") == "제목" 형태가 mybatis 쿼리 xml에 전달되면 mybatis는 #{title}을 "제목"으로 자동변환합니다.
	 	#{title}, #{category}, #{price} > {"제목", "카테고리", 1000} 이렇게 치환됩니다.
	 	
	 	<![CDATA[...]]> 항목은 원시(Raw) 문자열을 나타내는데, 해당 문자열 안에 '<','>' 등의 태그 문자가 있더라도
	 	태그로 인식하지 않고 쿼리의 정상적인 형태로 인식할 수 있게 도와줍니다.
	  -->
	<insert id="insert" parameterType="hashMap" useGeneratedKeys="true" >
		<selectKey keyProperty="book_id" resultType="int" order="BEFORE"> 
			SELECT SEQ_BOOK.NEXTVAL FROM DUAL
		</selectKey>
		<![CDATA[
		INSERT INTO BOOK(
			BOOK_ID, TITLE, CATEGORY, PRICE
		) VALUES (
			#{book_id}, #{title}, #{category}, #{price}
		)
		]]>
	</insert>	
	
	<!-- 
		데이터 조회 SQL 쿼리 작성방법
		SELECT TITLE, CATEGORY, RPICE, INSERT_DATE
		FROM BOOK
		WHERE BOOK_ID = 1
		resultType은 SELECT 쿼리가 실행된 후 반환된 값을 담을 컨테이너 타입을 말합니다.
	 -->
	<select id="selectBook" parameterType="hashMap" resultType="hashMap"> <!-- 리턴해서 담을꺼 필요 -->
		SELECT
			BOOK_ID, TITLE, CATEGORY, PRICE, INSERT_DATE
		FROM BOOK
		WHERE BOOK_ID = #{bookId}	
	</select>
	
	<update id="update" parameterType="hashMap">
		UPDATE BOOK
		SET
			TITLE = #{title},	
			CATEGORY = #{category},	
			PRICE = #{price}
		WHERE BOOK_ID =	#{bookId}
	</update>
		
	<delete id="delete" parameterType="hashMap">
		DELETE FROM BOOK
		WHERE BOOK_ID = #{bookId}
	</delete>
	
	<!-- 
		책 정렬을 위해서 ORDER BY 구문을 사용합니다.
		작은 순서부터 정렬하기 위해서는 ASC
		큰 순서로 정렬하기 위해서는 DESC를 사용합니다.
		
		WHERE 1=1은 관습적인 구문
		1=1은 늘 참이기 때문에 WHERE절을 나타낼 때 사용
		조건이 2개 이상일 경우 처음에 시작하는 조건은 WHERE절로 시작하고 두번째로 시작하는 조건은 AND이어야하기 때문
		
		마이바티스 if문은 조건을 나타냄
		test는 조건 규칙을 나타내는데 키워드가 있는 경우, if문의 쿼리들이 동작합니다.
		이때 쿼리의 내용이 파라미터가 아니라 마이바티스 규칙에 의해서 변경되는 것을 동적쿼리라고 합니다.
		CDATA 항목 안에는 if문의 작동이 되지 않기 때문에 CDATA를 사용하는 구문은 별도로 구별해서 사용하여야합니다.
		
		SQL 쿼리 조건에서 포함을 나타내는 구문은 LIKE 절입니다.
		- TITLE LIKE '검색어%' : 검색어로 시작
		- TITLE LIKE '%검색어' : 검색어로 종료
		- TITLE LIKE '%검색어%' : 검색어를 포함
	 -->
	<select id="selectBookList" parameterType="hashMap" resultType="hashMap">
		SELECT
			BOOK_ID, TITLE, CATEGORY, PRICE, INSERT_DATE
		FROM BOOK
		WHERE 1=1 <!-- 그냥 참 조건을 하나 만들어 둔 것, and 조건을 쓰게 상황을 만들어줌, 상황에 따라 알고리즘이 달라지니 확인 -->
		<if test="keyword != null and keyword != ''">
			AND
			(
				TITLE LIKE '%'||#{keyword}||'%' OR
				CATEGORY LIKE '%'||#{keyword}||'%'			
			)
		</if>
		ORDER BY INSERT_DATE DESC	
	
	</select>
		
</mapper>

useGeneratedKeys 인서트를 하고 나면 한줄 행이 나오고
그거 날리면 결과값 1이나 0이 날라오죠 그값을 리턴받았을때

바로 게시글에 대한 번호값은 아니잖아요 근데 상세보기 어케 되는 거죠 ?
-> 상태값을 받지만 그 해당 게시글의 번호를 같이 리턴 받아야 상세보기 페이지로 보내줘야 그 결과가 보이겠죠
-> 그때 사용하는게 useGeneratedKeys !
나는 인서트를 때리고 반환되는 값중에 pk로 설정된 값을 두고 그거도 받겠다.
근데 얘 useGeneratedKeys 혼자서는 못쓰고 그안에 selectKey랑 keyProperty = "컬럼명" 있어야함! (3가지)
그 한줄의 값이 여기에 담겨서 리턴됩니다.
-> <! [CDATA[ ]]> where절 태그가 아니고 쿼리의 일종이야! 묶어준 애들은 쿼리에 사용되어지는 문자라고 인식하게 해주는 것!


profile
안녕하세요! 초보개발자 공부 시작!

0개의 댓글