- PR -

チェックボックスについたところのみを変更したい

投稿者投稿内容
永井和彦
ぬし
会議室デビュー日: 2002/07/03
投稿数: 276
お住まい・勤務地: 東京都
投稿日時: 2004-03-15 12:32
引用:

MySQLのTable1のデータは次のようになっています。

NO NAME POINT
------------------------
1 田中 90
2 石田 30
3 松井 60
4   黒田 70

HTML上ではテキストタイプで表示されており、その場で例えば
NO2の場合、石田→村上、30→80と書き換えてチェックボックスにチェックをして
更新ボタンを押すと

NO NAME POINT
------------------------
1 田中 90
2 村上 80
3 松井 60
4   黒田 70

このように更新されるようにしたいと思っております。



逆に「田中→鈴木」と画面上で変更しても、その横にある(対応する)チェックボックスにチェックを入れなければ更新はされない……ということですね。

そうしますと。Clusterさんも仰ってますが、一行ずつ更新していくことになるかと思います。また、HTML上での名前の付け方等も少々手を加える必要りますね。

とりあえず、Java(受け)側のコードのイメージを以下に。落書きなので、括弧の対応とかとれてなくても突っ込まないで下さい(汗

コード:


---entity start---

public class InputData {
private int no;
private String name;
private int point;

private boolean update;

//以下略。セッターとかゲッターとか、コンストラクタとか
}

---entity end---

---logic start---

String sql = "UPDATE TABLE1 SET NAME = ?, POINT = ? WHERE NO = ? ";

InputData[] data = リクエストから入力データを取り出すクラス.メソッド(request, ..and etc);

Connection connection = null;
try{
connection = コネクション取得クラス.getConnection();
PreparedStatement pre = connection.preparedStatement(sql);

for(int i = 0; i < data.length; i++){
if(data[i].isUpdate){
pre.setString(1, data[i].getName());
pre.setInt(2, data[i].getPoint());
pre.setInt(3, data[i].getNo());
pre.executeUpdate();
}
}

connection.commit();

}finally{
if(connection != null){
connection.rollback();
connection.close();
}
}

---logic end---





[ メッセージ編集済み 編集者: 永井和彦 編集日時 2004-03-15 12:41 ]
992029
会議室デビュー日: 2004/03/15
投稿数: 6
投稿日時: 2004-03-15 13:44
Clusterさん、永井和彦さん、ありがとうございます。

・逆に「田中→鈴木」と画面上で変更しても、その横にある(対応する)チェックボックスにチェックを入れなければ更新はされない……ということですね。

そういうことです。


・異なる値で更新したいなら、Update文を1レコードずつ作成し、
実行する必要があります。
・Clusterさんも仰ってますが、一行ずつ更新していくことになるかと思います。

とりあえずClusterさんのご指摘どおり作ってみたつもりなのですがうまくいきません。

・SQL文はそれだけのことですが、それ以前の問題として、NAMEとPOINTが配列で
取れてません。(c1は配列で取ってるのに)
これでは、異なる値で更新なんてできるはずも無いです。

色々と変えてみたのですがエラーが出てしまいよく分かりません。
申し訳ないのですがどういうふうに直したらいいのか教えてください。


一応作ったソースを以下に示します。
これではNO1はちゃんと更新されるのですが、
NO2以降はデータを書き換えてチェックをして更新するとNO1のデータがそのままコピーされてしまいます。
for文がちゃんとできてないのでしょうか??

よろしくお願い致します。

//変更指定されたデータNOを取得する
String[] aa = request.getParameterValues("c1");
String NAME = cnvString(request.getParameter("NAME"));
int TENSUU = Integer.parseInt(request.getParameter("TENSUU"));

for(int i = 0; i < aa.length; i++){

//変更するデータのを取得する
Statement st1 = conn.createStatement();
String sql1 = "UPDATE TABLE1 SET "
+ " NAME = '" + NAME + "', TENSUU = " + TENSUU
+ " WHERE NO =" +aa[i];
st1.executeUpdate(sql1);
Statement st2 = conn.createStatement();
String sql2 = "UPDATE TABLE1 SET "
+ " NAME = '" + NAME + "', TENSUU = " + TENSUU
+ " WHERE NO =" +aa[i];
st2.executeUpdate(sql2);
Statement st3 = conn.createStatement();
String sql3 = "UPDATE TABLE1 SET "
+ " NAME = '" + NAME + "', TENSUU = " + TENSUU
+ " WHERE NO =" +aa[i];
st3.executeUpdate(sql3);
Statement st4 = conn.createStatement();
String sql4 = "UPDATE TABLE1 SET "
+ " NAME = '" + NAME + "', TENSUU = " + TENSUU
+ " WHERE NO =" +aa[i];
st4.executeUpdate(sql4);
}
Cluster
ぬし
会議室デビュー日: 2003/03/06
投稿数: 289
お住まい・勤務地: 大阪
投稿日時: 2004-03-15 14:26
まず、forループの仕組みをちゃんとわかってるでしょうか?
992029さんのサンプルだと、チェックボックスが4つあったとして、SQL文は
16回実行されてしまいますよ?

次に、aaという変数は配列になってて、forループのカウンタである i を添え字にして
アクセスしているので、 i が0〜3に変わることで1番目〜4番目の値にアクセス
できますが、NAMEやTENSUUは配列になってないので値が先頭の1つしか入ってません。
(どのSQL文でも同じNAMEとTENSUUを使ってますよね?)
これでは、違う値が入るはずもありません。配列として取る方法は、

引用:

//変更指定されたデータNOを取得する
String[] aa = request.getParameterValues("c1");
String NAME = cnvString(request.getParameter("NAME"));
int TENSUU = Integer.parseInt(request.getParameter("TENSUU"));


"c1"を取ってるときのように、getParameterValuesを使って取ってください。
(getParameterでは、複数あるうちの先頭だけしか取れません。ちょうど、
992029さんが言っているような結果(NO1だけが取れる)になります。)

あとは、NAMEとTENSUUが配列になるので、forループの中で適切な添え字で配列に
アクセスすればOKです。
じつは、この「適切な添え字」というのが難しいのですが。
(私の前のコメントでの注の部分がヒントです。)
992029
会議室デビュー日: 2004/03/15
投稿数: 6
投稿日時: 2004-03-15 15:45
Clusterさん、ありがとうございます。

・"c1"を取ってるときのように、getParameterValuesを使って取ってください。
 
getParameterValuesを使ってみました。
String[] aa = request.getParameterValues("c1");
String[] NAME = request.getParameterValues("NAME");
String[] TENSUU = request.getParameterValues("TENSUU");

TENSUUはIntegerなのですが
Int[] TENSUU = request.getParameterValues("TENSUU");
にするとエラーが出てしまいます。
これでもよろしいのでしょうか??

・あとは、NAMEとTENSUUが配列になるので、forループの中で適切な添え字で配列に
アクセスすればOKです。

添え字をNAMEはj、TENSUUはkにしました。

実行したところエラーは出ないのですが、
変更をしようとしてもどれも変更できません。
やはりfor文がおかしいのでしょうか??

どうかよろしくお願い致します。


下のプログラムは今作っているソースです。
このソースではチェックボタンをチェックしたところを
削除、または変更できるようにするプログラムです。
削除は今のところうまくいきます。


--------------------------------------------------------

<%@ page contentType="text/html; charset=Shift_JIS"
import="java.sql.*" %>
<% request.setCharacterEncoding("Shift_JIS"); %>
<%!
//文字コードの変換
public static String cnvString(String s) {
try {
return new String(s.getBytes("8859_1"), "JISAutoDetect");
}
catch(Exception e) {
return null;
}
}
%>

<%
//データベースの設定
String sv = "localhost"; //サーバ名
String db = "hellodb"; //データベース名
String user = ""; //ユーザ名
String pass = ""; //パスワード
String encode = "Shift_JIS"; //文字コード

//データベースに接続する
Class.forName("org.gjt.mm.mysql.Driver");
String url = "jdbc:mysql://" + sv + "/" + db
+ "?user=" + user
+ "&password=" + pass
+ "&useUnicode=true&characterEncoding=" + encode;
Connection conn = DriverManager.getConnection(url);


if(request.getMethod().equals("POST")){

String str=request.getParameter("hyouji");

if (str!=null) {

if (str.equals("削除")) {

try {
//削除指定されたデータIDを取得する
String[] aa = request.getParameterValues("c1");
//データを削除する
Statement st = conn.createStatement();
String sql = "DELETE FROM TABLE1 WHERE (NO IN(";
for(int i=0;i < aa.length; i++){
sql += aa[i];
if (i < aa.length -1) {
sql += ",";
}
else {
sql += "))";
}
}
st.executeUpdate(sql);

//削除したデータIDを表示する
out.println("データを削除しました");
for (int i =0;i<aa.length;i++){
out.println("<br>データID:" + aa[i]);
}
}
catch (Exception e) {
out.println("データ削除エラー");

}

}

if(str.equals("変更")){

try {
//変更指定されたデータNOを取得する
String[] aa = request.getParameterValues("c1");
String[] NAME = request.getParameterValues("NAME");
String[] TENSUU = request.getParameterValues("TENSUU");


for(int i = 0; i < aa.length; i++){
for(int j = 0; j < NAME.length; j++){
for(int k = 0; k < TENSUU.length; k++){


//変更するデータのを取得する
Statement st1 = conn.createStatement();
String sql1 = "UPDATE TABLE1 SET "
+ " NAME[j] = '" + NAME + "', TENSUU[k] = " + TENSUU
+ " WHERE NO =" +aa[i];
st1.executeUpdate(sql1);

Statement st2 = conn.createStatement();
String sql2 = "UPDATE TABLE1 SET "
+ " NAME[j] = '" + NAME + "', TENSUU[k] = " + TENSUU
+ " WHERE NO =" +aa[i];
st2.executeUpdate(sql2);

Statement st3 = conn.createStatement();
String sql3 = "UPDATE TABLE1 SET "
+ " NAME[j] = '" + NAME + "', TENSUU[k] = " + TENSUU
+ " WHERE NO =" +aa[i];
st3.executeUpdate(sql3);

Statement st4 = conn.createStatement();
String sql4 = "UPDATE TABLE1 SET "
+ " NAME[j] = '" + NAME + "', TENSUU[k] = " + TENSUU
+ " WHERE NO =" +aa[i];
st4.executeUpdate(sql4);
}}}

//変更したデータを表示する
out.println("データを変更しました");
for(int i = 0; i < aa.length; i++){
out.println("<br>データID:" + aa[i]);
}
}
catch (Exception e) {
out.println("データ変更エラー");
}
}
}

}


%>

<html>

<head>
<title>データを削除する</title>
</head>

<body>

<%

//データを取り出す
Statement st = conn.createStatement();
String sql = "SELECT * FROM TABLE1"; //実行するSQL
ResultSet rs = st.executeQuery(sql);

//取り出したデータを表示する
out.println("<table border=\"1\">");
out.println("<tr>");
out.println("<td> </td>");
out.println("<td>NO</td>");
out.println("<td>名前</td>");
out.println("<td>点数</td>");
out.println("</tr>");

while (rs.next()) {
out.println("<form method=\"POST\" action=\""
+ request.getRequestURI() + "\">");
out.println("<tr>");
out.println("<td><input type=\"checkbox\" name=\"c1\" value=\""
+ rs.getInt("NO") + "\"></td>");
out.println("<td>" + rs.getInt("NO") + "</td>");
out.println("<td><input type=\"text\" name=\"NAME\" value=\""
+ rs.getString("NAME") + "\"></td>");
out.println("<td><input type=\"text\" name=\"TENSUU\" value=\""
+ rs.getInt("TENSUU") + "\"></td>");
out.println("</tr>");

}
out.println("<tr>");
out.println("<td><input type=\"submit\" name=\"hyouji\" value=\"削除\"></td>");
out.println("<td><input type=\"submit\" name=\"hyouji\" value=\"変更\"></td>");
out.println("</tr>");
out.println("</form>");
out.println("</table>");

//データベース接続を閉じる
conn.close();
%>
</body>
</html>
Cluster
ぬし
会議室デビュー日: 2003/03/06
投稿数: 289
お住まい・勤務地: 大阪
投稿日時: 2004-03-15 17:31
引用:

やはりfor文がおかしいのでしょうか??



for文が、というよりforループの使い方が明らかにおかしいです。
まず、そのあたりをちゃんと確認(勉強?)されることをお勧めします。

そろそろ疲れてきたんで(笑)、forループのあたりの正解を書いちゃいます。
(実際にコンパイルはしてないので、細かい間違いはご容赦下さい)
コード:
try { 
    //変更指定されたデータNOを取得する 
    String[] aa = request.getParameterValues("c1"); 
    String[] NAME = request.getParameterValues("NAME"); 
    String[] TENSUU = request.getParameterValues("TENSUU"); 
    
    for(int i = 0; i < aa.length; i++){ 
    
        //変更するデータのを取得する 
        Statement st = conn.createStatement(); 
        String sql = "UPDATE TABLE1 SET " 
        + " NAME = '" + NAME[i] + "', TENSUU = " + TENSUU[i] 
        + " WHERE NO =" +aa[i]; 
        st.executeUpdate(sql); 
        
        //変更したデータを表示する 
        out.println("データを変更しました"); 
        out.println("<br>データID:" + aa[i]); 
    } 
} catch (Exception e) { 
    out.println("データ変更エラー"); 
} 


これで、「チェックボックスが全部チェックされている場合」は正しく動くはずです。

「チェックボックスが一部だけチェックされている場合」への対応は、
引用:

注:HTMLフォームがどうなっているのか定かでないですが、チェックボックスc1、
  テキストボックスPOINT・NAMEが単純に同数並んでいるのなら、単純に
  request.getParameterValues とするとうまくいきません。(配列がずれます)
  これは、HTTPの仕様で、チェックボックスはチェックしたものだけが
  送信されるからです。(テキストボックスは当然全て送信される)
  結果として、992029さんの例で言えば、
コード:
--------------------------------------------------------------------------------

c1=[2]
NAME=["田中","村上","松井","黒田"]
POINT=["90","80","60","70"]


--------------------------------------------------------------------------------


  という風に送信されます。ご注意下さい。


を参考に考えてください。
(これが、前の返答で『「適切な添え字」というのが難しい』といった部分です。)
992029
会議室デビュー日: 2004/03/15
投稿数: 6
投稿日時: 2004-03-15 18:52
・そろそろ疲れてきたんで(笑)、forループのあたりの正解を書いちゃいます。

申し訳ございません。
Clusterさんの言うとおり、チェックボックスが全部チェックされている場合は更新できました。
ありがとうございます。


・「チェックボックスが一部だけチェックされている場合」への対応は、
引用:
--------------------------------------------------------------------------------


注:HTMLフォームがどうなっているのか定かでないですが、チェックボックスc1、
  テキストボックスPOINT・NAMEが単純に同数並んでいるのなら、単純に
  request.getParameterValues とするとうまくいきません。(配列がずれます)
  これは、HTTPの仕様で、チェックボックスはチェックしたものだけが
  送信されるからです。(テキストボックスは当然全て送信される)
  結果として、992029さんの例で言えば、
コード:
--------------------------------------------------------------------------------

c1=[2]
NAME=["田中","村上","松井","黒田"]
POINT=["90","80","60","70"]


--------------------------------------------------------------------------------


  という風に送信されます。ご注意下さい。

--------------------------------------------------------------------------------


を参考に考えてください。
(これが、前の返答で『「適切な添え字」というのが難しい』といった部分です。)

ここで説明してくださっていることはよく分かるのですが、
やはり「適切な添え字というのが難しい」です。
NAMEでは「村上」、POINTでは「80」だけを引っ張り出してくるようにしないといけないってことですよね??

もう少しヒントをいただけないでしょうか??
よろしくお願い致します。
かずくん
ぬし
会議室デビュー日: 2003/01/08
投稿数: 759
お住まい・勤務地: 太陽系第三惑星
投稿日時: 2004-03-15 21:54
チェックボックスの値を上から順に、0からの連番にすれば、受け取ったチェックボックスの値から、変更する行を決定できるんじゃないの?
しょむ
ぬし
会議室デビュー日: 2001/09/06
投稿数: 430
投稿日時: 2004-03-15 22:01
値を取った(HTMLを作った)ときと、POSTしたときに、表がずれると変なことに。
表に unique key を付けて添字にすべき。

スキルアップ/キャリアアップ(JOB@IT)