Spring Framework 2)

Jinmin Kim·2021년 5월 20일
0

Spring

Spring MVC

MVC 기능 수행 과정
웹 -> DispatcherServlet -> HandlerMapping -> Controller -> ModelAndView
-> DispatcheerServlet -> ViewResolver -> View -> DispatcheerServlet -> 웹

Spring JDBC

web.xml - ContextLoaderListener를 사용해서 빈 설정 XML 파일 읽어들이기
action-servlet.xml - 스프링에서 필요한 여러가지 빈 설정
action-dataSource.xml - 스프링 JDBC 설정에 필요한 정보 설정
jdbc.properties - 데이터베이스 연결 정보 저장
action-service.xml - 서비스 빈 생성 설정

//web.xml
   //여러 설정 읽기위해 ContexetLoaderListener 설정
   <listener>	
   	<listener-class>
   		org.springframework.web.context.ContextLoaderListener
   	</listener-class>
   </listener>
   
   <context-param>
   	<param-name>contextConfigLocation</param-name>
   	<param-value>
    //ContexetLoaderListener로 해당위치의 설정 파일 읽어들이기
         /WEB-INF/config/action-service.xml
         /WEB-INF/config/action-dataSource.xml
   	</param-value>
   </context-param>
   
   <servlet>
      <servlet-name>action</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <load-on-startup>1</load-on-startup>
   </servlet>

   <servlet-mapping>
      <servlet-name>action</servlet-name>
      <url-pattern>*.do</url-pattern>
   </servlet-mapping>
//action-servlet
...

 	<bean id="viewResolver"
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="viewClass"
			value="org.springframework.web.servlet.view.JstlView" />
		<property name="prefix" value="/WEB-INF/views/" />
		<property name="suffix" value=".jsp" />
	</bean>
	<bean id="memberController" class="com.spring.member.controller.MemberControllerImpl">
		<property name="methodNameResolver">
			<ref local="methodResolver" />
		</property>
		<property name="memberService" ref="memberService" />
	</bean>
	
	<bean id="methodResolver" 
		class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
		<property name="mappings">
			<props>
				<prop key="/member/listMembers.do">listMembers</prop>
				<prop key="/member/addMember.do">addMember</prop>
				<prop key="/member/memberForm.do">memberForm</prop>
				<prop key="/member/memberDetail.do">memberDetail</prop>
			</props>
		</property>
	</bean>

	<bean id="urlMapping"
		class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
		<property name="mappings">
			<props>
				<prop key="/member/*.do">memberController</prop>
			</props>
		</property>
	</bean>
</beans>

//action-service.xml
...
	<bean id="memberService" class="com.spring.member.service.MemberServiceImpl">
	<!--memberService bean memberDAO 속성에  memberDAO 빈을 주입시킨다 -->
		<property name="memberDAO" ref="memberDAO" />
	</bean>
    
//action-dataSource.xml
	<bean id="propertyConfigurer"
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
			<!-- jdbc.properties에서 설정정보를 가지고온다  -->
				<value>/WEB-INF/config/jdbc.properties</value>
			</list>
		</property>
	</bean>
	<!-- jdbc.properties 4가지 설정정보로 SimpleDriverDataSource 빈 생성시에 DB에 연결한다 -->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
		<property name="driverClass" value="${jdbc.driverClassName}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
	</bean>
	<!-- memberDAO에 주입해준다  -->
	<bean id="memberDAO" class="com.spring.member.dao.MemberDAOImpl">
		<property name="dataSource" ref="dataSource" />
	</bean>

//jdbc.properties
jdbc.driverClassName = oracle.jdbc.driver.OracleDriver
jdbc.url = jdbc:oracle:thin:@localhost:1521:orcl
jdbc.username = ''
jdbc.password = ''
 

XML파일에 의한 주입되는 과정
1. memberController <- 2. memberService <- 3.memberDAO <- 4.dataSource
4 -> 3 : action-dataSource.xml
3 -> 2 : action-service.xml
2 -> 1 : action-servlet.xml
주의해야할점!!!
xml에서 대입을 해줄때 설정파일에서 생성된 빈을 주입하기 위해서 반드시 setter을 구현해야한다

DAO에서 jdbcTemplate를 사용하여 SQL을 사용해도된다

//MemberDAOImpl.java
public List selectAllMembers() throws DataAccessException {
		String query = "select id,pwd,name,email,joinDate"
				+ " from t_member "
				+ " order by joinDate desc";
		List membersList = new ArrayList();
		membersList = this.jdbcTemplate.query(query, new RowMapper(){
			public Object mapRow(ResultSet rs, int rowNum) throws SQLException{
				MemberVO memberVO = new MemberVO();
				memberVO.setId(rs.getString(("id")));
				memberVO.setPwd(rs.getString(("pwd")));
				memberVO.setName(rs.getString(("name")));
				memberVO.setEmail(rs.getString(("email")));
				memberVO.setJoinDate(rs.getString(("joinDate")));
				return memberVO;
			}
		});
		return membersList;
	}

위의 것들은 Spring JDBC의 기능인데, 실제 개발을 진행할때는
MyBatis나 Hibernate를 사용하여서 데이터베이스 연동을 하게된다.
하지만 위의 내용들을 알아두면 도움이 된다.

MyBatis

참고 : pro22
애플리케이션의 규모가 작을때는 기존의 JDBC를 이용해서 충분히 할수있었지만,
규모가 커졌을때에는 기존의 JDBC의 한계가 있다.
그래서 나온것이 MyBatis같은 데이터베이스 연동프레임워크가 나오게되었다.
기존 JDBC 연동
connection -> Statement 객체 생성 -> SQL문 전송 -> 결과 반환 -> close
이 방식의 단점은 SQL문이 기본 프로그래밍 코드에 섞인다는것.
MyBatis 특징
1. SQL을 소스코드가 아닌 XML로 분리
2. SQL과 프로그래밍 코드를 분리해서 구현
3. 데이터소스기능 트랜잭션 처리 기능

MyBatis 설정 파일
SqlMapConfig.xml : 데이터베이스 연동시 반환되는 값을 저장할 빈,트랜잭션,데이터소스 등 마이바티스 관련 정보 설정(데이터 연동 기능)
ex)member.xml : 원하는 sql문을 태그별로 정리해서 지정해둠

List selectList(query_id) : id에 대한 select 문을 실행후 여러 레코드 List로 반환
List selectList(query,id, 조건) : 위와 동일하나 조건도 전달
int insert(query,id Object obj) : id에 대한 insert문 및 obj 객체의 값 추가
int update(query,id Object obj) : obj 객체의 값으로 id에 대한 update문 실행
int delete(query,id Object obj) : obj 객체의 값으로 id에 대한 delete문 실행

//SqlMapConfig.xml
<configuration>
	<typeAliases>
		<typeAlias type="com.spring.ex01.MemberVO" alias="memberVO"/>
	</typeAliases>
	<environments default="development">
	 <environment id="development">
	  <transactionManager type="JDBC"/>
	  <!--DB 연결 설정  -->
	   <dataSource type="POOLED">
	    <property name="driver" value="oracle.jdbc.driver.OracleDriver" />
	    <property name="url" value="JDBC:oracle:thin:@localhost:1521:orcl" />
	    <property name="username" value=" " />
	    <property name="password" value=" " />
	   </dataSource>
	 </environment>
	</environments>
	
	<mappers>
	<!-- member.xml을 읽어들이기 -->
	 <mapper resource="mybatis/mappers/member.xml"/>
	</mappers>
</configuration>

//member.xml
//select, insert, update, delete태그로 나타내고
//각각의 원하는 id, parameterType을 적어준뒤
//dao에서 namespace를 통하여 접근하여서 원하는 sql의 id를 통해 sql 가져오기
<mapper namespace="mapper.member">
<!-- memberVO에 저장 -->
	<resultMap id="memResult" type="memberVO">
	 <result property="id" column="id" />
	 <result property="pwd" column="pwd" />
	 <result property="name" column="name" />
	 <result property="email" column="email" />
	 <result property="joinDate" column="joinDate" />
	</resultMap>
	<!--id를 가지고 DAO에서 호출하고, 반환되는 값들을 resultMap에 넣어준다-->
	select id="selectMemberByPwd" resultMap="memResult"  parameterType="int" >
      <![CDATA[
         select * from t_member
         where
         pwd = #{pwd}			
      ]]>
    </select>
    <insert id="insertMember" parameterType="memberVO">
     <![CDATA[
     	insert into t_member(id, pwd, name, email)
     	values(#{id}, #{pwd}, #{name}, #{email})
     ]]>
    </insert>
    <insert id="insertMember2" parameterType="java.util.HashMap">
     <![CDATA[
     	insert into t_member (id, pwd, name, email)
     	values(#{id}, #{pwd}, #{name}, #{email})
     ]]>
    </insert>
    <update id="updateMember" parameterType="memberVO">
     <![CDATA[
     	update t_member
     	set pwd=#{pwd}, name=#{name}, email=#{email}
     	where id=#{id}
     ]]>
    </update>
    <delete id="deleteMember" parameterType="String">
     <![CDATA[
     	delete from t_member
     	where
     	id=#{id}
     ]]>
    </delete>
</mapper>

//MemberDAO.java
...
public class MemberDAO {
	private static SqlSessionFactory sqlMapper=null;
	public static SqlSessionFactory getInstance(){
		if(sqlMapper==null){
			try{
				String resource = "mybatis/SqlMapConfig.xml";
				Reader reader = Resources.getResourceAsReader(resource);
				//myBatis를 이용하는 sqlMapper 객체 가져오기
				sqlMapper = new SqlSessionFactoryBuilder().build(reader);
				reader.close();
			}catch(Exception e){
				e.printStackTrace();
			}
		}
		return sqlMapper;
	}
	
	public List<MemberVO> selectMemberByPwd(int pwd) {
		//sql의 instance를 가져와서 session을 open
		sqlMapper = getInstance();
		SqlSession session = sqlMapper.openSession();
		List<MemberVO> membersList = null;
		//session의 selectList 메소드를 사용(여러개가 있을수 있으므로 List로 받아온다) 
		membersList = session.selectList("mapper.member.selectMemberByPwd", pwd);
		return membersList;
	}

	public int insertMember(MemberVO memberVO) {
		sqlMapper = getInstance();
		SqlSession session = sqlMapper.openSession();
		int result = 0;
		result = session.insert("mapper.member.insertMember", memberVO);
		session.commit();
		return result;
	}

	public int insertMember2(Map<String, String> memberMap) {
		sqlMapper = getInstance();
		SqlSession session = sqlMapper.openSession();
		int result = session.insert("mapper.member.insertMember2", memberMap);
		session.commit();
		return result;
	}

	public int updateMember(MemberVO memberVO) {
		sqlMapper = getInstance();
		SqlSession session = sqlMapper.openSession();
		int result = session.update("mapper.member.updateMember", memberVO);
		session.commit();
		return result;
	}

	public int deleteMember(String id) {
		sqlMapper = getInstance();
		SqlSession session = sqlMapper.openSession();
		int result = 0;
		result = session.delete("mapper.member.deleteMember", id );
		session.commit();
		return result;
	}
}

동적 MyBatis 사용

  1. SQL문의 조건절에서 사용
  2. where에 조건을 동적으로 추가
  3. JSTL과 XML 기반으로 동적 SQL문을 작성

동적 SQL문을 구성하는 요소들
1. if
2. choose(when, otherwise)
3. trim(where, set)
4. foreach

1. if

<where>
	<if test="조건식">
    </if>
</where>

<where>
   <if test="name != '' and name != null">
     name = #{name}
   </if>
   <if test="email != '' and email != null ">
     and email = #{email}
   </if>
</where>

2. choose(when, otherwise)

<choose>
   <when test="">
   </when>
   <otherwise>
    구문 n+1;
   </otherwise>
</choose>

<where>
      <choose>
       <when test="name != '' and name != null and email != '' and email != null">
        name=#{name} and email=#{email}
       </when>
       <when test="name != '' and name != null">
        name=#{name}
       </when>
       <when test="email != '' and email != null">
        email=#{email}
       </when>
      </choose>
 </where>

3.foreach

<foreach item="item" collection="list" index="index" open="(" close=")" separator=",">
 #{item}
</foreach>

where name in
  <foreach item="item" collection="list" open="(" separator="," close=")">
   #{item}
  </foreach>
order by joinDate desc

4. sql

<sql id="a">
   <![CDATA[
    select * from t_member
   ]]>
</sql>

<select id="foreachSelect" resultMap="memResult" parameterType="java.util.Map">
    	<include refid="a" />
        <!--include 부분으로 sql문을 넣어줄수있다. -->
         <!--<![CDATA[
    select * from t_member
   ]]>-->
     where name in
     <foreach item="item" collection="list" open="(" separator="," close=")">
      #{item}
     </foreach>
     order by joinDate desc
    </select>

Mybatis tip **
마이바티스에서 오라클의 like를 검색할때는 '%' 기호와 조건값사이에 반드시 ||기호를
사용해서 연결해주어야한다.

//아래와 같이하면 에러
<![CDATA[
	select * from t_member 
	where name like '%'#{name}'%'
]]>

//아래와 같이
<![CDATA[
	select * from t_member 
	where name like '%' || #{name} || '%'
]]>

Spring - MyBatis 연동(XML 파일 설정)

  1. 수동으로 직접 설정
  2. Maven 으로 라이브러리 자동 설정

action-mybatis.xml

	<bean id="propertyPlaceholderConfigurer" 
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
		<value>/WEB-INF/config/jdbc.properties</value>
		</property>
	</bean>
    
	//jdbc.property 읽어들이기
 	<bean id="dataSource" class="org.apache.ibatis.datasource.pooled.PooledDataSource">
		<property name="driver" value="${jdbc.driverClassName}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
	</bean>
	
	//datasource 속성에 datasource 빈 생성
	<bean id="sqlSessionFactory"
		class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
        //modelconfig 설정
		<property name="configLocation"
			value="classpath:mybatis/model/modelConfig.xml" />
        //mapper안에 모든 .xml파일들 들여와 설정
		<property name="mapperLocations" value="classpath:mybatis/mappers/*.xml" />
	</bean>
	// sqlsessionTemplate 클래스 사용하여 sqlsession 빈 생성
	<bean id="sqlSession"
		class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
	</bean>

	// sqlsession 빈을 memberDAO 빈 속성에 주입
	<bean id="memberDAO"
		class="com.spring.member.dao.MemberDAOImpl">
		<property name="sqlSession" ref="sqlSession"></property>
	</bean>

action-servlet.xml

<bean id="viewResolver"   
       class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      <property name="viewClass" 
                          value="org.springframework.web.servlet.view.JstlView"/>
      <property name="prefix" value="/WEB-INF/views/member/" /> 
      <property name="suffix" value=".jsp"/>
   </bean>
   
   <bean id="memberController" 
                            class="com.spring.member.controller.MemberControllerImpl">
      <property name="methodNameResolver">
         <ref local="memberMethodResolver"/>
      </property>
      <property name="memberService" ref="memberService"/>
   </bean>

   <bean  id="memberMethodResolver"
   class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver" >
      <property  name="mappings" >
        <props>
          <prop key="/member/listMembers.do" >listMembers</prop>
          <prop key="/member/addMember.do" >addMember</prop>
          <prop key="/member/removeMember.do">removeMember</prop>
          <prop key="/member/memberForm.do" >form</prop>
       </props>
      </property>
   </bean>
   
   
   <bean id="memberUrlMapping"
       class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
      <property name="mappings">
         <props>
            <prop key="/member/*.do">memberController</prop>
         </props>
      </property>
   </bean>
profile
Let's do it developer

0개의 댓글