• Home
  • About
    • Young's Github Pages photo

      一日不作一日不食

    • About
    • Github
  • Posts
    • All Posts
    • All Tags
  • Projects

Java EE 정리 44

29 Apr 2019

Reading time ~6 minutes

Java EE 정리 44 - Spring JDBC(4), Spring ORM


Spring JDBC를 사용한 update

  • select만 RowMapper를 사용하여 조금 복잡하지만 insert, update, delete는 간편
<!-- detail_member.jsp -->
...
<script type="text/javascript">
      $(function() {
            $("#btnUpdate").click(function() {
                  
                  if($("#btnUpdate").val() == "수정") {
                        var updateView =
                              "이름 : <input type='text' name='name'  value='"+$('#name').text()+"'/><br/>"
                              +"출신고 : <input type='text'  name='highschool' value='"+$('#highschool').text()+"'/><br/>"
                              +"지역 : <input type='text' name='loc'  value='"+$('#loc').text()+"'/><br/>";
                              
                        $("#btnUpdate").val("수정실행");
                        $("#view").html(updateView);
                  } else {
                        // 유효성 검증 후 submit
                        $("#frm").submit();
                  }
            });
      });
</script>
...
<c:choose>
      <c:when test="${ empty detailMember }">
            <h2>조회된 회원이 존재하지 않습니다.</h2>
      </c:when>
      <c:otherwise>
            <form name='frm' id='frm' action='update_member.do'  method='post'>
            <input type="hidden" name="num" value="${ param.num }"/>
            <div id="view">
                  <table border="1" style="text-align:center;">
                        <tr>
                              <th colspan="3"><h2>상세  회원정보</h2></th>
                        </tr>
                        <tr>
                              <td width="100">이미지</td>
                              <td width="100">이름</td>
                              <td width="100">
                                    <span id="name"><c:out value="${  detailMember.name }"/></span>
                              </td>
                        </tr>
                        <tr>
                              <td rowspan="4">
                                    <img id="img"  src="/spring_jdbc/upload/${ detailMember.img }" style="width:100px;  height:100px;"/>
                              </td>
                        </tr>
                        <tr>
                              <td>지역</td>
                              <td><span id="loc"><c:out value="${  detailMember.loc }"/></span></td>
                        </tr>
                        <tr>
                              <td>출신고</td>
                              <td>
                                    <span id="highschool"><c:out  value="${ detailMember.highschool }"/></span>
                              </td>
                        </tr>
                        <tr>
                              <td colspan="2" align="center">
                                    <input type="button"  onclick="history.back()" value="뒤로가기" class="btn"/>
                              </td>
                        </tr>
                  </table>
            </div>
            <div>
                  <input type="button" value="수정"  id="btnUpdate"class="btn"/>
            </div>
            </form>
      </c:otherwise>
</c:choose>

01

package kr.co.sist.vo;
public class MemberUpdateVO {
      private int num;
      private String name, highschool, loc;
      // getter, setter 생성
// JdbcDAO
...
      public int updateMember(MemberUpdateVO muvo) throws  DataAccessException {
            int cnt = 0;
            String updateMember =
                  "UPDATE test_like SET name=?, highschool=?, loc=?  WHERE num=?";
            cnt = jt.update(updateMember,muvo.getName(), muvo.getHighschool(),
                        muvo.getLoc(), muvo.getNum());
            
            return cnt;
      }
}
// JdbcService
...
      public boolean updateMember(MemberUpdateVO muvo) {
            boolean flag = false;
            try {
                  flag = jdao.updateMember(muvo) == 1;
            } catch(DataAccessException dae) {
                  dae.printStackTrace();
            }
            
            return flag;
      }
}
// JdbcContrller
...
      @RequestMapping(value="/update_member.do", method=POST)
      public String modifyMember(MemberUpdateVO muvo, Model model) {
            String resultMsg = "회원정보를 수정할 수 없습니다";
            boolean resultFlag = false;
            
            if(js.updateMember(muvo)) {
                  resultMsg = muvo.getName()+"님 정보를 변경하였습니다";
                  resultFlag = true;
            }
            
            model.addAttribute("resultMsg", resultMsg);
            model.addAttribute("resultFlag", resultFlag);
            
            return "member/update_result";
      }
}
  • 변경 성공여부에 따라 다른 이미지를 보여줌
<!-- member/update_result.jsp -->
...
<c:set var="img" value="img2.jpg"/>
<c:if test="${ resultFlag }">
      <c:set var="img" value="img.png"/>
</c:if>
<img src="http://localhost:8080/spring_jdbc/common/images/${ img  }"/><br/>
<c:out value="${ resultMsg }"/>

02

03

Spring JDBC를 사용한 delete

  • 크롬은 form태그 action값이 변경되면 유지됨, IE는 변경되었다가 다른 이벤트가 발생하면 초기값으로 돌아간다
<!-- member/detail_member.jsp -->
...
<script type="text/javascript">
      $(function() {
            $("#btnUpdate").click(function() {
                  
                  if($("#btnUpdate").val() == "수정") {
                        var updateView =
                              "이름 : <input type='text' name='name'  value='"+$('#name').text()+"'/><br/>"
                              +"출신고 : <input type='text'  name='highschool' value='"+$('#highschool').text()+"'/><br/>"
                              +"지역 : <input type='text' name='loc'  value='"+$('#loc').text()+"'/><br/>";
                              
                        $("#btnUpdate").val("수정실행");
                        $("#view").html(updateView);
                  } else {
                        // 유효성 검증 후 submit
                        document.frm.action='update_member.do';
                        $("#frm").submit();
                  }
            });
            
            $("#btnDelete").click(function() {
                  if(confirm($("[ "+"#name").text()+" ] 회원을 삭제  하시겠습니까?")) {
                        document.frm.action='delete_member.do';
                        $("#frm").submit();
                  }
            });
      });
</script>
...
            <div>
                  <input type="button" value="수정"  id="btnUpdate"class="btn"/>
                  <input type="button" value="삭제"  id="btnDelete"class="btn"/>
            </div>
            </form>
      </c:otherwise>
</c:choose>
// JdbcDAO
...
      public int deleteMember(int num) throws DataAccessException {
            int cnt = 0;
            
            String deleteMember = "DELETE FROM test_like WHERE num=?";
            cnt = jt.update(deleteMember,num);
            
            return cnt;
      }
}
// JdbcService
...
      public boolean deleteMember(int num) {
            boolean flag = false;
            try {
                  flag = jdao.deleteMember(num) == 1;
            } catch(DataAccessException dae) {
                  dae.printStackTrace();
            }
            return flag;
      }
}
// JdbcController
...
      @RequestMapping(value="/delete_member.do", method=POST)
      public String removeMember(int num, Model model) {
            String resultMsg = "회원정보를 삭제할 수 없습니다";
            boolean resultFlag = false;
            
            if(js.deleteMember(num)) {
                  resultMsg = "회원정보가 삭제되었습니다.";
                  resultFlag = true;
            }
            
            model.addAttribute("resultMsg", resultMsg);
            model.addAttribute("resultFlag", resultFlag);
            
            return "member/remove_result";
      }
}
<!-- member/remove_result.jsp -->
...
<c:set var="img" value="img2.jpg"/>
<c:if test="${ resultFlag }">
      <c:set var="img" value="img.png"/>
</c:if>
<img src="http://localhost:8080/spring_jdbc/common/images/${ img  }"/><br/>
<c:out value="${ resultMsg }"/>
...

04

  • 삭제와 동시에 파일 삭제처리
package kr.co.sist.domain;
public class MemberImg {
      
      private int cnt; // 삭제여부
      private String img; // 삭제할 이미지
      // 인자있는 생성자, getter, setter 생성
  • 삭제 처리 후 삭제여부와 삭제할 파일명을 Domain형태로 반환받음
// JdbcDAO
...
      public MemberImg deleteMember(int num) throws DataAccessException  {
            MemberImg mi = null;
            int cnt = 0;
            String img = "";
            
            // 삭제할 이미지 조회
            String selectImg = "SELECT img FROM test_like WHERE num=?";
            RowMapper<String> rm = new RowMapper<String>() {
                  @Override
                  public String mapRow(ResultSet rs, int rowNum) throws  SQLException {
                        String img = rs.getString("img");
                        return img;
                  }
            };
            
            img = jt.queryForObject(selectImg, rm, num);
            
            String deleteMember = "DELETE FROM test_like WHERE num=?";
            cnt = jt.update(deleteMember,num);
            
            mi = new MemberImg(cnt, img);
            
            return mi;
      }
}
// JdbcService
...
      public boolean deleteMember(int num) {
            boolean flag = false;
            
            try {
                  MemberImg mi = jdao.deleteMember(num);
                  flag = mi.getCnt() == 1;
                  if (flag) { // 삭제된 레코드가 존재하면
                        // 파일 삭제
                        if (!"default.png".equals(mi.getImg())) {
                              File file = new  File("C:/.../spring_jdbc/WebContent/upload/"
                                +mi.getImg());
                              file.delete();
                        }
                  }
            } catch(DataAccessException dae) {
                  dae.printStackTrace();
            }
            return flag;
      }
}

05

06

Spring ORM(Object Relational Mapping)

  • Spring framework과 DB framework를 연동하는 것
    • DB Framework에서 관리하던 걸 Spring Framework에서 대신 해주는 것

07

  • MyBatis, Hibernatet 등 framework과 연동가능
    • 연동 Module을 DB Framework에서 지원해주어야 한다
    • 원래 auto commit이 안되기 때문에 따로 commit을 해주어야한다
    • MyBatis의 경우 MyBatis-Spring.jar를 사용하여 연동
      • DB연동을 Spring으로 옮겨가서 수행, auto commit이 됨
      • Transaction 처리가 스프링으로 옮겨감
    • Spring Docs에는 Hibernate 연동방법만 나와있음
      • MyBatis 공식 홈페이지에서 MyBatis-Spring 정보를 얻을 수 있음

Spring ORM - MyBatis-Spring 설치

  • 연동할 수 있는 jar 다운
    • MyBatis와 MyBatis-Spring
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.6</version>
</dependency>

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis-spring</artifactId>
  <version>2.0.1</version>
</dependency>
  • 새로운 스프링 프로젝트 생성(WAR 파일을 import해서)
    • Spring으로 프로젝트 변경, Tern, Maven 프로젝트 적용
    • 기존 spring_jdbc에 있던 pom.xml 복붙, 위 디펜던시도 추가 후 Maven Project update
    • .m2 에 저장된 mybatis와 mybatis-spring.jar파일을 /WEB-INF/lib에 복붙

08

Spring ORM - MyBatis-Spring 사용

  • DB 연동 bean을 설정
    • WEB-INF/spring/root-context.xml에 설정
<bean id="dataSource"  class="org.springframework.jdbc.datasource.DriverManagerDataSource">
      <property name="driverClassName"  value="Driver명"/>
      <property name="url"  value="DB Server URL"/>
      <property name="username" value="계정명"/>
      <property name="password" value="비밀번호"/>
</bean>
  • 기존 MyBatis에서는 mybatis_config.xml에 위 설정을 넣었었으나 이제 Spring으로 옮겨옴
  • SqlSessionFactoryBean에 의존성 주입
    • SqlSessionFactoryBean은 SqlSessionFactoryBuilder와 SqlSessionFactory의 기능을 가진 클래스
<bean id="ssfb" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="configLocation" value="MyBatis 설정용 xml경로"/>
</bean>
  • MyBatis 설정용 xml은 이제 설정에 대한 정보는 갖지 않고 tyleAliases나 mapper에 대한 정보만 담게 된다
  • MyBatis Handler 의존성 주입 받기
    • 생성자 의존성 주입
    • 기존엔 SqlSession이었음, SqlSessionTemplate으로 변경됨
<bean id="객체명" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg ref="ssfb"/>
</bean>
  • 설정만 하고나선 기존 MyBatis에서 사용하던것과 동일
  • 사용 예
<!-- servlet-context.xml -->
...
      <context:annotation-config/>
      <context:component-scan base-package="kr.co.sist" />
      <context:component-scan base-package="kr.co.sist.dao" />
      <context:component-scan base-package="kr.co.sist.dao.*" />
      <context:component-scan base-package="kr.co.sist.service" />
      <context:component-scan base-package="kr.co.sist.service.*" />
      
</beans:beans>
<!-- root-context.xml -->
...
      <!-- Datasource 설정 -->
      <bean id="dataSource"  class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName"  value="oracle.jdbc.OracleDriver"/>
            <property name="url"  value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/>
            <property name="username" value="scott"/>
            <property name="password" value="tiger"/>
      </bean>
      
      <!-- SqlSessionFactoryBean 설정 -->
      <bean id="sqlSessionFactory"  class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation"  value="/WEB-INF/mybatis/mybatis_config.xml"/>
      </bean>

      <!-- SqlSessionTemplate 설정 -->
      <bean id="sst" class="org.mybatis.spring.SqlSessionTemplate">
            <constructor-arg ref="sqlSessionFactory"/>
      </bean>
      
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<!-- WEB-INF/mybatis/mybatis_config.xml -->
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <mappers>
    <mapper resource="kr/co/sist/mapper/test_mapper.xml"/>
  </mappers>
</configuration>
@Component
public class OrmDAO {
      
      @Autowired(required=false)
      private SqlSessionTemplate sst;
      
      public SqlSessionTemplate test() {
            return sst;
      }
}
@Component
public class OrmService {
      
      @Autowired(required=false)
      private OrmDAO odao;
      
      public void test() {
            System.out.println("-------"+odao);
      }
}
@Controller
public class OrmController {
      
      @Autowired(required = false)
      private OrmService os;

      @RequestMapping(value="/index.do", method=RequestMethod.GET)
      public String test() {
            os.test();
            return "test";
      }   
}
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
      location.href="index.do";
</script>
</head>
<body>
</body>
</html>

09



Java EESpring