본문 바로가기

Programming/[JSP]

[JSTL] SQL 태그

 

 

DataSource 를 이용해서 SQL을 처리하는 sql 태그는 다음과 같은 것들이 있다.

기능 태그 prefix
DataSource설정 SetDataSource sql
SQL query (dateParam, param) , update (dateParam, param) , transaction

 

 
sql 태그를 사용하기 위해서 페이지 상단에 다음과 같이 선언되어야 된다.
 
<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql"%>
 
 
 
1. <sql:setDataSource/>
DataSource 를 지정하는 방식은 <sql:setDataSource/> 태그의 사용법은 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
Syntax
 
<sql:setDataSource
 
        {dataSource="dataSource" |
 
            url="jdbcUrl"
 
            [driver="driverClassName"]
 
            [user="userName"]
 
            [password="password"]}
 
        [var="varName"]
 
        [scope="{page|request|session|application}"]/>


cs
오라클에서 사용을 한다면 다음과 같이 DataSource 를 설정할 수 있다.
 
1
2
3
4
5
6
7
8
9
10
11
12
13
<sql:setDataSource
 
            url="jdbc:oracle:thin:@localhost:1521:orcl"
 
            driver="oracle.jdbc.driver.OracleDriver"
 
            user="C##XERXES"
 
            password="****"
 
        var="okjspDS"
 
        scope="application" />
cs
 
 
이미 컨텍스트에 JNDI 설정이 되어있다면 다음과 같이 바로 불러서 사용하거나 <sql:query/> 에서 바로 사용할 수 있다.
 
기존의 dataSource 를 불러와 사용하는 경우
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<sql:setDataSource
 
        dataSource="jdbc/sbjang"
 
        var="okjspDS"
 
        scope="application" />
 
 
 
<sql:query/> 에서 바로 사용하는 경우
 
<sql:query var="emp"
 
        dataSource="jdbc/myora81">
cs
2. <sql:query/>
java 와는 달리 sql 문장을 문자열로 연결하지 않아도 가독성을 높여서 작성할 수 있다. <sql:query/>태그의 형식은 다음과 같다.
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
Syntax 1: body 없는 경우
 
<sql:query sql="sqlQuery"
 
        var="varName" [scope="{page|request|session|application}"]
 
        [dataSource="dataSource"]
 
        [maxRows="maxRows"]
 
        [startRow="startRow"]/>
 
 
 
Syntax 2: body 에 쿼리의 파라메터가 있는 경우
 
<sql:query sql="sqlQuery"
 
        var="varName" [scope="{page|request|session|application}"]
 
        [dataSource="dataSource"]
 
        [maxRows="maxRows"]
 
        [startRow="startRow"]>
 
    <sql:param> 액션들
 
</sql:query>
 
 
 
Syntax 3: 쿼리와 파라메터들이 body 에 있는 경우
 
<sql:query var="varName"
 
        [scope="{page|request|session|application}"]
 
        [dataSource="dataSource"]
 
        [maxRows="maxRows"]
 
        [startRow="startRow"]>
 
    sqlQuery
 
    선택적 <sql:param> 액션들
 
</sql:query>
cs
파라메터에는 두 가지가 있는데, 날짜 형식의 <sql:dateParam/> 와 일반적인 <sql:param/>태그가 있으며 형식은 다음과 같다.
3. <sql:dateParam/> , <sql:param/>
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Syntax
 
<sql:dateParam value="value" type="[timestamp|time|date]"/>
 
 
 
Syntax 1: value 속성에 파라메터 값이 지정된 경우
 
<sql:param value="value"/>
 
 
 
Syntax 2: body 내용에 파라메터 값이 지정된 경우
 
<sql:param>
 
    parameter value
 
</sql:param>
cs

<sql:param/> 은 java.sql.PreparedStatement.setString() 의 역할을 한다. 바인드변수의 순서에 따라서 써주면 된다.<sql:dateParam/>은 java.sql.PreparedStatement.setTimestamp() 역할을 하고,
 

 

 
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
<%@ page pageEncoding="MS949" %>
 
<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>
 
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
 
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 
<fmt:setLocale value="ko" />
 
<sql:query var="emp"
 
        dataSource="jdbc/myora81">
 
SELECT  EMPNO AS 사원번호, ENAME AS 이름,
 
            SAL AS 월급여, HIREDATE AS 입사일
 
    FROM EMP
 
 
 
</sql:query>
 
 
 
<table border="1">
 
  <tr>
 
<%-- 필드의 정보를 출력한다.            --%>
 
  <c:forEach var="columnName" items="${emp.columnNames}">
 
    <th><c:out value="${columnName}"/></th>
 
  </c:forEach>
 
 
 
<%-- 데이터를 한 줄씩 출력한다.         --%>
 
  <c:forEach var="row" items="${emp.rowsByIndex}">
 
    <tr>
 
<%-- 필드의 길이만큼 반복한다.          --%>
 
      <c:forEach var="column" items="${row}" varStatus="i">
 
        <c:choose>
 
          <c:when test="${i.index==3}">
 
      <td><fmt:formatDate value="${column}" pattern="yyyy/MM/dd"/></td>
 
          </c:when>
 
          <c:otherwise>
 
      <td><c:out value="${column}"/></td>
 
          </c:otherwise>
 
        </c:choose>
 
      </c:forEach>
 
  </c:forEach>
 
</table>
 
<hr>
 
<table border="1">
 
  <c:forEach var="row" items="${emp.rows}">
 
  <tr>
 
    <td>번호: <c:out value="${row['사원번호']}"/></td>
 
    <td>이름: <c:out value="${row['이름']}"/></td>
 
  </tr>
 
  </c:forEach>
 
</table>
cs
dataSource="jdbc/myora81" 의 JNDI는 7장에서 설명한 것처럼 컨텍스트에 설정된 DataSource 명이다.
 
SQL문은 보기 좋게 정렬을 해도 문자열로 덧붙일 필요가 없다. body 에 있는 sql문을 실행한 결과는 emp 라는 변수에 담겨서 이후에 사용이 된다. 이 변수는 ResultSet 과 같은데, JSTL에서 확장한 ResultSet 이고, javax.servlet.jsp.jstl.sql public interface Result 클래스로 내부적으로 정의된다. 지원하는 메소드는 다음과 같다.
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
javax.servlet.jsp.jstl.sql
 
public interface Result
 
public java.util.SortedMap[] getRows()
 
public Object[][] getRowsByIndex()
 
public String[] getColumnNames()
 
public int getRowCount()
 
public boolean isLimitedByMaxRows()
cs
위와 같은 메소드들이 내부적으로 정의되어있기 때문에 각각의 getter 메소드들을 사용해서 변수 emp를 활용할 수 있다.
 
<c:forEach/> 의 items 에 있는 ${emp.columnNames}는 getColumnNames() 메소드를 불렀다는 것을 알 수 있다. 이전의 7장에서 ResultSetMetaData 를 활용해서 뽑아낸 정보와 같은 효과를 볼 수 있다.
 
테이블 내용을 반환하는 ${emp.rowsByIndex} 도 유념할 만하다. 한 행을 row라는 변수에 넣은 뒤에 다음의 <c:forEach/> 에서 이 row변수의 컬럼별로 내용을 출력한다.
 
column 이라는 변수에 넣은 뒤에 column의 index가 3일 경우 날짜형식을 출력하기 위해서 <fmt:formatDate/> 태그를 사용했고, 그 외의 경우는 바로 출력하게 했다.
 
다음 <c:forEach/> 에서는 결과를 SortedMap 배열에 넣은 뒤에 한 줄씩 빼서 컬럼이름으로 빼내는 방식이다.
 
 
 
4. <sql:update/>
java.sql.Statement.executeUpdate() 메소드에 해당하는 <sql:update/> 태그의 형식은 다음과 같다.
 
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
Syntax 1: body 없는 경우
 
<sql:update sql="sqlUpdate"
 
        [dataSource="dataSource"]
 
        [var="varName"] [scope="{page|request|session|application}"]/>
 
 
 
Syntax 2: update 파라메터가 body에 있는 경우
 
<sql:update sql="sqlUpdate"
 
        [dataSource="dataSource"]
 
        [var="varName"] [scope="{page|request|session|application}"]>
 
    <sql:param> 액션들
 
</sql:update>
 
 
 
Syntax 3: update 문과 선택적 update 파라메터가 body에 있는 경우
 
<sql:update [dataSource="dataSource"]
 
        [var="varName"] [scope="{page|request|session|application}"]>
 
    sqlUpdate
 
    선택적 <sql:param> 액션들
 
</sql:update>
cs
형식과 동작은 <sql:query/> 태그와 동일하다. 다른 점은 executeUpdate() 메소드를 수행하기 때문에 DB에 변경을 가할 수 있다는 것이다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
<sql:query var="books" 
        sql="select * from PUBLIC.books where id = ?" >
        <sql:param value="${bookId}" />
</sql:query>
 
<c:forEach var="bookRow" begin="0" items="${books.rows}">            
        <sql:update var="books" sql="update PUBLIC.books set
              inventory = inventory - ? where id = ?" >
              <sql:param value="${item.quantity}" />
              <sql:param value="${bookId}" />
        </sql:update>
      </c:forEach>
    </c:forEach>
cs

 

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
<c:forEach var="bookRow" begin="0"
      items="${books.rowsByIndex}"
  <jsp:useBean id="bid"  type="java.lang.String" />
  <jsp:useBean id="bookRow" type="java.lang.Object[]" />
  <jsp:useBean id="addedBook" class="database.BookDetails"
    scope="page" >
    <jsp:setProperty name="addedBook" property="bookId"
      value="${bookRow[0]}" />
    <jsp:setProperty name="addedBook" property="surname"
      value="${bookRow[1]}" />
    <jsp:setProperty name="addedBook" property="firstName"
      value="${bookRow[2]}" />
    <jsp:setProperty name="addedBook" property="title"
      value="${bookRow[3]}" />
    <jsp:setProperty name="addedBook" property="price"
      value="${bookRow[4])}" />
    <jsp:setProperty name="addedBook" property="year"
      value="${bookRow[6]}" />
    <jsp:setProperty name="addedBook" 
      property="description" 
      value="${bookRow[7]}" />
    <jsp:setProperty name="addedBook" property="inventory"
      value="${bookRow[8]}" />
  </jsp:useBean>
  <% cart.add(bid, addedBook); %>
  ...
</c:forEach
cs
5. <sql:transaction/>
트랜잭션을 구현하는 <sql:transaction/> 태그의 형식은 다음과 같다.
 

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 
Syntax
 
<sql:transaction [dataSource="dataSource"]
 
        [isolation=isolationLevel]>
 
    <sql:query> 과 <sql:update> 문들
 
</sql:transaction>
 
 
 
isolationLevel ::= "read_committed"
 
                | "read_uncommitted"
 
                | "repeatable_read"
 
                | "serializable"

cs

격리 수준(isolationLevel)은 java.sql.Connection 의 setTransactionIsolation() 메소드를 사용한다.