160607: 58회차
종료하기 전 티스토리 네이버 로그아웃 할 것
1. 툴
동일
추가시:
2. 폴더
동일
추가시:
3. 사용할 사이트
동일
추가시:
4. 공부하는 것
컨트롤러 <- 인터페이스 -> 매니저 <-인터페이스->DAO <-CRUD처리해주는 Query->DB
근데 이제 DAO의 CRUD처리하는 query를 없앨거임
- SQL Maps 프레임워크는 관계형 데이터베이스에 접근할 때 필요한 자바코드를
현저하게 줄일수 있도록 도와줍니다.
- SQL Maps는 간단한 XML서술자를 사용해서 간단하게 자바빈즈를 SQL statement
에 맵핑시킵니다.
- SQL Map API는 프로그래머에게 자바빈즈를 PreparedStatement파라미터와
ResultSets으로 쉽게 맵핑할수 있도록 합니다.
- SQL과 비즈니스 로직이 분리되어 있어 배포 및 유지보수, 재활용성이 뛰어납니다.
- 일반 SQL뿐만 아니라 저장 프로시져까지 iBATIS는 처리할 수 있습니다.
- 파라미터를 기반으로 동적으로 실행 할 SQL을 지정할 수 있습니다.
1. - iBATIS의 위치
JSP ---> Spring(Struts2)---> Manager ---> DAO ---> iBATIS ---> SQL ---> ORACLE
| |
| |
+----- DTO(Value Object, Domain Object -------+
- iBATIS의 설정의 핵심 개념

Mapped Statement 는 아이바티스나 마이바티스에서 제공해주는 객체의 메소드를 통해서 사용함
- iBATIS의 설정파일
. SqlMapConfig 파일: 최상단에 위치 하며 전체옵션을 설정하고
각각의 SQL Map파일들의 위치를 지정합니다.
. Sql Map 파일 : 애플리케이션이 데이터베이스와 소통하기 위해 제공
하는 입력 파라미터 값과 조합되는 매핑 구문을 정의 합니다.
-데이터베이스는 sql밖에 못 알아들으니까 얘랑 소통하기 위해 필요한 것 -.-
2. 다운 로드 및 설치 (현재는 MyBATIS로 변경됨)
- http://ibatis.apache.org
- ibatis-2.3.4.726.jar 파일을 복사하여 'lib' 폴더에 복사합니다.
3. SQL Maps 설정 파일
>>>>> ibatis-2.3.0.677/simple_example/com/mydomain/data/SqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig
PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
<!-- Configure a built-in transaction manager. If you're using an
app server, you probably want to use its transaction manager
and a managed datasource -->
<transactionManager type="JDBC" commitRequired="false">
<dataSource type="SIMPLE">
<property name="JDBC.Driver" value="org.hsqldb.jdbcDriver"/>
<property name="JDBC.ConnectionURL" value="jdbc:hsqldb:."/>
<property name="JDBC.Username" value="sa"/>
<property name="JDBC.Password" value="sa"/>
</dataSource>
</transactionManager>
<!-- List the SQL Map XML files. They can be loaded from the
classpath, as they are here (com.domain.data...) -->
<sqlMap resource="com/mydomain/data/Account.xml"/>
<!-- List more here...
<sqlMap resource="com/mydomain/data/Order.xml"/>
<sqlMap resource="com/mydomain/data/Documents.xml"/>
-->
</sqlMapConfig>
4. SQL Map 파일
>>>>>> ibatis-2.3.0.677/simple_example/com/mydomain/data/Account.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="Account">
<!-- Use type aliases to avoid typing the full classname every time. -->
<typeAlias alias="Account" type="com.mydomain.domain.Account"/>
<!-- Result maps describe the mapping between the columns returned
from a query, and the class properties. A result map isn't
necessary if the columns (or aliases) match to the properties
exactly. -->
<resultMap id="AccountResult" class="Account">
<result property="id" column="ACC_ID"/>
<result property="firstName" column="ACC_FIRST_NAME"/>
<result property="lastName" column="ACC_LAST_NAME"/>
<result property="emailAddress" column="ACC_EMAIL"/>
</resultMap>
<!-- Select with no parameters using the result map for Account class. -->
<select id="selectAllAccounts" resultMap="AccountResult">
select * from ACCOUNT
</select>
<!-- A simpler select example without the result map. Note the
aliases to match the properties of the target result class. -->
<select id="selectAccountById" parameterClass="int" resultClass="Account">
select
ACC_ID as id,
ACC_FIRST_NAME as firstName,
ACC_LAST_NAME as lastName,
ACC_EMAIL as emailAddress
from ACCOUNT
where ACC_ID = #id#
</select>
<!-- Insert example, using the Account parameter class -->
<insert id="insertAccount" parameterClass="Account">
insert into ACCOUNT (
ACC_ID,
ACC_FIRST_NAME,
ACC_LAST_NAME,
ACC_EMAIL
)values (
#id#, #firstName#, #lastName#, #emailAddress#
)
</insert>
<!-- Update example, using the Account parameter class -->
<update id="updateAccount" parameterClass="Account">
update ACCOUNT set
ACC_FIRST_NAME = #firstName#,
ACC_LAST_NAME = #lastName#,
ACC_EMAIL = #emailAddress#
where
ACC_ID = #id#
</update>
<!-- Delete example, using an integer as the parameter class -->
<delete id="deleteAccountById" parameterClass="int">
delete from ACCOUNT where ACC_ID = #id#
</delete>
</sqlMap>
5. SqlMapClient API를 통해 statement를 수행하기.
이 클래스는 buildSqlMap()이라는 하나의 중요한 정적 메소드를 가진다.
- buildSqlMap()메소드는 간단하게 sqlMap-config.xml의 내용을 읽을수 있는
Reader인스턴스를 가져온다.
-----------------------------------------------------------------------------------------------------------------------
- SqlMapClient는 이것에 관련된 모든 맵핑된 statement를 수행하기 위한 API를
제공한다. 그 메소드들은 아래와 같다.
------------------------------------------------------------------------
1. 1) 라이브러리 2) xml 설정파일 필요
2. 2)에는 1)전체옵션을 갖고 있는 xml 2) 쿼리문을 갖고 있는 xml 이 있음
3. 메소드는 ★3)sqlmapclient API에 있는 애들임
4. ★의 메소드는 insert, update, delete, queryforobject, queryforlist가 있음
5. 얘네 실행하기 위한 query는 id값으로 가져옴
iBatis -> 지금은 myBatis만 사용!!
얘네들 + spring하면 소스 코드가 간소화되어서 사용하기 좋음
field 안에 있는 data 값 뽑을 때 #를 사용하는데 이걸 names mapping이라고 함
#이름# dlfms tlrdmfh tkdydgka
data의 위치는 parameterClass = "Account" 요기 있는 객체의 멤버변수인 것임
구) DAO 안의 SQL문 -> Result Set을 이용함
신) Mapped Statement 확인 -> 끝!
왜냐면 SQLmapClient가 내부적으로 알아서 연결을 해주기 때문임.
1.전체 xml이 필요함 - 계정, Driver
2. Sql Mapper 필요함 - 실행할 쿼리문
3. Sql map client - xml의 값을 읽어들여서 실행/처리 해주는 것
Query문 구별을 위한것 : id
SqlMapClient의
StatementName = id
parameterObject = update할 객체
queryforObject - return형이 1개인 select
queryforList - return 형이 list 인 select
- 얘네 둘이는 쿼리 안에서 resultmap / resultclass를 선언해놔야 한다
어쨌든 제일 중요한 건
sqlmapclient가 method를 호출하는 것
메소드 중에 좀 중요한 것
insert
update
delete
queryforobject
queryforlist
얘네 사용하기 위해선 id값이 필요함 (id는 parameter로 받음)
--------------------------------------------------------------------------
와 다른 옵션에 대한 설정을 제공하는 중앙집중적인 XML설정 파일을 사용해서 설정
된다.
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
그렇게 함으로써 속성파일내에 각각의 이름지어진 값들은 SQL Maps설정파일내에
조될수 있는 변수가 될수 있고 모든 SQL Maps는 내부에서 참조된다.
예를 들면 속성파일이 다음을 포함한다면
예를 들면,
패스나 어떤 유효한 URL로부터 로드될수 있다.
예를 들면 고정된 파일경로를 위해 다음처럼 사용한다.

3) <transactionManager> 요소
SQL Maps를 위한 트랜잭션 관리를 설정하도록 한다. type 속성값은 사용하기 위한
중에 하나로 표시할수 있다.
이 설정은 JNDI자원으로부터 사용자 트랜잭션을 위치시키기 위한 UserTransaction
속성값을 요구한다.
한다는 것이다.
이 셋팅은 비-트랜잭션(예를 들면 읽기전용) 데이터베이스에 유용하다.
프레임워크 생명주기의 부분처럼 트랜잭션이 커밋되거나 롤백되지 않는다.
위한 데이터소스를 설정하기 위한 속성 값의 집합이다.
여기엔 프레임워크에서 제공되는 3가지 데이터소스타입이 있다.
제공하기 위해 기본적으로 풀링(pooling) 데이터소스 구현을 제공한다.
이것은 iBATIS SimpleDataSource connection풀링을 기초로 한다.
DBCP (Database Connection Pool)을 사용한다.
이 DataSource는 애플리케이션/웹 컨테이너가 DataSource구현물을 제공하지 못하거나
당신이 standalone애플리케이션을 구동할 때 이상적이다.
<transactionManager type="JDBC">
connection pool 그리고 제공되는 DataSource구현물이 있을 때 사용한다.
JDBC DataSource구현물에 접근하기 위한 표준적인 방법은 JNDI컨텍스트를
통하는것이다.
트랜잭션 자원을 포함하기 위해서는 JTA트랜잭션 관리가 요구된다.
사용한다. SqlMapClient인스턴스에 의해 사용되는 각각의 SQL Map XML파일은
반드시 선언되어야 한다.
SQL Map XML파일은 클래스패스나 URL로부터 스트림(stream)자원처럼 로드 될것이다.
당신은 SQL Maps를 명시해야 한다. 다음은 그에 대한 예이다.
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
<select>
id - 태그를 구분하는 유일한 값
parameterClass - 조건절에 사용할 value값 , 이름을 접근 #name#
resultClass - select 태그에만 선언, 결과값을 담을 클래스를 선언
parameterMap - ?,? 표시로 접근, parameterMap 태그를 따로 선언해야함
resultMap - resultClass와 같은 역할하며 resultMap 태그를 따로 선언해야함
- 컬럼의 이름과 저장할 객체에 필드가 이름이 다를때 사용
<insert>
id -
parameterClass -
parameterMap -
<update>
id -
parameterClass -
parameterMap -
<delete>
id -
parameterClass -
parameterMap -
<sql>
id -
<include>
refid - <sql>로 생성된 쿼리문을 refid=id 로 해서 가져온다.
<sql id="boardWhere">
<isNotEmpty property="keyword" prepend="AND">
<isEqual property="keytype" compareValue="title">
title LIKE '%' || #keyword# || '%'
</isEqual>
<isEqual property="keytype" compareValue="content">
contents LIKE '%' || #keyword# || '%'
</isEqual>
<isEqual property="keytype" compareValue="userid">
userid LIKE '%' || #keyword# || '%'
</isEqual>
<isEqual property="keytype" compareValue="all">
(
title LIKE '%' || #keyword# || '%'
OR
contents LIKE '%' || #keyword# || '%'
OR
userid LIKE '%' || #keyword# || '%'
)
</isEqual>
</isNotEmpty>
</sql>
<select id="getList" parameterClass="boardCmd" resultMap="domain">
SELECT
boardSeq, categoryId, userid, title, contents, hit, regDate, grp, dep, stp,
commCnt, attachCnt, isReply, rowNum
FROM (
SELECT
boardSeq, categoryId, userid, title, contents, hit, regDate, grp, dep, stp,
commCnt, attachCnt, isReply,
ROW_NUMBER() OVER(ORDER BY grp DESC, stp) as rowNum
FROM
board
WHERE
categoryId = #categoryId#
<dynamic>
<include refid="boardWhere" />
</dynamic>
) a
WHERE rowNum BETWEEN #start# AND #end#
</select>
<parameterMap>
<parameterMap id="boardColumn" class="Board">
<parameter property="boardSeq" jdbcType="NUMBER" />
<parameter property="title" jdbcType="NVARCHAR" />
<parameter property="contents" jdbcType="NTEXT" />
</parameterMap>
<insert id="insert" parameterMap="boardColumn">
INSERT INTO board (
boardSeq,
title,
contents
) VALUES (
?, ?, ?
)
</insert>
<selectKey>
자동 key 생성
<selectKey keyProperty="boardSeq" resultClass="int">
SELECT nextVal(#sequence#)
</selectKey>
INSERT (....) VALUES (boardSeq, ...) Table
<selectKey keyProperty="boardSeq" resultClass="int">
INSERT .......... Table
SELECT SCOPE_IDENTITY()
</selectKey>
Collection
한방쿼리
Board.java
private int boardSeq ;
private String title;
private String contents;
private List<Attachment> attachList;
:
BoardDao.java
getSqlMapClientTemplate().queryForObject("Board.get", 10);
:
<sqlMap namespace="Board">
<resultMap id="boardView" class="org.apache.domain.Board">
<result property="boardSeq" column="boardSeq" />
<result property="title" column="title" />
<result property="contents" column="contents" />
<result property="attachList" select="Board.getAttachList" column="boardSeq" />
</resultMap>
<select id="get" parameterClass="int" resultMap="boardView">
SELECT boardSeq, title, contents FROM board
WHERE boardSeq = #value#
</select>
<select id="getAttachList" parameterClass="int" resultClass="org.apache.domain.Attachment">
parameterClass - 가져오는 파일의 형식
resultClass - 리턴형
SELECT boardSeq, attachSeq, fileName FROM attachment WHERE boardSeq = #value#
</select>
</sqlMap>
다이나믹 쿼리
동적맵핑 문장
<select id="get" parameterClass="cmd" resultClass="board">
SELECT *
FROM board
<dynamic prepend=" WHERE " open="(" close=")">
<isNotEmpty property="keyword">
<isEqual property="keytype" compareValue="title">
title LIKE '%' || #keyword# || '%'
</isEqual>
<isEqual property="keytype" compareValue="content">
contents LIKE '%' || #keyword# || '%'
</isEqual>
</isNotEmpty>
</dynamic>
</select>
dynamic 요소
property – 비교되는 프라퍼티(필수)
prepend – statement에 붙을 오버라이딩 가능한 SQL부분(옵션)
open – 결과적인 전체내용물을 열기위한 문자열(옵션)
close – 결과적인 전체내용물을 닫기위한 문자열(옵션)
이항연산
removeFirstPrepend - 처음으로 내용을 출력하는 자식 요소의 prepend속성 값을 출력할지 여부
comparePreperty - property 속성과 비교할 파라미터 객체의 프로퍼티
compareValue - property 속성과 비교할 정적인 값
<isEqual> -
<isNotEqual> -
<isGreaterThan> - 값이 큰지
<isGreaterEqual> - 값이 크거나 같은지
<isLessThan> - 값이 작은지
<isLessEqual> - 값이 작거나 같은지
<select id="board parameterClass="cmd" resultClass="Board">
SELECT * FROM board
<dynamic prepend=" WHERE ">
<isEqual property="userType" compareValue="ADMIN">
userType = 'ADMIN'
</isEqual>
<isNotEqual property="userType" compareValue="ADMIN">
userType <> 'ADMIN'
</isNotEqual>
</dynamic>
</select>
단항연산
removeFirstPrepend - 처음으로 내용을 출력하는 자식 요소의 prepend속성 값을 출력할지 여부
<isPropertyAvailable> - 프로퍼티가 파라메터에 존재하는지 검사, domain에서는 프로퍼티를, Map에서는 key를 찾는다.
<isNotPropertyAvailable> - 프로퍼티가 파라메터에 존재하지 않는지 검사, domain에서는 프로퍼티를, Map에서는 key를 찾는다.
<isNull> -
<isNotNull> -
<isEmpty> -
<isNotEmpty> -
파라미터 요소 (parameterClass, parameterMap)
<isParameterPresent> - 파라메터가 존재하는지
<isNotParameterPresent> - 파라메터가 존재하지 않는지
<select id="board" resultClass="Board">
SELECT * FROM board
<isParameterPresent prepend=" WHERE ">
<isNotEmpty property="category">
category = #category#
</isNotEmpty>
</isParameterPresent>
</select>
iterate
property (필수) -
prepend -
open - the string to open a full iteration, useful for brackets. (option)
close - the string with which to close the entire iteration, useful for brackets. (Optional) conjunction - the string to be applied between each iteration, and is useful for the AND and OR. (option)
removeFirstPrepend -
ibatis/board.xml
<delete id="deleteXE" parameterClass="map">
DELETE FROM board
<dynamic prepend=" WHERE ">
<iterate property="boardSeqs" open=" num IN (" close=")" conjunction=",">
#boardSeqs[]#
</iterate>
</dynamic>
</delete>
sql : delete from board
where num in (1,3,5,7,9);
BoardDAO.java
:
@Autowired
BoardTest.java
package spring.sts.model;
board.xml
>>>>> src/main/resources/ibatis-config.xml
-----------------------------------------------------------------------------------------------------
1) SQL MAP XML 파일
id - 동일한 값이 없어야 함
parameterClass - 여러개를 보내고 싶을 때는 map이나 dto
resultClass - 이게 없으면 결과값이 안나옴 !! - 이거의 타입은 결과값이 따라 다름
- 실제 데이타가 담겨질 형이거나 기본형으로 선언해주면 됨
- 갖다 쓰는거니까 select에서만 필요함
parameterMap - ? (preparedStatement처럼) 로 접근함, 태그를 따로 선언해야함
- ?가 위치할 곳이 #id# 얘 자리임
- 이걸 쓰기 위해서는 map을 선언해줘야함
resultMap - resultClass와 같은 역할하며 resultMap 태그를 따로 선언해야함
- 컬럼의 이름과 저장할 객체에 필드가 이름이 다를때 사용
- result의 property랑 column명이 다를 떄 사용
-만약에 alias 썼으면 resultClass 써도 됨
그러니까
1) parameterClass = parametermap
인데 values에 들어갈 게
#아이디의존재# 하고 ? 하고 차이임 ㅇㅇ
2) resultClass = resultMap
인뎅
resultClass는
그냥 이름을 가져다가 적어주면 되고
resultMap은 property랑 column명이 다를 때 사용함
근데 만약에 resultMap 써야 할 거 같은 곳에 as (alias)로 적어주면 resultClass 써도 됨
그리고 result친구들은 select에서만 필요함
-----------------------------------------
<sql>
id -
얘는 조각 쿼리임 ㅇㅇ
<sql id="boardWhere">
<isNotEmpty property="keyword" prepend="AND">
<isEqual property="keytype" compareValue="title">
title LIKE '%' || #keyword# || '%'
</isEqual>
<isEqual property="keytype" compareValue="content">
contents LIKE '%' || #keyword# || '%'
</isEqual>
<isEqual property="keytype" compareValue="userid">
userid LIKE '%' || #keyword# || '%'
</isEqual>
<isEqual property="keytype" compareValue="all">
(
title LIKE '%' || #keyword# || '%'
OR
contents LIKE '%' || #keyword# || '%'
OR
userid LIKE '%' || #keyword# || '%'
)
</isEqual>
</isNotEmpty>
</sql>
여기서 isEqual이 모두 생성이 되는 게 아니라 개 중 1개가 생성되는 것
(OR) 임
그래서 뭐가 생성될 지는 모르겠지만 갖다 쓰는 법은
sql id인 boardWhere로 갖다 쓰면 됨
prepend는 저 쿼리문을 사용하기 전에
AND라는 게 들어간다는 얘기임 (연결용)
-----------------
<include>
refid - <sql>로 생성된 쿼리문을 refid=id 로 해서 가져온다.
----------------------------------------------------
<select id="getList" parameterClass="boardCmd" resultMap="domain">
SELECT
boardSeq, categoryId, userid, title, contents, hit, regDate, grp, dep, stp,
commCnt, attachCnt, isReply, rowNum
FROM (
SELECT
boardSeq, categoryId, userid, title, contents, hit, regDate, grp, dep, stp,
commCnt, attachCnt, isReply,
ROW_NUMBER() OVER(ORDER BY grp DESC, stp) as rowNum
FROM
board
WHERE
categoryId = #categoryId#
<dynamic>
<include refid="boardWhere" />
</dynamic>
) a
WHERE rowNum BETWEEN #start# AND #end#
</select>
그래서
<dynamic>
<include refid="boardWhere" />
</dynamic>
이부분에서처럼 include 태그 안에서 id를 가져다가 쓰면
저 위의 boardWherd의 isEqual문 중에 해당되는 하나가 저 안에 들어감 ㅇㅇ
-------------------------------------------------------
그래서 조각 쿼리<sql>를 만들었다! 고 하면 <include>로 가져다 쓰면 됨
----------------------------------------------------------
<parameterMap>
<parameterMap id="boardColumn" class="Board">
<parameter property="boardSeq" jdbcType="NUMBER" />
<parameter property="title" jdbcType="NVARCHAR" />
<parameter property="contents" jdbcType="NTEXT" />
</parameterMap>
<insert id="insert" parameterMap="boardColumn">
INSERT INTO board (
boardSeq,
title,
contents
) VALUES (
?, ?, ?
)
</insert>
이렇게 ?를 사용하려면 꼭 parameterMap을 적어줘야한다.
<parameterMap id="boardColumn" class="Board">
요기서 Board는 실제로 존재하는 class를 적어줘야함
사실 parameterClass를 적어줘도 별 상관 없음
<!-- Insert example, using the Account parameter class -->
<insert id="insertAccount" parameterClass="Account">
insert into ACCOUNT (
ACC_ID,
ACC_FIRST_NAME,
ACC_LAST_NAME,
ACC_EMAIL
)values (
#id#, #firstName#, #lastName#, #emailAddress#
)
</insert>
이런 식으로 적어줘도 됩니다.
--------------------------------------------
1. a 테이블에 insert -> 1이라는 sequence 생성
2. b 테이블에 pk 라는 값으로 새로 insert -> 1 이라는 sequence 생성
이것이 1:1 관계
이럴 때
1의 1 sequence를 2의 값으로 사용하고 싶어질 때가 있음 ㅇㅇ
<selectKey>
자동 key 생성
<selectKey keyProperty="boardSeq" resultClass="int">
SELECT nextVal(#sequence#) //얘는 sequence값을 뽑아내는 거임
</selectKey>
INSERT (....) VALUES (boardSeq, ...) Table
<selectKey keyProperty="boardSeq" resultClass="int">
INSERT .......... Table
SELECT SCOPE_IDENTITY()
</selectKey>
이걸 굳이 selectKey로 사용하는 이유는
key값을 리턴받기 위해서임 (-_-);;
<insert>
insert into bbs ( bbsno
)values( )
</insert>
이렇게 안 쓰고
<insert>
insert into bbs (
)values( (select nvl(max(bbsno)) + 1 from bbsno ), )
</insert>
해도 되는뎅
이럴 때
<insert id = "create">
insert into bbs (bbsno, name......
)values( (select nvl(max(bbsno)) + 1 from bbsno ), )
</insert>
sqlMapClient.insert("create", BbsDTO);
이렇게 하고 (왜했지? -_-)
<insert id = "create">
<selectKey key = bbsno>
select nvl(max(bbsno)) + 1 from bbsno
</selectkey>
//이거를 만들면 현재 뭘(이 경우에서는 insert) 해주면서 사용된 키값을 리턴함
insert into bbs (bbsno, name......
)values(#bbsno#, #name#, ...) //조기 위에서 생성되어진 키값을 values에서 갖다씀
</insert>
sqlMapClient.insert("create", BbsDTO);
이러면 insert의 실패/성공 여부를 잘 알 수가 없으니까
sqlMapClient.insert("create", BbsDTO); - 리턴값: null or key값
sqlMapClient.update("create", BbsDTO); <-★ true / false 리턴함
그래서 리턴값 용으로는 update를 씀 (개발자가 사용 많이 함)
근데 굳이 키값 리턴 받고 싶지 않을 떄는
values 안에다가 원래 쓰던 대로 sequence값 쓰면 됨
그러면 null을 리턴함
- 성공 실패 여부 확인이 어려움
이게 쿼리 실행을 update로 하고 싶은 게 아니라 리턴값 떄문에 update를 쓰는 것
----------------------------------------------------------------------------------------
Collection
한방쿼리
Board.java // Board.java - DTO
private int boardSeq ;
private String title;
private String contents;
private List<Attachment> attachList; //Attachment - 클래스인것
:
BoardDao.java
getSqlMapClientTemplate().queryForObject("Board.get", 10); //select를 실행하는 queryForObject
//한건의 데이터를 리턴하려고 ㅇㅇ
//(id값 , parameter값)
:
<sqlMap namespace="Board">
<resultMap id="boardView" class="org.apache.domain.Board">
<result property="boardSeq" column="boardSeq" />
<result property="title" column="title" />
<result property="contents" column="contents" />
//위에 애들은 아무것도 리턴을 안함
<result property="attachList" select="Board.getAttachList" column="boardSeq" />
//근데 얘는 select에서 getAttachList라는 것을 호출함 -> 그리고 boardSeq 는 10
// <select id="getAttachList" parameterClass="int" resultClass="org.apache.domain.Attachment"> 이거임
// private List<Attachment> attachList; 니까 list로 리턴함 ㅇㅇ
// 아 그럼 select 가 여러개라서 한방쿼리가 아니라 list로 그거해서 그거한거군 ㅇㅇ..
//구래서 어 ㅡㅡ;......
//얘가 queryForObject처럼 실행할 수 있는 결과를 가지고 있는 무언가라고? ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
</resultMap>
<select id="get" parameterClass="int" resultMap="boardView">
// <resultMap id="boardView" class="org.apache.domain.Board"> 요기서 만든 것
SELECT boardSeq, title, contents FROM board
WHERE boardSeq = #value# //여기 10이 들어감!
</select>
<select id="getAttachList" parameterClass="int" resultClass="org.apache.domain.Attachment">
SELECT boardSeq, attachSeq, fileName FROM attachment WHERE boardSeq = #value#
</select>
//셀렉트가 두개
</sqlMap>
그래서 ㅇㅕ러 개의 쿼리를 한 방에 실행하는 것 -.-)...
이렇게 부르지는 않는데 그냥 여러 개를 한번에 실행할 수 있어서 이렇게 부르는 것
------------------------------------------------------
저것을 사용할 예시인거십니다
파일 업로드 게시판
1. 글번호, 이름, 제목, 내용, 파일 <- board
//근데 파일이 여러개 올라갈 수도 있으니까 파일 정보를 가지고 있는 뭔가도 있어야함
//그리고 파일만 리턴형이 list임 -.,-)
파일정보
1. 파일번호, 파일이름, 게시판번호,
1 a.txt 1 <- attachment
2 b.txt 1(boardSeq)
이 정보를 가지고 있는 것은 attachMent class의 하나의 정보인것
이걸 쓰려고!
[1] 1.에 해당되는 애들을 다 데려다가 select한 후에 resultMap에 박음
근데 file만 list형이니까
<result property="attachList" select="Board.getAttachList" column="boardSeq" />
이런 식으로 만듬 ㅇㅇ
[2] 그런 담에 쟤네 속성 하나씩 뽑아다가 list에다가 넣음 ㅇㅇ
-------------------------------------------------------------------
다이나믹 쿼리
동적맵핑 문장
<select id="get" parameterClass="cmd" resultClass="board">
SELECT *
FROM board
<dynamic prepend=" WHERE " open="(" close=")">
<isNotEmpty property="keyword">
<isEqual property="keytype" compareValue="title">
title LIKE '%' || #keyword# || '%'
</isEqual>
<isEqual property="keytype" compareValue="content">
contents LIKE '%' || #keyword# || '%'
</isEqual>
</isNotEmpty>
</dynamic>
</select>
keyword가 비어있을 경우 (empty) 면 아무것도 안 들어감!!
dynamic 요소
property – 비교되는 프라퍼티(필수)
<isNotEmpty property="keyword">
prepend – statement에 붙을 오버라이딩 가능한 SQL부분(옵션)
<dynamic prepend=" WHERE " open="(" close=")">
open – 결과적인 전체내용물을 열기위한 문자열(옵션)
close – 결과적인 전체내용물을 닫기위한 문자열(옵션)
이항연산
removeFirstPrepend - 처음으로 내용을 출력하는 자식 요소의 prepend속성 값을 출력할지 여부
이러면 prepend의 where를 한 번만 사용한다는 뜻 'ㅇ'
comparePreperty - property 속성과 비교할 파라미터 객체의 프로퍼티
compareValue - property 속성과 비교할 정적인 값
<isEqual> -
<isNotEqual> -
<isGreaterThan> - 값이 큰지
<isGreaterEqual> - 값이 크거나 같은지
<isLessThan> - 값이 작은지
<isLessEqual> - 값이 작거나 같은지
크거나 같을 때만 dynamic 태그를 생성하는 것
<select id="board parameterClass="cmd" resultClass="Board">
SELECT * FROM board
<dynamic prepend=" WHERE "> // 생성된 태그가 있으면 where 조건 사용!
<isEqual property="userType" compareValue="ADMIN">
userType = 'ADMIN'
</isEqual>
<isNotEqual property="userType" compareValue="ADMIN">
userType <> 'ADMIN' //이게 not이라는 뜻이래
</isNotEqual>
</dynamic>
</select>
단항연산
removeFirstPrepend - 처음으로 내용을 출력하는 자식 요소의 prepend속성 값을 출력할지 여부
<isPropertyAvailable> - 프로퍼티가 파라메터에 존재하는지 검사, domain에서는 프로퍼티를, Map에서는 key를 찾는다.
도메인 - DTO 같은 것
<isNotPropertyAvailable> - 프로퍼티가 파라메터에 존재하지 않는지 검사, domain에서는 프로퍼티를, Map에서는 key를
찾는다.
<isNull> -
<isNotNull> -
<isEmpty> -
<isNotEmpty> -
파라미터 요소 (parameterClass, parameterMap)
<isParameterPresent> - 파라메터가 존재하는지
<isNotParameterPresent> - 파라메터가 존재하지 않는지
<select id="board" resultClass="Board">
SELECT * FROM board
<isParameterPresent prepend=" WHERE ">
<isNotEmpty property="category">
category = #category#
</isNotEmpty>
</isParameterPresent>
</select>
iterate
property (필수) -
prepend -
open - the string to open a full iteration, useful for brackets. (option)
close - the string with which to close the entire iteration, useful for brackets. (Optional) conjunction - the string to
be applied between each iteration, and is useful for the AND and OR. (option)
removeFirstPrepend - 한번만 만들어지는 방법~~~
------------------------------
<<쓰프링에서 ㅁ바티스 쓰는법>>
1. 라이부러리가 있어야함
<!-- iBATIS setting -->
<dependency>
<groupId>org.apache.ibatis</groupId>
<artifactId>ibatis-sqlmap</artifactId>
<version>2.3.4.726</version>
</dependency>
<!-- DBCP setting -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- Oracle JDBC Driver-->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.1.0.7.0</version>
</dependency>
이걸 pom.xml에 붙여넣기함
이거 하면 maven dependencies에 jar 다운로드함! :D
이제 pool 쓸거임!
2. root-context.xml에다가 xmlns 추가할거임
xmlns:p="http://www.springframework.org/schema/p"
이렇게 스프링 프레임워크를 추가했음.
<!-- 데이터베이스 접속 설정 -->
<bean
id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
p:driverClassName="oracle.jdbc.driver.OracleDriver"
p:url="jdbc:oracle:thin:@127.0.0.1:1521:XE"
p:username="soldesk"
p:password="1234"
p:maxActive="2"
p:maxIdle="1"
p:defaultAutoCommit="true"
/>
<!-- iBATIS SQL 실행 클래스 -->
<bean id="sqlMapClient"
class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"
p:dataSource-ref="dataSource"
p:configLocation="WEB-INF/spring/ibatis-config.xml" />
<!-- Spring과 iBATIS 연결자 -->
<bean id="sqlMapClientTemplate"
class="org.springframework.orm.ibatis.SqlMapClientTemplate"
p:sqlMapClient-ref="sqlMapClient" />
//이거는 모델1이나 2에서 사용하는 게 아니라 스프링에서 사용하는 거라서 적어줘야 하는것!!
이렇게 bean 객체도 생성함
3. 3. WEB-INF/spring/ibatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig
PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<!-- SQL Mapping 파일 목록 -->
<sqlMapConfig>
<settings
useStatementNamespaces="true"
/>
<sqlMap resource="ibatis/board.xml" />
</sqlMapConfig>
이것도 만듬 ㅇㅇ
src/main/resources에다가
<sqlMap resource="ibatis/board.xml" />
1) ibatis 패키지를 만들고
2) 그안에 board.xml을 만듬
이제 board.xml 내용 채울거임
첨에는 그냥
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="board">
</sqlMap>
이정도 만들어주고
<typeAlias alias="DTO" type="spring.model.board.BoardDTO"/>
alias 정의해 주고
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="board">
<typeAlias alias="DTO" type="spring.model.board.BoardDTO"/>
<select id="list" parameterClass="Map" resultClass="DTO">
SELECT num, name, subject, regdate,count,filename,indent, r
FROM(
SELECT num, name, subject, regdate,count,filename,indent, rownum r
FROM(
SELECT num, name, subject, regdate,count,filename,indent
FROM board
ORDER BY ref DESC, ansnum
)
)
<![CDATA[
WHERE r >= #sno# and r <= #eno#
]]>
</select>
</sqlMap>
이런 거 만드는데
cdata 영역은 xml이 분석을 하지 않는 것 같음.
<dynamic>
</dynamic>
dynamic 안에 isequal문으로 구분해서 각각 다른 query문을 생성함
@Autowired
private SqlMapClientTemplate ibatis;
보드 매니저에다가 생성해주고
list 고칠거임
public List<BoardDTO> list(Map map) {
List<BoardDTO> list = null;
try{
list = dao.list(map,ibatis);
}catch(Exception e){
e.printStackTrace();
}finally{
}
return list;
}
매니저의 list이고
이제 DAO 고칠거임
public List<BoardDTO> list(Map map, SqlMapClientTemplate ibatis) throws SQLException {
return ibatis.queryForList("board.list", map);//(board.xml의 namespace.id, parameter객체)
}
이런식으로 고침! :D
지금까지 한 board.xml은
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="board">
<typeAlias alias="DTO" type="spring.model.board.BoardDTO" />
<select id="total" parameterClass="Map" resultClass="int">
SELECT count(*) from board
<dynamic prepend="WHERE">
<isEqual property="col" compareValue="name">
name like '%' | #word# || '%'
</isEqual>
<isEqual property="col" compareValue="subject">
subject like '%' | #subject# || '%'
</isEqual>
<isEqual property="col" compareValue="content">
content like '%' | #content# || '%'
</isEqual>
<isEqual property="col" compareValue="subject_content">
subject like '%' | #word# || '%'
OR
content like '%' | #word# || '%'
</isEqual>
</dynamic>
</select>
<select id="list" parameterClass="Map" resultClass="DTO">
SELECT num, name, subject, regdate,count,filename,indent, r
FROM(
SELECT num, name, subject, regdate,count,filename,indent, rownum r
FROM(
SELECT num, name, subject, regdate,count,filename,indent
FROM board
<dynamic prepend="WHERE">
<isEqual property="col" compareValue="name">
name like '%' | #word# || '%'
</isEqual>
<isEqual property="col" compareValue="subject">
subject like '%' | #subject# || '%'
</isEqual>
<isEqual property="col" compareValue="content">
content like '%' | #content# || '%'
</isEqual>
<isEqual property="col" compareValue="subject_content">
subject like '%' | #word# || '%'
OR
content like '%' | #word# || '%'
</isEqual>
</dynamic>
ORDER BY ref DESC, ansnum
)
)
<![CDATA[
WHERE r >= #sno# and r <= #eno#
]]>
</select>
</sqlMap>
@Autowired
private SqlMapClientTemplate ibatis;
보드 매니저에다가 생성해주고
list 고칠거임
public List<BoardDTO> list(Map map) {
List<BoardDTO> list = null;
try{
list = dao.list(map,ibatis);
}catch(Exception e){
e.printStackTrace();
}finally{
}
return list;
}
매니저의 list이고
이제 DAO 고칠거임
public List<BoardDTO> list(Map map, SqlMapClientTemplate ibatis) throws SQLException {
return ibatis.queryForList("board.list", map);//(board.xml의 namespace.id, parameter객체)
}
이런식으로 고침! :D
총 고친 board.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="board">
<typeAlias alias="DTO" type="spring.model.board.BoardDTO" />
<select id="read" resultClass="dto" parameterClass="int">
select num, name, subject, content, count, filename, filesize
from board
where num = #num#
</select>
<update id="create" parameterClass="DTO">
insert into board
(num,name,subject,content,ref,regdate,passwd,ip,filename,filesize)
values
(board_seq.nextval,
#name#,#subject#,#content#,
(select nvl(max(ref),0) + 1 from board),
sysdate,#passwd#,#ip#,#filename#,#filesize#)
</update><!-- 업데이트를 쓰는 이유는 return값이 f/t가 아니기 때문이다. -->
<select id="total" parameterClass="Map" resultClass="int">
SELECT count(*) from board
<dynamic prepend="WHERE">
<isEqual property="col" compareValue="name">
name like '%' | #word# || '%'
</isEqual>
<isEqual property="col" compareValue="subject">
subject like '%' | #subject# || '%'
</isEqual>
<isEqual property="col" compareValue="content">
content like '%' | #content# || '%'
</isEqual>
<isEqual property="col" compareValue="subject_content">
subject like '%' | #word# || '%'
OR
content like '%' | #word# || '%'
</isEqual>
</dynamic>
</select>
<select id="list" parameterClass="Map" resultClass="DTO">
SELECT num, name, subject, regdate,count,filename,indent, r
FROM(
SELECT num, name, subject, regdate,count,filename,indent, rownum r
FROM(
SELECT num, name, subject, regdate,count,filename,indent
FROM board
<dynamic prepend="WHERE">
<isEqual property="col" compareValue="name">
name like '%' | #word# || '%'
</isEqual>
<isEqual property="col" compareValue="subject">
subject like '%' | #subject# || '%'
</isEqual>
<isEqual property="col" compareValue="content">
content like '%' | #content# || '%'
</isEqual>
<isEqual property="col" compareValue="subject_content">
subject like '%' | #word# || '%'
OR
content like '%' | #word# || '%'
</isEqual>
</dynamic>
ORDER BY ref DESC, ansnum
)
)
<![CDATA[
WHERE r >= #sno# and r <= #eno#
]]>
</select>
</sqlMap>
총 고친 boardDAO
package spring.model.board;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import org.springframework.orm.ibatis.SqlMapClientTemplate;
import org.springframework.stereotype.Component;
import spring.utility.board.DBClose;
@Component
public class BoardDAO {
public boolean create(BoardDTO dto, SqlMapClientTemplate ibatis) throws SQLException {
boolean flag = false;
if(ibatis.update("board.create",dto) >0){
flag = true;
}
return flag;
}
public List<BoardDTO> list(Map map, SqlMapClientTemplate ibatis) throws SQLException {
return ibatis.queryForList("board.list", map);//(board.xml의 namespace.id, parameter객체)
}
public int total(Map map, SqlMapClientTemplate ibatis) throws SQLException {
//이렇게 형변환 해줘야 오브젝트 -> 인트형으로 사용 가능!!!
return (Integer) ibatis.queryForObject("board.total", map);
}
public BoardDTO read(int num, SqlMapClientTemplate ibatis) throws SQLException {
return (BoardDTO) ibatis.queryForObject("board.read", num);
}
public void upCount(int num, Connection con) throws SQLException {
PreparedStatement pstmt=null;
StringBuffer sql = new StringBuffer();
sql.append(" UPDATE board ");
sql.append(" SET count = count + 1 ");
sql.append(" WHERE num = ? ");
try {
pstmt = con.prepareStatement(sql.toString());
pstmt.setInt(1, num);
pstmt.executeUpdate();
} finally{
DBClose.close(pstmt);
}
}
public boolean update(BoardDTO dto, Connection con) throws SQLException {
boolean flag = false;
PreparedStatement pstmt = null;
StringBuffer sql = new StringBuffer();
sql.append(" UPDATE board ");
sql.append(" SET name = ?, ");
sql.append(" subject = ?, ");
sql.append(" content = ? ");
if(dto.getFilesize()>0){
sql.append(" , ");
sql.append(" filename = ? , ");
sql.append(" filesize = ? ");
}
sql.append(" WHERE num = ? " );
try{
int i=0;
pstmt = con.prepareStatement(sql.toString());
pstmt.setString(++i, dto.getName());
pstmt.setString(++i, dto.getSubject());
pstmt.setString(++i, dto.getContent());
if(dto.getFilesize()>0){
pstmt.setString(++i, dto.getFilename());
pstmt.setInt(++i, dto.getFilesize());
}
pstmt.setInt(++i, dto.getNum());
int cnt = pstmt.executeUpdate();
if(cnt>0) flag = true;
}finally{
DBClose.close(pstmt);
}
return flag;
}
public boolean passwdCheck(int num, String passwd, Connection con) throws SQLException {
boolean flag = false;
PreparedStatement pstmt = null;
ResultSet rs = null;
StringBuffer sql = new StringBuffer();
sql.append(" SELECT count(*) FROM board ");
sql.append(" WHERE num = ? AND passwd = ? ");
try{
pstmt = con.prepareStatement(sql.toString());
pstmt.setInt(1, num);
pstmt.setString(2, passwd);
rs = pstmt.executeQuery();
if(rs.next()){
int cnt = rs.getInt(1);
if(cnt>0) flag = true;
}
}finally{
DBClose.close(pstmt, rs);
}
return flag;
}
public BoardDTO readReply(int num, Connection con) throws SQLException {
BoardDTO dto = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
StringBuffer sql = new StringBuffer();
sql.append(" SELECT num, ref, indent, ansnum, subject ");
sql.append(" FROM board ");
sql.append(" WHERE num = ? ");
try{
pstmt = con.prepareStatement(sql.toString());
pstmt.setInt(1, num);
rs = pstmt.executeQuery();
if(rs.next()){
dto = new BoardDTO();
dto.setNum(rs.getInt("num"));
dto.setRef(rs.getInt("ref"));
dto.setIndent(rs.getInt("indent"));
dto.setAnsnum(rs.getInt("ansnum"));
dto.setSubject(rs.getString("subject"));
}
}finally{
DBClose.close(pstmt, rs);
}
return dto;
}
public void upAnsnum(int ref, int ansnum, Connection con) throws SQLException {
PreparedStatement pstmt = null;
StringBuffer sql = new StringBuffer();
sql.append(" UPDATE board ");
sql.append(" SET ansnum = ansnum +1 ");
sql.append(" WHERE ref = ? AND ansnum > ? ");
try{
pstmt = con.prepareStatement(sql.toString());
pstmt.setInt(1, ref);
pstmt.setInt(2, ansnum);
pstmt.executeUpdate();
}finally{
DBClose.close(pstmt);
}
}
public boolean replyCreate(BoardDTO dto, Connection con) throws SQLException {
boolean flag = false;
PreparedStatement pstmt = null;
StringBuffer sql = new StringBuffer();
sql.append(" insert into board ");
sql.append(" (num,name,subject,content,ref,indent,ansnum,regdate,passwd,ip,filename,filesize,refnum) ");
sql.append(" values ");
sql.append(" (board_seq.nextval, ");
sql.append(" ?,?,?, ");
sql.append(" ?,?,?, ");
sql.append(" sysdate,?,?,?,?,?) ");
try {
pstmt = con.prepareStatement(sql.toString());
pstmt.setString(1, dto.getName());
pstmt.setString(2, dto.getSubject());
pstmt.setString(3, dto.getContent());
pstmt.setInt(4, dto.getRef());
pstmt.setInt(5, dto.getIndent()+1);
pstmt.setInt(6, dto.getAnsnum()+1);
pstmt.setString(7, dto.getPasswd());
pstmt.setString(8, dto.getIp());
pstmt.setString(9, dto.getFilename());
pstmt.setInt(10, dto.getFilesize());
pstmt.setInt(11, dto.getNum()); //부모의 num
int cnt = pstmt.executeUpdate();
if(cnt>0) flag = true;
} finally{
DBClose.close(pstmt);
}
return flag;
}
public boolean refnumCheck(int num, Connection con) throws SQLException {
boolean flag = false;
PreparedStatement pstmt = null;
ResultSet rs =null;
StringBuffer sql = new StringBuffer();
sql.append(" SELECT count(*) ");
sql.append(" FROM board ");
sql.append(" WHERE refnum = ? ");
try{
pstmt = con.prepareStatement(sql.toString());
pstmt.setInt(1, num);
rs = pstmt.executeQuery();
if(rs.next()){
int cnt = rs.getInt(1);
if(cnt>0) flag = true;
}
} finally{
DBClose.close(con, pstmt);
}
return flag;
}
public boolean delete(int num, Connection con) throws SQLException {
boolean flag = false;
PreparedStatement pstmt = null;
StringBuffer sql = new StringBuffer();
sql.append(" DELETE FROM board ");
sql.append(" WHERE num = ? ");
try{
pstmt = con.prepareStatement(sql.toString());
pstmt.setInt(1, num);
int cnt = pstmt.executeUpdate();
if(cnt>0)flag = true;
}finally{
DBClose.close(pstmt);
}
return flag;
}
}
총 고친 boardMGr
package spring.model.board;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.ibatis.SqlMapClientTemplate;
import org.springframework.stereotype.Service;
import spring.utility.board.DBClose;
import spring.utility.board.DBOpen;
@Service
public class BoardMgr {
@Autowired
private BoardDAO dao;
@Autowired
private SqlMapClientTemplate ibatis;
public boolean create(BoardDTO dto) {
boolean flag = false;
try{
flag = dao.create(dto,ibatis);
}catch(Exception e){
e.printStackTrace();
}finally{
}
return flag;
}
public List<BoardDTO> list(Map map) {
List<BoardDTO> list = null;
try{
list = dao.list(map,ibatis);
}catch(Exception e){
e.printStackTrace();
}finally{
}
return list;
}
public int total(Map map) {
int total = 0;
try{
total = dao.total(map,ibatis);
}catch(Exception e){
e.printStackTrace();
}finally{
}
return total;
}
public BoardDTO read(int num) {
BoardDTO dto = null;
try{
dto = dao.read(num,ibatis);
}catch(Exception e){
e.printStackTrace();
}finally{
}
return dto;
}
public void upCount(int num) {
Connection con = DBOpen.getConnection();
try{
dao.upCount(num,con);
}catch(Exception e){
e.printStackTrace();
}finally{
DBClose.close(con);
}
}
public boolean update(BoardDTO dto) {
boolean flag = false;
Connection con = DBOpen.getConnection();
try{
flag = dao.update(dto,con);
}catch(Exception e){
e.printStackTrace();
}finally{
DBClose.close(con);
}
return flag;
}
public boolean passwdCheck(int num, String passwd) {
boolean flag = false;
Connection con = DBOpen.getConnection();
try{
flag = dao.passwdCheck(num,passwd,con);
}catch(Exception e){
e.printStackTrace();
}finally{
DBClose.close(con);
}
return flag;
}
public BoardDTO readReply(int num) {
BoardDTO dto = null;
Connection con = DBOpen.getConnection();
try{
dto = dao.readReply(num,con);
}catch(Exception e){
e.printStackTrace();
}finally{
DBClose.close(con);
}
return dto;
}
public boolean reply(BoardDTO dto) {
boolean flag = false;
Connection con = DBOpen.getConnection();
try{
con.setAutoCommit(false);
//ansnum 증가(update)
dao.upAnsnum(dto.getRef(),dto.getAnsnum(),con);
//답변을 생성(create)
flag = dao.replyCreate(dto,con);
con.commit(); //db적용
}catch(Exception e){
try {
con.rollback();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
} finally{
try {
con.setAutoCommit(true);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
DBClose.close(con);
}
return flag;
}
public boolean refnumCheck(int num) {
boolean flag = false;
Connection con = DBOpen.getConnection();
try{
flag = dao.refnumCheck(num,con);
}catch(Exception e){
e.printStackTrace();
}finally{
DBClose.close(con);
}
return flag;
}
public boolean delete(int num) {
boolean flag = false;
Connection con = DBOpen.getConnection();
try{
flag = dao.delete(num,con);
}catch(Exception e){
e.printStackTrace();
}finally{
DBClose.close(con);
}
return flag;
}
}
다 아직 안했습니다
5. 수업
진도:
hw:
6. 할것
국내자격증
정보처리기사, 정보처리산업기사 - 한국산업인력공단
컴퓨터를 효과적으로 활용하기 위해서 하드웨어와 정교한 소프트웨어가 필요하다. 이에 따라 우수한 프로그램을 개발하여 업무의 효율성을 높이고, 궁극적으로 국가발전에 이바지하기 위해서 컴퓨터에 관한 전문적인 지식과 기술을 갖춘 사람을 양성할 목적으로 제정된다. 컴퓨터 시스템을 통한 프로그램 개발 및 전산시스템을 분석하고, 전산 업무의 타당성검토, 정보시스템분석, 시스템설계 등 정보처리 전반에 관한 업무수행이 가능하다.
사무자동화산업기사 - 한국산업인력공단
일반 사무환경에서 사무작업을 하고 있는 실무자로 하여금 업무상 발생하는 데이터의 안전성을 확보하고, 작업효율을 증진시킴으로써 궁극적으로 인간 중심의 정보문화 정착에 기여하며 보다 효율적으로 업무에 필요한 정보를 이용하게 하기 위하여 필요한 자격증이다. 정보화시대의 산업경영실무에서 필요로 하는 사무처리용 컴퓨터 및 컴퓨터통신의 운용을 중심으로 한 모든 사무자동화 실무, 즉 응용프로그램, 사무자동화기기 및 뉴미디어 터미널 등의 사무정보기기를 활용하여 사무능률을 극대화할 수 있도록 종합적으로 유지, 관리하는 직무를 수행할 수 있다.
컴퓨터활용능력 1급 - 대한상공회의소
누구나 컴퓨터를 사용할 줄 알고 접하는 정보화 시대에 개개인의 컴퓨터 활용능력을 객관적으로 검증하기 위하여 도입하였다. 스프레드시트, 데이터베이스 프로그램 등 각종 응용 프로그램을 이용하여 실무에 적용할 수 있게 한다.
PCT(Personal Computer Efficiency Test) - 한국정보산업연합회
개개인의 PC활용 능력을 종합적이고 객관적으로 평가하여 실제 PC활용도를 측정하는 실무 중심의 시험으로서 민간자격 국가공인 사업의 일환으로 도입 실시되는 국가공인 민간자격증이다. 검증받은 실력을 바탕으로 개인 업무, 회사 내 업무에 활용한다.
인터넷정보관리사 전문가,1,2급 - 한국정보통신인력개발센터
인터넷 및 관련기술에 대한 이해와 인터넷을 활용한 정보의 검색, 가공 및 활용능력을 검정하는 자격이다. 인터넷을 활용하여 정보를 수집, 가공, 처리, 관리하며 부서의 정보화를 담당한다.
국외자격증
MCP(Microsoft Certified Professional) - Microsoft
마이크로소프트 데스크톱 제품 사용자들을 위해 설치, 구성 및 기술지원을 제공할 수 있는 자격을 부여합니다. MCP는 MCSE, MCSD, MCDBA등의 시작점이라고 할 수 있습니다. 기업이나 조직에서 해당업무에 적합한 인력을 채용하고 활용하거나 아웃소싱을 통한 기술 지원 서비스를 제공 받을 경우, 그리고 기업 스스로의 기술력을 측정하기 위한 경우 가장 적합한 기술 인증이다.
MCSE(Microsoft Certified Systems Engineer) - Microsoft
비즈니스 요구 사항을 분석하고 Microsoft Windows 2000 플랫폼과 Microsoft 서버 소프트웨어를 기반으로 비즈니스 솔루션용 인프라를 설계하고 구현하는 전문가들을 위한 프리미어 인증이다. 구현 업무에는 네트워크 시스템 설치, 구성 및 문제 해결이 포함된다. MCSE 인증은 업계에서 가장 널리 인정받는 기술 인증 중 하나이다. 프리미어 MCSE 인증을 취득하면 최첨단 Microsoft Windows 운영 체제와 Microsoft 서버 제품을 성공적으로 설계, 구현 및 관리할 수 있는 기술이 있음을 입증할 수 있다. 시스템 엔지니어, 네트워크 엔지니어, 시스템 분석가, 네트워크 분석가, 기술 컨설턴트, 시스템 분석가, 네트워크 분석가, 시스템 엔지니어, 기술지원 엔지니어들에게 적합한 인증이다.
CSD(Microsoft Certified Solution Developer) - Microsoft
Microsoft 개발 도구, 기술, 플랫폼 및 Microsoft Windows DNA 아키텍처를 사용하여 첨단 비즈니스 솔루션을 설계 및 개발하는 전문가들을 위한 프리미어 인증이다. MCSD가 개발할 수 있는 응용 프로그램의 종류에는 데스크톱 응용 프로그램 및 다중 사용자, 웹 기반, N 계층, 트랜잭션 기반 응용 프로그램 등이 있다. 이 인증은 비즈니스 요구 사항 분석에서 솔루션 유지에 이르기까지 다양한 작업과 관련이 있다. MCSD 트랙에는 Microsoft SQL Server 및 Microsoft Visual Studio 같은 Microsoft의 응용 프로그램 서버와 제품을 사용하여 웹 기반의 분산형 상용 솔루션을 구축하는 능력을 테스트하는 인증 시험이 포함된다. 소프트웨어 엔지니어, 응용 프로그램 분석가, 소프트웨어 응용 프로그램 개발자, 소프트웨어 개발자, 기술 컨설턴트, 소프트웨어 어플리케이션 엔지니어들에게 적합하다.
MCDBA(Microsoft Certified DataBase Administrator) - Microsoft
Microsoft SQL Server™ 데이터베이스를 구현 및 관리하는 전문가를 위한 프리미어 인증이다. MCP제도는 마이크로 소프트의 현 제품 및 기술에 관한 역량을 대내외적으로 증명해 주는 프로그램으로, 기업이나 조직내에 해당업무에 가장 적합한 인적 자원을 채용하고 활용하거나 외부의 협력업체를 통해 컴퓨터서비스를 제공받는 경우, 또는 기업 자체의 기술 조직을 구축하는 경우에 최고의 기술력을 인증해주는 자격으로 마이크로소프트 제품과 기술에 대한 여러분의 사용 능력을 입증할 수 있는 가장 좋은 기준이다.
OCP(Oracle Certified Professional) - Oracle
오라클 공인 전문가 제도는 오라클 제품 사용자의 관련 업무별 전문 기술지식 정도를 측정하여 대내외적으로 증명해 주며, 오라클의 제품과 최신 기술을 활용하여 최적의 솔루션을 설계, 개발, 응용하는데 필요한 인력의 역량을 인증해 주는 프로그램이다. 오라클에서는 OCP(오라클 공인 전문가 제도)를 운영하여 사용자들에게 보다 합리적인 기준을 마련한다. 전 세계적으로 Oracle 전문가로 공인되며, 한국오라클 교육 협력사로 등록시 자격 요건이 되며, 한국오라클 교육센터의 재택 강사 선정시 필수 자격이며, 오라클 공인 전문가를 업계의 필요한 부분에서 일할 수 있다.
SCJP(Sun Certified Java Programmer) - Sun Microsystems
SUN의 Java 프로그래머 자격증시험으로 Java 언어의 기본요소인 Keywords, Literal, Comments, Operators등에 대한 정확한 이해와 사용법 및 Java를 이용한 네트워크 프로그래밍, 애플리케이션 디자인, 그래픽 툴제작, GUI 디자인과 개발 및 관련툴과 JDBC와 OOP 개념 이해 정도의 테스트를 통해 Java 기술 분야의 능력을 검증해 준다. 자격증 취득 후 SI업체의 소프트웨어 개발자나 다양한 종류의 Java 프로젝트에 참여할 수 있고, 또한 국내 대기업들의 경우 Java 자격증 취득자를 확보하려는 경향이 있으며 최근에는 웹 관련 프로그램 개발부분에서 SUN의 Java 프로그래머 자격증 보유자의 수요가 늘고 있는 실정이라 그 전망이 밝아 인력수요가 증가할 전망이다.
SCJD(Sun Certified Java Developer) - Sun Microsystems
SUN공인 Java개발자 자격인증프로그램SCJD(Sun Certified Java Developer)는 Java를 개발하고 ,Java의 신기술을 리드해 가는 sun에서 Java실력을 검증하고 직접 인증해주며 Java전문가로써 인정받을 수 있는 최고의 전문자격이다. SCJD는 다양한 형태의 플랫폼에서 작동할 수 있도록 Java를 이용하며, Java프로그램 한가지로 일반 PC나 다양한 네트워크 환경에서 동작하는 애플리케이션작성의 업무를 한다. 자격증 취득 후 SI업체의 소프트웨어 개발자나 다양한 종류의 Java프로젝트에 참여할 수 있고, 국내 대기업들의 경우 Java 자격증 취득자를 경쟁적으로 확보하려는 경향이 있으며 최근에는 웹 관련 프로그램 개발부분에서 Java자격증 보유자의 수요가 늘고 있어, 전문가의 수요도 증가할 전망이다.
SCNA(Sun Certified Network Administrator) - Sun Microsystems
SUN에서 네트워크 관리분야의 능력을 검증해 주는 최고의 자격으로 SCNA 자격인증 프로그램을 제공한다. 자격취득자는 네트워크 관리분야의 기술적인 능력을 사용할 수 있다. 시스템 네트웍을 최적으로 관리하며 시스템 관리자나 Web server관리자 업무를 수행한다. 자격증 취득시 네트워크 관리분야의 기술적인 능력에 대한 실질적인 평가를 받으며, 대규모로 네트워크를 운영하는 기업체 등에서 인터넷과 인트라넷 관리의 중요성이 커지기 때문에 자격취득자의 인력수요는 증가할 것이다.
CCDA(Cisco Certified Design Associate) - Cisco Systems
CCDA는 컴퓨터 네트워킹 전문가 양성을 목적으로 시행된 시스코의 기술 공인 프로그램인 CCC(Cisco Career Certification)의 하나로 네트워크 설계 관련 능력을 검증하는 자격증이다. CCC는 크게 Network Design과 Network Support의 2가지 트랙으로 구분되며 기술력에 따라 Associate, Professional, Expert로 단계가 나뉘어져 있다. CCDA는 이 중에서 Net - work Design 트랙의 Associate 단계에 해당된다. 2000년 5월 발표된 자료에 의하면 같은 Associate 단계인 CCNA가 1,000여명에 이르는데 비해 CCDA 취득자는 100여 명 미만이었다. 그 이유는 네트워크 구축에 대한 고객의 요구사항을 파악하고 충족시킬 수 있는 능력을 평가하기 위해 소형 네트워크의 설치, 구성, 진단 및 운영에 관한 기본적인 능력뿐 아니라, 네트워크 성능 및 보안 등에 관련된 지식까지 요구하기 때문이다. CCDA는 노드 100개 이하의 소형 네트워크를 가진 사업체 및 기관을 위한 LAN, WAN 및 다이얼 접속 서비스를 포함하는 라우팅형 및 스위칭형 네트워크 설계 능력을 평가한다. 또한 고객의 요구사항에 맞는 네트워크의 구축을 위해 네트워크 관련 장비의 특성을 잘 이해하고 이에 대한 유기적인 결합 능력도 필요하다. 네트워크 통합(NI) 업체에서는 CCDA 기술력을 지닌 인력을 많이 필요로 하고 있다. 그 밖에, 시스코 장비를 취급하는 네트워크 장비 업체, 외국계 IT 기업이나 시스코 네트워크 장비 등을 사용하는 국내 기업에서 네트워크 전문가로 활동할 수 있다. 여느 IT 관련 업종보다 보수가 높은 편이다. 가장 큰 이유는 희소성 때문이다. 현재 네트워크 전문가라 할 만한 인력이 그리 많지 않은 반면, 각 업체에서의 수요는 기하급수적으로 늘고있는 추세다. 제대로 일을 할 만큼 경력이 쌓이기까지 상당한 기간이 소요되는데 다 관련 참고 도서나 정보가 충분치 않은 것도 몸값을 높이는 주된 요인이다. 인터넷의 확산은 앞으로 더욱 커다란 물결을 형성할 것이다. 결국 그에 따른 인력 수요도 커지게 마련, 따라서 네트워크에 관심이 있고 자질도 충분하다면, 전문 직종에 종사하는 특권을 누릴 수 있는 분야라 할 수 있다.
CCDP(Cisco Certified Design Professional) - Cisco Systems
CCDP는 컴퓨터 네트워킹 전문가 양성을 목적으로 시행된 시스코의 기술 공인 프로그램인 CCC(Cisco Career Certification)의 하나로 네트워크의 설계 및 분석 관련 능력을 검증하는 자격증이다. CCC는 크게 Network Design과 Network Support의 2가지 트랙으로 구분되며 기술력에 따라 Associate, Professional, Expert로 단계가 나뉘어져 있다. CCDP는 이 중에서 Net - work Design 트랙의 Professional 단계에 해당된다. CCDP는 반드시 CCNA와 CCDA를 취득한 사람에 한하여 응시할 수 있는 기회를 제공하며, CCDA보다 더 복잡한 네트워크 문제를 해결할 수 있는 실무 능력을 요구한다. 구체적으로 노드 수 100~500개 이상의 중형 네트워크를 가진 사업체 및 기관을 위한 LAN, WAN 및 다이얼 접속 서비스를 포함하는 라우팅형 및 스위칭형 네트워크 설계 능력을 평가한다. CCDP 자격증을 취득하면 외국계 IT 기업 취업에 유리하며, 네트워크 설계 분야에서 고급 전문 지식을 보유했음을 인정받게 된다. 또한 다중 프로토콜 기반의 인터네트워크를 디자인하거나 네트워크 디자인 프로젝트의 분석 작업을 수행하는 인터네트워크 디자이너나 시스템 디자이너로 활동할 수 있다. 그 밖에 시스코 장비에 대한 여러가지 혜택을 받기 위해 시스코사와 파트너십을 맺을 경우, CCDP 자격을 보유한 기술력이 필수 조건이 되므로 CCDP 자격증의 가치는 매우 높게 평가되고 있다.
CCNA(Cisco Certified Network Associate) - Cisco Systems
CCNA는 컴퓨터 네트워킹 전문가 양성을 목적으로 시행된 시스코의 기술 공인 프로그램 인 CCC(Cisco Career Certification)의 하나로 네트워크 설치 및 운영 능력을 공인하 는 자격증이다. CCC는 크게 Network Design과 Network Support의 2가지 트랙으로 구분되며 기술력에 따라 Associate, Professional, Expert로 단계가 나누어져 있다. CCNA는 이 중에서 Net - work Support 트랙의 Associate 단계에 해당된다. CCNA 인증은 시스코사에서 주관하므로 시스코 장비에 대한 지식을 묻기도 한다. 그러나 시스코 기술 인증 프로그램인 CCC의 CCNP, CCDP, CCIE 같은 상위 자격을 취득하기 전의 기본 인증이기 때문에 네트워크를 구성하는 전반적 구조나 구성 요소에 대한 질문들이 주를 이룬다. 즉, 장비에 국한되지 않고 인터넷을 구성하는 요소들에 대한 기본 지식을 습득할 수 있다. 개념 위주의 문제가 많으며, 노드 100개 이하의 소형 네트워크에 대한 LAN, WAN 및 다이얼 액세스 서비스를 설치, 구성 및 운영할 수 있는 능력을 평가한다. 시스코 네트워크 장비를 사용하는 국내 및 외국계 IT 기업에서 네트워크 전문가로 활동할 수 있다.
CCNP(Cisco Certified Network Professional) - Cisco Systems
CCNP는 컴퓨터 네트워킹 전문가 양성을 목적으로 시행된 시스코의 기술 공인 프로그램인 CCC(Cisco Career Certification)의 하나로 라우터와 스위치를 사용하여 네트워크를 구성하는 능력과 네트워크 운영상의 여러 가지 트러블 슈팅(trouble shooting) 능력을 평가하는 자격증이다. CCC는 크게 Network Design과 Network Support의 2가지 트랙으로 구분되며 기술력에 따라 Associate, Professional, Expert로 단계가 나누어져 있다. CCNP는 이 중에서 Network Support 트랙의 Professional 단계에 해당된다. CCNP는 반드시 CCNA를 취득한 사람에 한하여 응시할 수 있는 기회를 제공하며, CCNA보다 더 복잡한 네트워크 문제를 해결할 수 있는 실무 능력을 요구한다. 구체적으로 노드 수 100~500개 이상의 중형 네트워크에 대한 LAN, WAN 및 다이얼 액세스 서비스를 설치, 구성 및 운영할 수 있는 능력을 평가한다. 외국계 IT 기업이나 시스코 네트워크 장비 등을 사용하는 국내 기업에서 네트워크 전문가로 활동할 수 있다. 국내 기업에서 시스코와 Reseller 계약을 체결하기 위해서는, CCNP의 자격을 보유한 기술력이 필수 조건이 되기 때문이다. 또한 자격 취득의 여부가 대외적으로 그 회사의 기술력을 나타내는 척도로도 인정되므로 CCNP 자격 취득자의 전망은 매우 밝다고 하겠다.
CCIE(Cisco Certified Internetwork Expert) - Cisco Systems
CCIE 프로그램은 인터네트워킹 업계의 고도로 숙련된 기술 엔지니어를 기업들이 알아볼 수 있도록 하기 위해 시스코가 1993년도에 처음 도입한 전문가 레벨 인증이다. 오늘날의 CCIE (Cisco Certified Internetwork Expert: 시스코 인증 인터네트워크 전문가)프로그램은 인터네트워킹 숙련도를 측정할 수 있는 전문가적 벤치마크를 설정해 놓고 있다. 지원자는 5종류의 CCIE 인증 트랙 중 하나를 선정하여 준비 할 수 있으며, 자격 시험(필기 시험) 및 2일 간의 랩 테스트(실기 시험)을 통과함으로써 획득할 수 있다. CCIE는 CCNP나 CCDP처럼 선수자격을 요구하지 않는다. 그러나 CCNA와 CCNP 과정은 CCIE를 준비하는 과정에서 반드시 필요한 기본지식을 제공한다. 즉, CCIE에 응시하기 위해서는 CCNA, CCNP / CCDA, CCDP의 지식/기술을 충분히 습득/훈련하는 것이 요구된다. 특히, 무경험자가 합격한 사례가 없어 보통 네트워크 분야에서 2년 이상의 경력자가 추천된다. CCIE 시험은 연중가능하며, 영문으로 진행되며 PC를 통해 치러진다. CCIE는 Routing and Switching, ISP Dail, Wan Switching, SNA-IP, Design Track으로 구분된다. CCIE 자격증소지자들이 대부분 취득한 것은 Routing and Switching Track으로 이 분야에서만 4,500명이 넘는다. (2000. 8. 31기준) 전세계적으로 CCIE자격증 소지자는 4,791명으로 그 중 한국인은 32명이다. CCIE 자격증을 취득한 사람은 네트워크에 관련하여 최적화된 환경과 애플리케이션 기반 솔루션을 제공할 수 있는 기술력을 보유하게 된다. 그러므로 시스코 제품뿐만 아니라, LAN, WAN, 인터넷 등 모든 네트워크에 대한 전반적인 지식을 갖춘 최고 수준의 네트워크 전문가임을 인증받게 된다. 국내에 CCIE 자격을 보유한 사람은 약 50명이다. 이들은 시스코나 시스코 협력업체 또는 시스코의 제품을 사용하고 있는 네트워크 전문업체에서 컨설턴트로 일하거나, 네트워크 관리자로서 개인 사무실을 독립적으로 운영할 수 있을 만큼의 영향력을 보이고 있다.
MCSE (Microsoft Certified Systems Engineer)
MS Windowa NT 및 MS BackOffice 제품군을 사용하여 시스템의 효율적인 계획, 관리, 유지 및 지원 등에 대한 테스트를 하는 시험이다. 비즈니스 요구사항과 디자인을 분석하고 마이크로소프트 윈도우 2000 서버 소프트웨어를 기반으로 한 비즈니스 솔루션에 대한 인프라스트럭쳐를 구현한다. 시스템 구현, 즉 설치, 구성과 네트워크 시스템 문제 해결 등을 수행하는 전문가에게 있어 최고의 인증 자격증이다.
MCSD(Microsoft Certified Solution Developer)
MCSD(Microsoft Certified Solution Developer)는 한마디로 프로그래밍 자격증이다. 컴퓨터 응용 프로그램 시스템을 분석, 디자인, 개발, 테스트, 구현 및 유지 관리함으로써 마이크로소프트 개발 도구, 기술 및 플랫폼을 사용하여 기능적인 목적의 업무 디자인을 충족시키고 사용자 정의 솔루션을 개발하는 업무를 한다. MCSD가 되려면 마이크로소프트 오피스 및 BackOffice 제품을 포함, 마이크로소프트의 각종 개발 도구 및 기술을 사용하여 사용자의 요구에 맞는 업무용 솔루션을 디자인 및 개발할 수 있어야 한다. 또한 MCSD가 되면, 해당 프로그램들을 테스트할 수 있는 자격이 부여된다.
OCA (Oracle Certified Associate)
Oracle9i OCA(Oracle Certified Associate) Track은 신입 level의 사원이 Oracle DBA 역할을 제대로 수행하기 위해 필요한 기본적인 지식을 갖추고 있다는 것을 입증할 수 있는 자격증으로, 2개의 테스트로 이루어져 있다. OCA Track은 OCP를 꿈꾸는 사람들이 첫 번째 기회를 잡을 수 있도록 도와준다. OCA는 IT 분야에서 높은 평가를 받고 있는 OCP 및 Certified Master DBA 자격증을 취득할 수 있는 기본 토대라고 할 수 있다.
SCJP (Sun Certified Java Programmer)
SCJP(Sun Certified Java Programmer)는 썬마이크로시스템즈의 Java 프로그래머 자격증 시험으로, Java 언어의 기본 요소인 keywords, literal, comments, operators등에 대한 정확한 이해와 사용법 및 Java를 이용한 네트워크 프로그래밍, 애플리케이션 디자인, 그래픽 툴 제작, GUI 디자인과 개발 및 관련 툴과 JDBC와 OOP 개념 이해 정도를 테스트를 하여 Java 기술분야의 능력을 검증한다.
SCCD (Sun Certified Web Component Developer for J2EE)
SCCD(Sun Certified Web Component Developer for J2EE)는 Web-tier상에서 Servlet과 JSP API를 이용한 프로그래밍 능력을 검증해 주는 자격인증 프로그램으로, 인터넷 시대를 이끌어갈 수 있는 기술 경쟁력을 검증한다
리눅스마스터
기사 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
아오
영 안되면 기능사라도
'Programming' 카테고리의 다른 글
160609: 60회차 (0) | 2016.06.09 |
---|---|
160608: 59회차 (0) | 2016.06.08 |
160603: 57회차 (0) | 2016.06.03 |
160602: 56회차 (0) | 2016.06.02 |
160601: 55회차 (0) | 2016.06.01 |