일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 생성자오버로드
- 자바
- 어윈 사용법
- oracle
- cursor문
- 한국건설관리시스템
- 컬렉션 타입
- 다형성
- 객체 비교
- exception
- 제네릭
- GRANT VIEW
- 컬렉션프레임워크
- 집합_SET
- 참조형변수
- 오라클
- EnhancedFor
- 대덕인재개발원
- 인터페이스
- 자동차수리시스템
- NestedFor
- abstract
- 사용자예외클래스생성
- 추상메서드
- 환경설정
- 예외미루기
- 정수형타입
- Java
- 메소드오버로딩
- 예외처리
- Today
- Total
거니의 velog
(10) 마이바티스 프레임워크 사용하기 1 본문
1. 마이바티스란?
* 애플리케이션의 규모가 작을 때는 JDBC를 이용해 충분히 개발할 수 있었다. 그러나 인터넷 사용자가 폭발적으로 증가하고 애플리케이션의 기능이 복잡해짐에 따라 기존의 JDBC로 개발하는 데는 한계가 드러나게 되었다.
* 기존 JDBC로 개발할 경우 반복적으로 구현해야 할 SQL 문도 많을 뿐만 아니라 SQL 문도 복잡하다. 따라서 자연스럽게 마이바티스(MyBatis)나 하이버네이트와 같은 데이터베이스 연동 관련 프레임워크가 등장하게 되었다. 이번에는 마이바티스 프레임워크에 대해 알아볼 것이다. 우선 마이바티스를 왜 사용하게 되었는지 그 등장 배경부터 알아보자.
* 기존의 JDBC를 연동하려면 다음과 같은 과정을 거쳐야 한다.
connection -> Statement 객체 생성 -> SQL문 전송 -> 결과 반환 -> close
* 이 방식의 단점은 SQL문이 프로그래밍 코드에 섞여 코드를 복잡하게 만든다는 것이다. 이 방법을 개선해 SQL 문의 가독성을 높여 사용하기 편하게 만든 것이 바로 마이바티스 프레임워크이다.
* 다음 코드는 쇼핑몰에서 자바의 JDBC 기능을 이용해 상품 정보를 추가하는 insert 문이다. 문자열로 SQL 문을 만들어 사용하는 방식이다.
[AdminDAO.java]
...
public void addGoods(GoodsVO goodsVO) throws SQLException {
Connection conn = dataFactory.getConnection();
Statement stmt = conn.createStatement();
String query = "insert into t_Goods_info (goods_id, " +
"goods_sort, " +
"goods_title, " +
"goods_writer, " +
"goods_publisher, " +
"goods_price, " +
"goods_sales_price, " +
"goods_point, " +
"goods_published_date, " +
"goods_total_page, " +
"goods_isbn, " +
"goods_delivery_price, " +
"goods_delivery_date, " +
"goods_type, " +
"goods_writer_intro, " +
"goods_intro, " +
"goods_publisher_comment, " +
"goods_recommendation, " +
"goods_contents_order)";
query += values('"+
"goodsVO.getGoods_id()+"', '"+
"goodsVO.getGoods_sort()+"', '"+
"goodsVO.getGoods_title()+"', '"+
"goodsVO.getGoods_writer()+"', '"+
"goodsVO.getGoods_publisher()+"', '"+
"goodsVO.getGoods_price()+"', '"+
"goodsVO.getGoods_sales_price()+"', '"+
"goodsVO.getGoods_point()+"', '"+
"goodsVO.getGoods_published_date()+"', '"+
"goodsVO.getGoods_page_total()+"', '"+
"goodsVO.getGoods_isbn()+"', '"+
"goodsVO.getGoods_delivery_price()+"', '"+
"goodsVO.getGoods_delivery_date()+"', '"+
"goodsVO.getGoods_type()+"', '"+
"goodsVO.getGoods_writer_intro()+"', '"+
"goodsVO.getGoods_intro()+"', '"+
"goodsVO.getGoods_publisher_comment()+"', '"+
"goodsVO.getGoods_recommandation()+"', '"+
"goodsVO.getGoods_contents_order()+"')";
System.out.println(query);
stmt.executeUpdate(query);
String goods_id = goodsVO.getGoods_id();
}
...
* 애플리케이션의 기능이 복잡해지면 해당 기능과 관련된 SQL문의 길이가 보통 몇 십 줄씩 된다. 그런데 길이가 긴 SQL문을 위 코드처럼 다시 문자열로 만들어서 사용한다면 상당히 불편하다. 그뿐만 아니라 SQL문 실행 시 오류도 많이 발생하고 유지보수에도 문제가 많이 발생한다.
* 하지만 마이바티스를 사용하면 복잡한 SQL문이라도 SQL Developer 같은 도구에서 SQL문을 사용하는 것처럼 표준화된 방법으로 사용할 수 있다. 아래의 코드처럼 개발자가 작성하기 쉬울 뿐 아니라 코드 가독성도 좋다.
[SQL Developer에서 실행한 SQL 문]
insert into t_shopping_order (order_id
, member_id
, goods_id
, goods_title
, order_goods_qty
, order_total_price
, orderer_name
, receiver_name
, receiver_hp1
, receiver_hp2
, receiver_hp3
, delivery_address
, delivery_message
, delivery_method
, smssts_yn
, gift_wrapping
, pay_method
, card_com_name
, card_pay_month
, pay_ordered_hp_num)
values ('1'
, 'lee'
, '19'
, '아이디어 구현 중심 자바'
, 1
, 27000
, '이병승'
, '이병승'
, '011'
, '1212'
, '6767'
, '우편번호:05762<br>도로명주소:서울 송파구 강남빌딩 301호'
, '택배 기사님께 전달할 메시지를 남겨주세요.'
, '일반택배'
, 'no'
, '신용카드<br>카드사:삼성<br>할부개월수:3개월
, '삼성'
, '3개월'
, '해당 없음');
* 마이바티스 프레임워크의 특징은 다음과 같다.
* SQL 실행 결과를 자바 빈즈 또는 Map 객체에 매핑해 주는 Persistence 솔루션으로 관리한다.
즉, SQL을 소스 코드가 아닌 XML로 분리한다.
* SQL문과 프로그래밍 코드를 분리해서 구현한다.
* 데이터소스(DaraSource) 기능과 트랜잭션 처리 기능을 제공한다.
(1) SqlMapConfig.xml에 각 기능별로 실행할 SQL문을 SqlMap.xml에 미리 작성한 후 등록한다.
(2) 애플리케이션에서 데이터베이스와 연동하는데 필요한 데이터를 각각의 매개변수에 저장한 후 마이바티스에 전달한다.
(3) 애플리케이션에서 요청한 SQL문을 SqlMap.xml에서 선택한다.
(4) 전달한 매개변수와 선택한 SQL문을 결합한다.
(5) 매개변수와 결합된 SQL문을 DBMS에서 실행한다.
(6) DBMS에서 반환된 데이터를 애플리케이션에서 제공하는 적당한 매개변수에 저장한 후 반환한다.
* 다시 정리하면 데이터베이스 연동 시 사용되는 SQL문을 미리 SqlMapConfig.xml에 작성해 놓고 애플리케이션에서 데이터베이스 연동 시 해당 SQL 문에서 사용될 데이터를 지원하는 해당 매개변수에 저장한 후 SQL문에 전달한다. 전달된 매개변수와 SQL문을 결합해 SQL문을 DBMS로 전송하여 실행한다. 그리고 그 결과를 애플리케이션에서 제공하는 자료형으로 반환한다.
* 이제 실습에 필요한 마이바티스를 다운로드하여 설치해보자.
2. 마이바티스 설치하기
에 접속한 후, Products 탭을 클릭한다.
2. MyBatis 3 옆에 있는 download 링크를 클릭한다.
3. mybatis-3.4.6.zip 파일을 클릭해 다운로드 한다.
4. 다운로드한 압축 파일의 압축을 해제한다.
5. mybatis-3.4.6.jar 를 복사해 새로 만든 프로젝트의 lib 폴더에 붙여 넣는다. 그리고 이 버전에 대응하는 ojdbc.jsr 파일도 복사해 붙여 넣는다. JSTL 관련 라이브러리도 이전 세팅을 참고해 붙여 넣는다.
3. 마이바티스 이용해 회원 기능 실습하기
* 이번에는 마이바티스를 이용해 회원 테이블과 연동하여 다양한 회원 관련 기능을 수행해 보자.
(1) 마이바티스 설정 파일 작성
* 마이바티스에서는 다음 표에 있는 두 가지 설정 파일을 사용한다.
< 마이바티스 관련 설정 파일 >
설정 파일 | 기능 |
SqlMapConfig.xml | 데이터베이스 연동 시 반환되는 값을 저장할 빈이나 트랜잭션, 데이터소스 등 마이바티스 관련 정보를 설정한다. |
member.xml | 회원 정보 관련 SQL 문을 설정한다. |
* 스프링처럼 마이바티스도 SqlMapConfig.xml 에서 데이터소스(DataSource)를 설정해 데이터베이스와 연동할 수 있는 기능을 제공한다. 그리고 실제 개발 시 마이바티스에서 제공하는 데이터소스를 사용해 데이터베이스와 연동한다.
1. 다음과 같이 설정 파일들을 추가한다. 이 때 각 설정 파일은 src 패키지 아래에 위치해야 한다는 것을 잊지 말자!
2. SqlMapConfig.xml을 다음과 같이 작성한다. <typeAlias> 태그는 애플리케이션에서 SQL문으로 값을 전달하거나 마이바티스에서 DBMS로 SQL문 실행 시 반환되는 레코드를 저장하는 용도로 사용하기 위한 빈인 memberVO 빈을 생성한다. 또한 <dataSource> 태그를 이용해 마이바티스가 연동하는 데이터베이스에 대한 데이터소스를 설정한다. 마지막으로 <mappers> 태그를 이용해 마이바티스에서 사용하는 SQL 문이 있는 XML 파일의 위치를 지정한다.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<typeAlias type="com.spring.ex01.MemberVO" alias="memberVO"/>
<!-- DAO에서 SQL 문으로 값을 전달할 때 또는 SQL 문을 실행한 후 가져온 값을 DAO로 전달할 때 사용할 빈을 생성한다. -->
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="JDBC:oracle:thin:@localhost:1521:XE" />
<property name="username" value="scott" />
<property name="password" value="tiger"/>
</dataSource> <!-- 데이터베이스 연결을 설정한다. -->
</environment>
</environments>
<mappers>
<mapper resource="mybatis/mappers/member.xml"/>
<!-- 회원 기능 관련 SQL문이 있는 member.xml을 읽어 들인다. 이 때 반드시 지정한 패키지 이름과 일치해야 한다는 것에 주의하자 -->
</mappers>
</configuration>
3. member.xml을 다음과 같이 작성하여 회원 기능과 관련된 SQL문을 설정한다. 먼저 다른 파일의 SQL 문과 구별하기 위해 mapper.member 로 네임스페이스를 지정하고 SQL문을 실행한 후 반환되는 회원 정보 레코드를 저장하기 위한 resultMap을 지정한다. 각 레코드는 한 개의 MemverVO 객체를 생성한 후 지정한 속성에 따라 레코드의 컬럼 값을 저장한다. <select> 태그의 id 속성은 MemberDAO 에서 SQL 문을 구분해서 호출하는 용도로 사용되며, 반환되는 레코드를 id가 memResult 인 resultMap에 저장한다.
<?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">
<mapper namespace="mapper.member"> <!-- member.xml의 네임스페이스를 지정한다. -->
<resultMap id="memResult" type="memberVO"> <!-- SQL문을 실행한 후 반환되는 레코드들을 <typeAlias> 태그에서 지정한 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" /> <!-- 레코드의 컬럼 이름에 대해 memberVO의 같은 속성에 값을 설정한다. -->
</resultMap>
<!-- DAO에서 id를 이용해 해당 SQL 문을 호출하고, 반환되는 레코드를 memResult에 저장한다.
<resultMap id="memResult" type="java.util.HashMap">
<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> -->
<select id="selectAllMemberList" resultMap="memResult">
<![CDATA[
select * from t_member order by joinDate desc
]]>
</select>
<select id="selectName" resultType="String">
<![CDATA[
select name from t_member
where id = 'hong'
]]>
</select>
<select id="selectPwd" resultType="int" >
<![CDATA[
select pwd from t_member
where id = 'hong'
]]>
</select>
<select id="selectMemberById" resultType="memberVO" parameterType="String" >
<![CDATA[
select * from t_member
where
id=#{id}
]]>
</select>
<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.Map">
<![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>
<!-- 동적 SQL문 -->
<select id="searchMember" parameterType="memberVO" resultMap="memResult">
<![CDATA[
select * from t_member
]]>
<where>
<if test=" name != '' and name != null">
name=#{name}
</if>
<if test="email != '' and email != null ">
and email = #{email}
</if>
</where>
order by joinDate desc
</select>
<!--
<sql id="a">
<![CDATA[
select * from t_member
]]>
</sql> -->
<!--
<select id="searchMember" parameterType="memberVO" resultMap="memResult">
<include refid="a" />
<![CDATA[
select * from t_member
]]>
<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>
order by joinDate desc
</select> -->
<select id="foreachSelect" resultMap="memResult" parameterType="java.util.Map">
<!-- <include refid="a" /> -->
<![CDATA[
select * from t_member
]]>
where name in
<foreach item="item" collection="list" open="(" separator="," close=")" >
#{item}
</foreach>
order by joinDate desc
</select>
<insert id="foreachInsert" parameterType="java.util.Map">
<foreach item="item" collection="list" open="INSERT ALL" separator=" " close="SELECT * FROM DUAL" >
INTO t_member(id, pwd, name, email)
VALUES (#{item.id},
#{item.pwd},
#{item.name},
#{item.email})
</foreach>
</insert>
<!--
<select id="selectLike" resultMap="memResult" parameterType="String" >
<![CDATA[
select * from t_member
where
name like '%'#{name}'%'
]]>
</select>
-->
<!-- like 검색 -->
<select id="selectLike" resultMap="memResult" parameterType="String" >
<![CDATA[
select * from t_member
where
name like '%' || #{name} || '%'
]]>
</select>
</mapper>
(2) 마이바티스를 이용한 회원 정보 조회 실습
* 그럼 본격적으로 마이바티스를 이용해 회원 정보를 조회해 보자.
1. 실제 마이바티스와 연동하기 위한 자바 클래스와 JSP 파일을 다음과 같이 준비한다.
2. MemberServlet을 다음과 같이 작성한다. 브라우저에서 요청 시 MemberDAO 객체를 생성한 후 selectAllMemberList()를 호출하는 서블릿이다.
package com.spring.ex01;
import java.io.IOException;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/mem.do")
public class MemberServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doHandle(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doHandle(request, response);
}
private void doHandle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
MemberDAO dao = new MemberDAO();
List<MemberVO> membersList = dao.selectAllMemberList(); // MemberDAO 객체를 생성하고 selectAllMemberList() 를 호출한다.
//List<HashMap<String, String>> membersList = dao.selectAllMemberList();
request.setAttribute("membersList", membersList);
RequestDispatcher dispatch = request.getRequestDispatcher("test01/listMembers.jsp");
dispatch.forward(request, response);
}
}
3. MemberDAO 클래스를 다음과 같이 작성한다. SqlMapConfig.xml 파일을 이용해 SqlMapper 객체를 생성한다. 그런 다음 selectAllMemberList() 메서드를 호출하면서 인자로 mapper.member.selectAllMemberList를 전달해 member.xml에서 해당 네임스페이스와 id에 해당하는 SQL문을 작성한다.
package com.spring.ex01;
import java.io.Reader;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class MemberDAO {
public static SqlSessionFactory sqlMapper = null;
private static SqlSessionFactory getInstance() {
if (sqlMapper == null) {
try {
String resource = "mybatis/SqlMapConfig.xml"; // MemberDAO의 각 메서드 호출 시 src/mybatis/SqlMapConfig.xml에서 설정 정보를 읽은 후 데이터베이스와의 연동 준비를 한다.
Reader reader = Resources.getResourceAsReader(resource);
sqlMapper = new SqlSessionFactoryBuilder().build(reader); // 마이바티스를 이용하는 sqlMapper 객체를 가져온다.
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return sqlMapper;
}
public List<MemberVO> selectAllMemberList() {
sqlMapper = getInstance();
SqlSession session = sqlMapper.openSession(); // 실제 member.xml의 SQL문을 호출하는 데 사용되는 SqlSession 객체를 가져온다.
List<MemberVO> memlist = null;
memlist = session.selectList("mapper.member.selectAllMemberList"); // 여러 개의 레코드를 조회하므로 selectList() 메서드에 실행하고자 하는 SQL문의 id를 인자로 전달한다.
return memlist;
}
// public List<HashMap<String, String>> selectAllMemberList() {
// sqlMapper = getInstance();
// SqlSession session = sqlMapper.openSession();
// List<HashMap<String, String>> memlist = null;
// memlist = session.selectList("mapper.member.selectAllMemberList");
// return memlist;
// }
}
4. MemberVO 클래스를 다음과 같이 작성한다. SQL문으로 전달할 값이나 SQL문을 실행한 후 반환되는 레코드들의 값을 각 속성에 저장한다.
package com.spring.ex01;
import java.sql.Date;
public class MemberVO {
private String id;
private String pwd;
private String name;
private String email;
private Date joinDate;
public MemberVO() {}
public MemberVO(String id, String pwd, String name, String email) {
this.id = id;
this.pwd = pwd;
this.name = name;
this.email = email;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getJoinDate() {
return joinDate;
}
public void setJoinDate(Date joinDate) {
this.joinDate = joinDate;
}
}
5. 회원 정보를 표시하는 listMambers.jsp는 이전의 listMembers.jsp를 복사해서 사용하자.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"
isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="contextPath" value="${pageContext.request.contextPath}" />
<%
request.setCharacterEncoding("UTF-8");
%>
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<title>회원 정보 출력창</title>
</head>
<body>
<table border="1" align="center" width="80%">
<tr align="center" bgcolor="lightgreen">
<td><b>아이디</b></td>
<td><b>비밀번호</b></td>
<td><b>이름</b></td>
<td><b>이메일</b></td>
<td><b>가입일</b></td>
</tr>
<c:forEach var="member" items="${membersList}">
<tr align="center">
<td>${member.id}</td>
<td>${member.pwd}</td>
<td>${member.name}</td>
<td>${member.email}</td>
<td>${member.joinDate}</td>
</tr>
</c:forEach>
</table>
<a href="${contextPath}/member/memberForm.do">
<h1 style="text-align:center">회원가입</h1>
</a>
</body>
</html>
6. 다음의 주소로 요청하여 실행 결과를 확인한다.
- http://localhost:8090/pro23/mem.do
'Java_Spring Framework part1' 카테고리의 다른 글
(12) 마이바티스 프레임워크 사용하기 3 (0) | 2023.11.10 |
---|---|
(11) 마이바티스 프레임워크 사용하기 2 (1) | 2023.11.08 |
(9) 스프링 JDBC 기능 (0) | 2023.10.28 |
(8) 스프링 MVC 기능 3 (0) | 2023.10.26 |
(7) 스프링 MVC 기능 2 (0) | 2023.10.04 |