リクエストパラメータを使ったSQL文
<body> <p>検索キーワードを入力してください</p> <form action="search" method="post"> <input type="text" name="keyword"> <input type="submit" value="検索"> </form> </body>
@WebServlet(urlPatterns={"/chapter14/search"}) public class Search extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter pw = resp.getWriter(); Page.header(pw); try { InitialContext ic=new InitialContext(); DataSource ds=(DataSource)ic.lookup("java:/comp/env/jdbc/book"); Connection con=ds.getConnection(); // リクエストパラメータの取得 String keyword = req.getParameter("keyword"); // SQL文の指定 // プレースホルダ(後から値を設定可能)を記述 PreparedStatement st=con.prepareStatement("select * from product where name like ?"); st.setString(1, "%" + keyword + "%"); // SQL文の実行 ResultSet rs=st.executeQuery(); // 結果の取得 while (rs.next()) { pw.println(rs.getInt("id")); pw.println(":"); pw.println(rs.getString("name")); pw.println(":"); pw.println(rs.getInt("price")); pw.println("<br>"); } // データベースからの切断 // ResultSetクラスは、PreparedStatemntクラスがクローズされると自動的にクローズされるため省略可 st.close(); con.close(); } catch (Exception e) { e.printStackTrace(pw); } Page.footer(pw); } }
SQLインジェクション
SQLインジェクション・・・想定しないSQL文を実行され、データベースを不正操作すること。
登録するサーブレット
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <p>検索キーワードを入力してください</p> <form action="search" method="post"> <input type="text" name="keyword"> <input type="submit" value="検索"> </form> </body> </html>
@WebServlet(urlPatterns={"/chapter14/search"}) public class Search extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter pw = resp.getWriter(); Page.header(pw); try { InitialContext ic=new InitialContext(); DataSource ds=(DataSource)ic.lookup("java:/comp/env/jdbc/book"); Connection con=ds.getConnection(); // リクエストパラメータの取得 String keyword = req.getParameter("keyword"); // SQL文の指定 // プレースホルダ(後から値を設定可能)を記述 PreparedStatement st=con.prepareStatement("select * from product where name like ?"); st.setString(1, "%" + keyword + "%"); // SQL文の実行 ResultSet rs=st.executeQuery(); // 結果の取得 while (rs.next()) { pw.println(rs.getInt("id")); pw.println(":"); pw.println(rs.getString("name")); pw.println(":"); pw.println(rs.getInt("price")); pw.println("<br>"); } // データベースからの切断 // ResultSetクラスは、PreparedStatemntクラスがクローズされると自動的にクローズされるため省略可 st.close(); con.close(); } catch (Exception e) { e.printStackTrace(pw); } Page.footer(pw); } }
トランザクション
トランザクション・・・DBにおいて分割して実行することのできない処理の単位
コミット・・・実行の結果を確定すること
ロールバック・・・実行を取り消して、実行前の状態にもどすこと
デフォルトでは、自動コミットモードが有効になっている。SQL文を1個実行する限りは、自動コミットで問題ない。
@WebServlet(urlPatterns={"/chapter14/transaction"}) public class Transaction extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter pw = resp.getWriter(); Page.header(pw); try { InitialContext ic=new InitialContext(); DataSource ds=(DataSource)ic.lookup("java:/comp/env/jdbc/book"); Connection con=ds.getConnection(); // リクエストパラメータの取得 String name = req.getParameter("name"); int price = Integer.parseInt(req.getParameter("price")); // 自動コミットを無効 con.setAutoCommit(false); PreparedStatement ps = con.prepareStatement("insert into product values(null, ?, ?)"); ps.setString(1, name); ps.setInt(2, price); // SQL文の実行 ps.executeUpdate(); ps = con.prepareStatement("select * from product where name = ?"); ps.setString(1, name); // SQL文の実行 ResultSet rs = ps.executeQuery(); int line = 0; while(rs.next()) { line++; } if(line == 1) { // コミット con.commit(); pw.println("商品を登録しました。"); } else { // ロールバック con.rollback(); pw.println("商品はすでに登録されています"); } con.setAutoCommit(true); ps.close(); con.close(); } catch (Exception e) { e.printStackTrace(pw); } Page.footer(pw); } }
トランザクション分離レベル・・・複数のトランザクションが同時に実行されたとき、トランザクションの一貫性をどの程度まで保つかを定義したもの。
SERIALIZABLE・・・複数のトランザクションを順番に実行したとき同じ結果になる
REPEATABLE READ・・・トランザクションが実行中に取得するデータは、途中で他のトランザクションによって変更されない
READ COMMITTED・・・他のトランザクションによる更新について、コミット済みのデータのみを取得する
READ UNCOMMITTED・・・他のトランザクションによる更新について、コミット済みでないデータも取得する