質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
JSP

JSP(Java Server Pages)とは、ウェブアプリケーションの表示レイヤーに使われるサーバーサイドの技術のことです。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Struts 2

Apache Struts 2は、Apache Strutsプロジェクトにて開発されているオープンソースのJavaベースのWebアプリケーションフレームワークです。Sturts1に比べ、設定ファイルの削減、依存性の注入、POJO等の改善がなされています。

Q&A

解決済

6回答

1216閲覧

ロジックや方法についてアドバイスをいただきたいです。

Takki

総合スコア16

JSP

JSP(Java Server Pages)とは、ウェブアプリケーションの表示レイヤーに使われるサーバーサイドの技術のことです。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Struts 2

Apache Struts 2は、Apache Strutsプロジェクトにて開発されているオープンソースのJavaベースのWebアプリケーションフレームワークです。Sturts1に比べ、設定ファイルの削減、依存性の注入、POJO等の改善がなされています。

0グッド

2クリップ

投稿2018/10/13 09:36

編集2018/10/13 09:52

前提・実現したいプログラム

現在、JavaとStruts2を使用してプログラムの作成を行っておりますが、ロジックで行き詰まりました。
下記のやり方は無駄に複雑であり、綺麗な方法ではないということは理解していますが、
このようにやらなければいけない状況にありますので、アドバイスいただけると幸いです。

5つの内、どのスポーツを経験したことがあるかデータベースに記録するプログラムです。
画面にはスポーツ名の書かれたチェックボックスが5つあり、ユーザーが任意の数を選択して送信します。

ここでは2つテーブルを使用します。
【usersテーブル】
id   name    sports


1   山田    00000
2  鈴木     00000
3  佐藤    00000
4  田中    00000

【sportsテーブル】
id name


1   野球
2   サッカー
3   テニス
4   ゴルフ
5   バスケットボール

usersテーブルのsportsカラムには文字列の00000が初期値として挿入されており、
0(未経験)1(経験)として判断します。

00000の1の位(右端)からスポーツIDの1,2,3,4,5となってます。下記のような感じです。
users <sportsカラム> 0 | 0 | 0 | 0 | 0 ※0(未経験)1(経験)
sports <idカラム> 5 | 4 | 3 | 2 | 1

例えば、山田さんが「野球」と「ゴルフ」を選択した場合、データベースは下記のようになります。
【usersテーブル】
id   name    sports


1   山田    01001
2  鈴木     00000
3  佐藤    00000
4  田中    00000

教えていただきたいこと

現在はチェックボックスで選択されたスポーツidをActionクラスで配列で受け取っています。
その配列を利用し、Actionクラスで下記のようなロジックを組みたいと思っていますがいい案が浮かびません。

private String number = "00000";
private Collection<Integer> checkBoxSports;

配列が[2,3]の場合、00110のように2,3の位を1に変更した5桁の文字列をnumberに再代入する

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2018/10/13 09:44

チェックの配列から数値に変換するのがわからないんですか?いまいちなにを聞きたいのかわかりません
Takki

2018/10/13 09:55

分かりづらくてすみません。質問内容を簡潔にしました。配列を元に文字列の特定の部分を変更(今回の場合であれば0を1に)変更する方法があれば教えていただきたいです。
guest

回答6

0

Collectionに置き換える理由は、Struts2のチェックボックス用タグである <s:checkboxlist> が、 チェックボックスがチェック済みであるデータが格納されている java.util.List 型で 受け取るようになっているので、ビット文字列をListに変換する処理が必要でしょう。

<s:checkboxlist>を使ったチェックボックス入力欄を表示するJSPは次のようになります。

html

1<%@ page contentType="text/html; charset=UTF-8" %> 2<%@ taglib prefix="s" uri="/struts-tags" %> 3<html> 4<body> 5<s:form action="register" method="POST"> 6 <s:checkboxlist name="selectedSports" list="sportsList" listKey="id" listValue="name" value="selectedSports"></s:checkboxlist> 7 <s:submit value="送信" /> 8</s:form> 9</body> 10</html>
  • name : FORM送信時のパラメータ名
  • list : チェックボックスに表示する項目名とチェック時の値が入っているlistのActionクラスフィールド名
  • listKey : listで指定したチェックボックスにチェックされた時のvalue値
  • listValue : チェックボックス用表示ラベル
  • value : デフォルトチェックされている値のList表現

この形をとるため、valueに渡すList側の値を作ります。一番簡単なのは、ActionかDTOでもどちらでも良いのですが変換ロジックを作ります。例えば最も単純な例では、以下のようになるでしょう。

java

1public class SportConverter { 2 public static List<Integer> convertToList(String bitString) { 3 String[] bits = bitString.split(""); 4 List<Integer> bitList = new ArrayList<>(); 5 6 for (int i=0;i<bits.length;i++) { 7 if (bits[i].equals("1")) { 8 bitList.add(i + 1); 9 } 10 } 11 12 return bitList; 13 } 14}

例えば、bitStringに "01101" が入っていた場合は、この戻り値は、[2,3,5] の3つの値が入っているListです。

これをActionクラスから渡せばよいでしょう。

java

1import java.util.ArrayList; 2import java.util.List; 3 4import org.apache.struts2.convention.annotation.Action; 5import org.apache.struts2.convention.annotation.Result; 6import org.apache.struts2.convention.annotation.Results; 7 8import com.github.apz.sample.model.SportConverter; 9import com.github.apz.sample.model.Sports; 10import com.opensymphony.xwork2.ActionSupport; 11 12@Results({ 13 @Result(name = ActionSupport.SUCCESS, type = "dispatcher", location="sports.jsp") 14}) 15public class SportsAction extends ActionSupport { 16 @Action("display") 17 public String display() throws Exception { 18 19 // ユーザが経験済みのスポーツ一覧を取得 20 String experiencedSports = "01001"; 21 22 selectedSports = SportConverter.convertToList(experiencedSports); 23 24 return ActionSupport.SUCCESS; 25 } 26 27 @Action("register") 28 public String register() throws Exception { 29 return ActionSupport.SUCCESS; 30 } 31 32 public List<Sports> getSportsList() { 33 // チェックボックスに表示するSports一覧を返す。 34 } 35 36 private List<Integer> selectedSports;  // 別途get/setメソッドを作成 37} 38

java

1// 別途get/setメソッドを作成 2public class Sports { 3 private Integer id; 4 private String name; 5}

投稿2018/10/13 16:40

A-pZ

総合スコア12011

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Takki

2018/10/15 12:37

ご回答ありがとうございました。ご丁寧な説明、ほんとにためになります。 今回は一番早く理解ができた回答の方法で解決しましたが、これから載せていただいた説明をじっくり読んで理解たいと思います。今後も質問すると思いますので、アドバイスをいただけると嬉しいです。
guest

0

sportsテーブルを、

id name value


1   野球 1
2   サッカー 10
3   テニス 100
4   ゴルフ 1000
5   バスケットボール 10000

としておいて、value を足しこんでいけばいいかと

投稿2018/10/13 11:04

y_waiwai

総合スコア87719

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Takki

2018/10/13 11:44

ご回答ありがとうございます! 非常に参考になりました!すごいです!私には思いつかなかったです(^^;) カラムを増やさないと実現は厳しいのでしょうか?
y_waiwai

2018/10/13 11:49

いや、こうしとくとわかりやすいし、処理も簡単になるってはなしで。 増やしたことでかかるコストと、運用でズボラできるコストを比べて、ズボラできそうならこうすればいいというはなしですね
Takki

2018/10/15 12:30

ご回答ありがとうございました!今回は別の方法で解決しましたが、非常に参考になりました。
guest

0

現状での回答については皆さんがやられているのでよいとして、本質的には DB 設計見直した方がよいですね。
というのも、今はスポーツが5種類だからいいですけど、これが増えたらどう対応しますか、という話です。

投稿2018/10/14 01:36

tacsheaven

総合スコア13703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Takki

2018/10/15 12:26

ご回答ありがとうございました!やhりDB設計がおかしいですよね。実はもっと種目が多いんです(^^;)
guest

0

これでいいんじゃないの?
データの構造や変数名がいまいちわかりにくいですが…

java

1int answer = 0; 2for (int id : sportsId) { 3 answer |= 1 << (id - 1); 4} 5number = "00000" + Integer.toBinaryString(answer); 6number = number.substring(number.length() - 5);

投稿2018/10/14 01:23

編集2018/10/14 01:29
swordone

総合スコア20649

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Takki

2018/10/15 12:29

ご回答ありがとうございました!すみません、コードの理解に時間がかかりそうでしたので、今回は別の方法で解決しました。載せていただいたコードもこれから解読します。今後も質問すると思いますので、またお力を貸していただけると嬉しいです。
swordone

2018/10/15 14:23

そもそも0と1の文字列にする必要もなさそうな。このforで出した数値そのままでいい気もする。
guest

0

ベストアンサー

わかりやすいのは次の3ステップかなと。速度などは考慮していませんし、セキュリティ、例外の処理などについては別途質問するか、仕事仲間に聞いてみてください。

  • 更新前の文字列を配列に直す
  • 必要な箇所を1にする
  • 文字列に戻す

java

1 public static void main(String[] args) { 2 String sports = "00000"; 3 Collection<Integer> checkBoxSports = Arrays.asList(2, 5); 4 5 // 文字列を配列にします 6 char[] temp = sports.toCharArray(); 7 // 1を入れます 8 for(int i : checkBoxSports) 9 temp[i-1] = '1'; 10 // 文字列に戻します 11 sports = new String(temp); 12 13 System.out.printf(sports); 14 }

(※課題を読み間違えていたので回答を修正しました。)

投稿2018/10/13 11:03

編集2018/10/13 12:10
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Takki

2018/10/13 11:29

なるほど、比較を行うんですね! ただ、プログラミング歴がかなり浅いのでおっしゃっている方法がハッキリとは理解できません。 00000の文字列と[2,5]を比較して10010という文字列を作ることは可能なのでしょうか? 大変お手数ですが、簡単な例で構いませんのでソースコードを載せていただけると嬉しいです(><)
退会済みユーザー

退会済みユーザー

2018/10/13 11:37

おっと。お題を勘違いしていました、すみません。あとで修正とソースコードのっけときます。
Takki

2018/10/13 11:40

質問が分かりづらくて、すみません(><) よろしくお願いいたします!
Takki

2018/10/15 12:24 編集

ありがとうございます!テストプログラムですので、セキュリティー面や速度は問題ありません! 載せていただいたコードをもとに下記の通り目的の文字列を取得することができました。 本当に助かりました。  String sports = "00000";  Collection<Integer> checkBoxSports; char[] temp = sports.toCharArray(); for(int i : checkBoxSports){  switch(i){    case 1:     temp[4] = '1';     break;    case 2:     temp[3] = '1';     break;    case 3:     temp[2] = '1';     break;    case 4:     temp[1] = '1';     break;    case 5:     temp[0] = '1';     break;   }  }  sports = new String(temp);
swordone

2018/10/15 18:51

switchにしなくても、temp[5-i]でよくない?
Takki

2018/10/16 03:38

そちらのほうが断然いいですね。採用させてもらいました。
guest

0

多対多を表現する一般的な DB 設計をして、アプリケーションを組み立てていくのが良いと思います。

  • 多対多リレーションシップとは

https://products.sint.co.jp/siob/blog/relationship#toc-4

usrs , sports, sprts_users の3つのテーブルが必要になりますが、
user, sport の数の増減にも対応がしやすいです。
user から sport を求める 、sport から user を求める、いろいろな条件で検索する、集計をすることなどが ふつうの SQL コマンドで可能になります。

posrt を ビットに割り当てるようなことをすると、テーブル数は少なくて済むし、user から sport を引くのは簡単になります。
でもスポーツごとに経験者の集計をする場合に ビットを意識したロジックにすることが必要になります。

一般的な DB 構成にしておけば、SQL の組み方の例をみつけるのは簡単です。
DB の index を設定しておけば、大容量になっても速度低下は防げるはずです

投稿2018/10/15 21:21

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問