일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 자바배열예제
- Oracle기초
- 2020정보처리기사실기정리
- 자바 정규표현식 예제
- spring crud
- 스프링 CRUD게시판
- 2020정보처리기사실기
- 프로그래머스 SQL
- 자바연산자
- CRUD게시판만들기
- 프로그래머스 MYSQL
- 프로그래머스 쿼리문
- js datepicker
- 오라클설치
- 게시판만들기
- jsp게시판만들기
- 2020정보처리기사실기요약
- 자바기초
- html기초
- jsp 팝업띄우기
- 정보처리기사실기정리
- 스프링게시판만들기
- PLSQL
- 스프링 crud
- crud게시판
- spring crud게시판
- 오버라이딩
- 정처기실기정리
- jsp 날짜팝업
- 날짜지정팝업
- Today
- Total
영보의 SystemOut.log
[JSP,MyBatis] CRUD 게시판 만들기(1) #업로드/다운로드/수정/삭제 본문
앞서 한것에 이어서 오늘은 JSP와 Java, MyBatis를 이용하여
첨부파일 업로드, 다운로드, 수정, 삭제가 가능한 게시판을 만들어 보겠습니다.
먼저 사용한 라이브러리입니다.
또한 한글이 깨지지 않게, UTF-8로 환경설정을 해줬습니다.
# Oracle에 테이블 생성
1 2 3 4 5 6 7 8 9 10 11 12 | CREATE TABLE databoard4( no NUMBER, name VARCHAR2(34) CONSTRAINT db4_name_nn NOT NULL, subject VARCHAR2(1000) CONSTRAINT db4_sub_nn NOT NULL, content CLOB CONSTRAINT db4_cont_nn NOT NULL, pwd VARCHAR2(10) CONSTRAINT db4_pwd_nn NOT NULL, regdate DATE DEFAULT SYSDATE, hit NUMBER DEFAULT 0, filename VARCHAR2(260), filesize NUMBER DEFAULT 0, CONSTRAINT db4_no_pk PRIMARY KEY(no) ); | cs |
1 2 | INSERT INTO databoard7(no,name,subject,content,pwd,filename) VALUES(1,'홍길동','마이바티스 curd이용법','JSP include가 있는 경우 처리방법','1234',' ');COMMIT; | cs |
# db.properties
1 2 3 4 | driver=oracle.jdbc.driver.OracleDriver url=jdbc:oracle:thin:@211.238.142.195:1521:XE username=hr password=happy | cs |
- 일반 파일을 추가해서 경로/IP/Oracle id/pw
# DataBoardVO.java
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | package com.sist.dao; import java.util.*; public class DataBoardVO { private int no; private String name; private String subject; private String content; private String pwd; private Date regdate; private int hit; private String filename; private int filesize; private String dbday; public int getNo() { return no; } public void setNo(int no) { this.no = no; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSubject() { return subject; } public void setSubject(String subject) { this.subject = subject; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } public Date getRegdate() { return regdate; } public void setRegdate(Date regdate) { this.regdate = regdate; } public int getHit() { return hit; } public void setHit(int hit) { this.hit = hit; } public String getFilename() { return filename; } public void setFilename(String filename) { this.filename = filename; } public int getFilesize() { return filesize; } public void setFilesize(int filesize) { this.filesize = filesize; } public String getDbday() { return dbday; } public void setDbday(String dbday) { this.dbday = dbday; } } | cs |
- 미리 Oracle에 생성해놓은 데이터를 VO에서 이클립스와 연동하기 위해 getter/setter로 캡슐화 코딩을 해줍니다.
# DataBoardDAO.java
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 | package com.sist.dao; // XML파싱후에 => 실행된 결과를 받는 위치=>DAO에서 메소드 호출 import java.io.*;//XML파일 읽기 => Reader (한글파일) import java.util.*;//List => 구현 (ArrayList); 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 DataBoardDAO { // XML을 파싱(데이터 읽기) => 읽은 데이터 저장 ==> SqlSesionFactory private static SqlSessionFactory ssf; // 초기화 => XML을 읽기(자동으로 셋팅) static { try { // 1. XML파일 읽기 Reader reader=Resources.getResourceAsReader("Config.xml"); // Config에 등록되어 있는 모든 XML파일 읽는다 // 파일명에 대소문자를 구분한다 // 2. XML을 파싱 : 필요한 데이터 읽어 간다 (마이바티스 라이브러리가 읽어 간다) => 저장을 하고 사용한다 ssf=new SqlSessionFactoryBuilder().build(reader); // 파싱 => SAX(읽기전용) => 태그를 한개씩 읽어와서 필요데이터를 저장하는 방식 }catch(Exception ex) { // 에러처리 System.out.println(ex.getMessage()); } } public static List<DataBoardVO> boardListData(Map map) { List<DataBoardVO> list=new ArrayList<DataBoardVO>(); // Connection을 사용한 다음에 반드시 반환 ==> SqlSession SqlSession session=null; // SqlSession => Connection과 동일한 역할 수행 // 컴파일 예외처리는 없다 => 초반에 에러처리하기 위해서 => 예외처리를 하는 것이 좋다 => null try { // 실행 : 정상수행 : try수행 => finally수행 // 비정상 : 중간에 catch수행 => finally수행 // 1. 미리 만든 Connection객체를 얻어 온다 session=ssf.openSession(); // 2. XML에 있는 SQL문장을 실행후에 결과값을 달라 list=session.selectList("boardListData",map); }catch(Exception ex) { ex.printStackTrace();//실행하는 과정을 보여준다 } finally { // 반환 => Connection=>close() if(session!=null) session.close(); /* * close() * { * if(ps!=null) ps.close(); * if(conn!=null) conn.close(); ==> disConnection() * } */ } return list; } // 총페이지 ==> id="boardTotalPage" // <select id="boardTotalPage" resultType="int"> public static int boardTotalPage() { // 지역변수는 반드시 초기화 /* * 클래스 => null * String => null */ int total=0; SqlSession session=null; try { // 1. connection 객체를 가지고 온다 session=ssf.openSession(); total=session.selectOne("boardTotalPage"); }catch(Exception ex) { ex.printStackTrace(); } finally { if(session!=null)//연결이 되어 있다면 session.close(); // 연결을 종료 (자동으로 반환 => 반환 다시 사용이 가능) } return total; } // 데이터 추가 public static void boardInsert(DataBoardVO vo) { SqlSession session=null; try { session=ssf.openSession(true);// commit을 실행한다 // INSERT,UPDATE,DELETE => 데이터베이스 변경 => 반드시 COMMIT session.insert("boardInsert",vo); // 여러개의 SQL문장을 실행하면 //session.commit(); }catch(Exception ex) { // 에러 처리 ex.printStackTrace(); } finally { if(session!=null) // 오라클에 연결되어 있다면 session.close(); } } public static DataBoardVO boardDetailData(int no) { // 데이터를 받을 변수 설정 DataBoardVO vo=new DataBoardVO(); // 오라클 연결 SqlSession session=null;// Connection => SqlSession안에 Connection기능을 가지고 있다 // 데이터를 가지고 오는 과정 에러가 발생할 수 있다 => 사전에 에러방지 프로그램 => 예외처리 /* * 예외처리 * = 직접 처리 (에러가 발생하면 바로 처리해서 사용) try~catch * = 간접처리 (시스템 에러발생여부만 확인하고 에러 회피) throws */ try { // 정상적으로 실행 => 에러 => catch를 수행하고 점프 // 연결 session=ssf.openSession(); // Commit을 포함하지 않는다 // 작업 수행 // 1. 조회수 증가 // <update id="hitIncrement" parameterType="int"> session.update("hitIncrement",no); session.commit();// 포함이 안되면 조회수가 증가를 하지 않는다 // 2. 증가된 조회수를 포함해서 데이터 가지고 오기 // <select id="boardDetailData" resultType="DataBoardVO" parameterType="int"> vo=session.selectOne("boardDetailData", no); }catch(Exception ex) { // 에러가 났을 경우에 처리 (복구) ex.printStackTrace();//어떤 에러가 났는지 확인 } finally { // 정상수행 ,비정상 수행 상관없이 => 무조건 수행 (서버연결 해제,데이터베이스 연결 해제) if(session!=null) // 연결되어 있다면 session.close(); // ps.close(), conn.close() => disConnection() } return vo;// 사용자가 요청한 데이터를 받아 볼 수 있다 } // 찾기 관련 내용 // 찾은 갯수 // <select id="boardFindCount" resultType="int" parameterType="hashmap"> public static int boardFindCount(Map map) { int count=0; // 연결(오라클) => 객체 SqlSession session=null; try { session=ssf.openSession(); count=session.selectOne("boardFindCount",map); }catch(Exception ex) { // 에러 처리 ex.printStackTrace(); } finally { if(session!=null) session.close(); // conn.close() => DBCP (반환=>재사용) } return count; } public static List<DataBoardVO> boardFindData(Map map) { List<DataBoardVO> list=new ArrayList<DataBoardVO>(); // 연결 객체 SqlSession session=null; try { // 객체주소 얻기 session=ssf.openSession(); // COMMIT(X) list=session.selectList("boardFindData",map); }catch(Exception ex) { ex.printStackTrace(); } finally { if(session!=null) session.close(); } return list; } // 삭제 하기 // JSP(요청) ==> databoard-mapper.xml ==> DAO 처리 ==> JSP에서 받아서 화면 출력 public static boolean boardDelete(int no,String pwd) { boolean bCheck=false; SqlSession session=null; try { // Conection session=ssf.openSession(); // 비밀번호 가지고 오기 // <select id="boardGetPassword" resultType="String" parameterType="int"> String db_pwd=session.selectOne("boardGetPassword",no); if(pwd.equals(db_pwd)) { bCheck=true; // 실제 삭제 // <delete id="boardDelete" parameterType="int"> session.delete("boardDelete",no); // 반드시 commit session.commit(); } else { bCheck=false; } }catch(Exception ex) { ex.printStackTrace(); } finally { // session을 닫는다 (connection,preparedstatement 포함) if(session!=null) session.close(); } return bCheck; } // <select id="boardGetInfoData" resultType="DataBoardVO" parameterType="int"> public static DataBoardVO boardGetInfoData(int no) { DataBoardVO vo=new DataBoardVO(); SqlSession session=null; try { // 연결 session=ssf.openSession(); vo=session.selectOne("boardGetInfoData",no); }catch(Exception ex) { // 에러 처리 ex.printStackTrace(); } finally { // 닫기 if(session!=null) session.close(); } return vo; } public static DataBoardVO boardUpdateData(int no) { DataBoardVO vo=new DataBoardVO(); SqlSession session=null; try { session=ssf.openSession(); vo=session.selectOne("boardDetailData",no); }catch(Exception ex) { ex.printStackTrace(); } finally { if(session!=null) session.close(); } return vo; } // 수정하기 public static boolean boardUpdate(DataBoardVO vo) { boolean bCheck=false; SqlSession session=null; try { session=ssf.openSession(); String db_pwd=session.selectOne("", vo.getNo()); if(db_pwd.equals(vo.getPwd())) { bCheck=true; // 본인이면 session.update("boardUpdate",vo); // 저장한다 session.commit(); } else { //본인이 아니면 bCheck=false; } }catch(Exception ex) { // 에러처리 ex.printStackTrace(); } finally { if(session!=null) session.close(); // 연결종료 => 다시 사용하기 위한 반환 } return bCheck; } } | cs |
- DAO : xml 파싱 후 결과값을 받는 위치로 DAO에서 메소드를 호출해준다.
- Config.xml에 등록되어 있는 모든 XML파일을 읽는다.
- XML을 파싱하면 마이바티스 라이브러리가 필요한 데이터를 읽어간다. => 저장 후 사용
- SAX(읽기전용)
: 태그를 한개씩 읽어와서 필요한 데이터를 저장하는 방식
JAXP | SAX : 읽기 => 일반적으로 모든 라이브러리는 SAX방식을 사용한다 => MyBatis,Spring... |
JAXB | binding |
#databoard-mapper.xml
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | <?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="com.sist.dao.databoard-mapper"> <select id="boardListData" resultType="DataBoardVO" parameterType="hashmap"> SELECT no,subject,name,TO_CHAR(regdate,'YYYY-MM-DD') as dbday,hit,num FROM (SELECT no,subject,name,regdate,hit,rownum as num FROM (SELECT no,subject,name,regdate,hit FROM databoard1 ORDER BY no DESC)) WHERE num BETWEEN #{start} AND #{end} </select> <select id="boardTotalPage" resultType="int"> SELECT CEIL(COUNT(*)/10.0) FROM databoard1 </select> <!-- 내용보기 : 다운로드 --> <!-- 중복된 문장이 있는 경우 처리:재사용 --> <sql id="where-no"> WHERE no=#{no} </sql> <!-- 조회수 증가 --> <update id="hitIncrement" parameterType="int"> UPDATE databoard1 SET hit=hit+1 <include refid="where-no"/> </update> <!-- 실제 데이터 읽기 --> <select id="boardDetailData" resultType="DataBoardVO" parameterType="int"> SELECT no,name,subject,content,TO_CHAR(regdate,'YYYY-MM-DD') as dbday, hit,filename,filesize FROM databoard1 <include refid="where-no"/> </select> <!-- 추가 --> <!-- DataBoardVO #{name} vo.getName() , #{pwd} vo.getPwd()--> <!-- Map에 데이터를 묶어서 전송 , VO에 데이터를 묶어서 전송 VO에 소속된 변수 => VO VO에 없는 변수가 있는 경우 => Map --> <!-- <insert id="boardInsert" parameterType="DataBoardVO"> INSERT INTO databoard VALUES( (SELECT NVL(MAX(no)+1,1) FROM databoard),#{name},#{subject}, #{content},#{pwd},SYSDATE,0,#{filename},#{filesize} ) </insert> --> <insert id="boardInsert" parameterType="DataBoardVO"> <!-- Sequence SELECT NVL(MAX(no)+1,1) FROM databoard을 먼저 수행한 후에 결과값을 no에 받아서 INSERT 문장에 추가 --> <selectKey keyProperty="no" resultType="int" order="BEFORE"> SELECT NVL(MAX(no)+1,1) FROM databoard1 </selectKey> INSERT INTO databoard1 VALUES( #{no}, #{name}, #{subject}, #{content}, #{pwd}, SYSDATE, 0, #{filename}, #{filesize} ) <!-- 수정하기 --> <update id="boardUpdate" parameterType="DataBoardVO"> UPDATE databoard1 SET name=#{name}, subject=#{subject}, content=#{content} <include refid="where-no"/> </update> <!-- 삭제하기 --> <select id="boardGetPassword" resultType="String" parameterType="int"> SELECT pwd FROM databoard1 <include refid="where-no"/> </select> <!-- 게시물이 삭제가 되면 업로드된 파일을 삭제 --> <select id="boardGetInfoData" resultType="DataBoardVO" parameterType="int"> SELECT filename, filesize FROM databoard1 <include refid="where-no"/> </select> <!-- 본인일 경우에는 게시물을 삭제 --> <delete id="boardDelete" parameterType="int"> DELETE FROM databoard1 <include refid="where-no"/> </delete> <!-- 찾기 --> <!-- ${fd} => 컬럼명,테이블명 (name LIKE , subject LIKE, content LIKE) #{ss} => 일반 데이터 --> <select id="boardFindData" resultType="DataBoardVO" parameterType="hashmap"> SELECT no,subject,name,TO_CHAR(regdate,'YYYY-MM-DD') as dbday,hit FROM databoard1 WHERE ${fd} LIKE '%'||#{ss}||'%' </select> <select id="boardFindCount" resultType="int" parameterType="hashmap"> SELECT COUNT(*) FROM databoard1 WHERE ${fd} LIKE '%'||#{ss}||'%' </select> </mapper> | cs |
- mapper : SQL문장이 어디에 있는지 확인하기 위해서 사용
- XML을 씀으로써 귀찮은 코드들이 줄고 사용자 정의기 때문에 데이터 전달이 더 쉬워집니다
추가로 Connection, PreParedStatement, ResultSet 등등을 MyBatis에서 해주기 때문에 유지보수에도 용이합니다.
# Config.xml
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 | <?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> <properties resource="db.properties"/> <typeAliases> <!-- VO를 등록 --> <typeAlias type="com.sist.dao.DataBoardVO" alias="DataBoardVO"/> </typeAliases> <!-- 오라클 연결하는 부분 : getConnection() --> <environments default="development"><!-- 개발 환경을 만든다 --> <environment id="development"> <transactionManager type="JDBC"/> <!-- 오라클 정보를 모아서 MyBatis 라이브러리에 전송 : DataSource --> <dataSource type="POOLED"> <!-- 오라클 연결을 위한 기본정보를 마이바티스로 전송 --> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <mappers> <mapper resource="com/sist/dao/databoard-mapper.xml"/><!-- 분산 여러개를 등록이 가능 --> </mappers> </configuration> | cs |
* UNPOOLED : 요청(SQL문장 실행)할때 오라클 연결 , 결과값을 가지고 오면 오라클 연결 해제
- 단점 : 연결하는 시간이 많이 소모(연결이 지연될 수 도 있다)
* POOLED : DBCP (미리 Connection을 연결하고 요청시마다 연결된 Connection을 넘겨주고 사용 후 반환
- 재사용이 가능
- 연결하는 소모되지 않는다
- Connection의 생성 갯수를 제어 할 수 있다
- 일반적으로 웹프로그램에서는 기본으로 사용
포스팅 양이 많아져서
두번째 포스팅으로 뵙겠습니다.
'Web > JSP' 카테고리의 다른 글
[JSP] JSP에서 JSTL사용하여 타임 셋팅해서 팝업띄우기 (0) | 2021.02.10 |
---|---|
[JSP] java로 특정 날짜(Date) 지정해서 popup 팝업 뜨게 하기(2) (0) | 2021.02.10 |
[JSP] jsp창에 java로 특정 날짜 지정해서 popup 팝업 뜨게 하기 (0) | 2021.02.08 |
[JSP,MyBaits] CRUD 게시판 만들기(3) #업로드/다운로드/수정/삭제 (0) | 2020.09.24 |
[JSP,MyBatis] CRUD 게시판 만들기(2) #업로드/다운로드/수정/삭제 (0) | 2020.09.24 |