20210418のJavaに関する記事は8件です。

JavaでShellコマンドを実行する

JavaでローカルLinux環境、リモートLinux環境にあるShellを実行して、標準出力、エラー出力、結果コードを取得することができます。 まず、下記のライブラリをインポートする必要があります。 pom.xml <dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.55</version> </dependency> 標準出力、エラー出力、結果コードを受け取るためのBeanクラス: ShellCmdResult.java import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; import java.util.List; public class ShellCmdResult { /** エラーリスト */ private List<String> errorList; /** echoリスト */ private List<String> echoList; /** 結果コード */ private int result; public ShellCmdResult() { this.echoList = new ArrayList<>(); this.errorList = new ArrayList<>(); } public List<String> getErrorList() { return errorList; } public void setErrorList(List<String> errorList) { this.errorList = errorList; } public List<String> getEchoList() { return echoList; } public void setEchoList(List<String> echoList) { this.echoList = echoList; } public int getResult() { return result; } public void setResult(int result) { this.result = result; } public void addEcho(String echo) { this.echoList.add(echo); } public void addError(String error) { this.errorList.add(error); } @Override public String toString() { return "ShellCmdResult{" + "errorList=" + StringUtils.join(errorList, ", ") + "], echoList=[" + StringUtils.join(echoList, ", ") + "], result=" + result + '}'; } } 実行ロジック: ShellCmdExecutor.java import com.jcraft.jsch.ChannelExec; import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; import org.apache.commons.lang3.StringUtils; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.Properties; public class ShellCmdExecutor { private static final int SESSION_TIMEOUT = 10000; private static final int CHANNEL_TIMEOUT = 5000; /** * リモートホストにあるコマンドを実行する. * * @param host リモートホスト名(IPアドレス) * @param port ポート番号 * @param user ユーザID * @param password パスワード * @param cmd コマンド * @return ShellCmdResult * @throws JSchException * @throws IOException */ public static ShellCmdResult exec(String host, int port, String user, String password, String cmd) throws JSchException, IOException { JSch jsch = new JSch(); Session session = null; ChannelExec channelExec = null; try { Properties config = new Properties(); config.put("StrictHostKeyChecking", "no"); session = jsch.getSession(user, host, port); session.setConfig(config); session.setPassword(password); session.connect(SESSION_TIMEOUT); channelExec = (ChannelExec) session.openChannel("exec"); channelExec.setCommand(cmd); channelExec.connect(CHANNEL_TIMEOUT); try (BufferedReader errorReader = new BufferedReader(new InputStreamReader(channelExec.getErrStream())); BufferedReader echoReader = new BufferedReader(new InputStreamReader(channelExec.getInputStream()))) { ShellCmdResult shellCmdResult = new ShellCmdResult(); String line = null; while ((line = echoReader.readLine()) != null) { shellCmdResult.addEcho(line); } while ((line = errorReader.readLine()) != null) { shellCmdResult.addError(line); } int exitStatus = channelExec.getExitStatus(); shellCmdResult.setResult(exitStatus); return shellCmdResult; } } finally { if (channelExec != null && channelExec.isConnected()) { channelExec.disconnect(); } if (session != null && session.isConnected()) { session.disconnect(); } } } /** * ローカルにあるコマンドを実行する. * * @param cmd コマンド * @return ShellCmdResult * @throws IOException * @throws InterruptedException */ public static ShellCmdResult exec(String cmd) throws IOException, InterruptedException { Runtime runtime = Runtime.getRuntime(); Process process = runtime.exec(new String[]{"bash", "-c", cmd}); try (BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); BufferedReader echoReader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { ShellCmdResult shellCmdResult = new ShellCmdResult(); String line = null; while ((line = echoReader.readLine()) != null) { shellCmdResult.addEcho(line); } while ((line = errorReader.readLine()) != null) { shellCmdResult.addError(line); } int exitStatus = process.waitFor(); shellCmdResult.setResult(exitStatus); return shellCmdResult; } } } 使い方: import com.jcraft.jsch.JSchException; import java.io.IOException; public class Main { public static void main(String[] args) throws IOException, JSchException, InterruptedException { // リモートShellを実行する String host = "192.168.xxx.xxx"; int port = 22; String user = "root"; String password = "12345"; String cmd = "bash /tmp/test.sh"; ShellCmdResult shellCmdResult = ShellCmdExecutor.exec(host, port, user, password, cmd); System.out.println(shellCmdResult); // ローカルShellを実行する cmd = "bash /tmp/test.sh"; shellCmdResult = ShellCmdExecutor.exec(cmd); System.out.println(shellCmdResult); } } 以上。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【忘備録】BigDecimalクラスについて

1.なぜBigDecimalクラスを使うのか double型のは正確な10進数の小数を保持できないため 10進数 → 2進数 → 10進数の変換の際に誤差が生じる ※例:0.3の場合 ・10進数表現 → 0.3 ・2進数表現 → 0.299999999999999988897769753748... 2.BigDecimalクラス書き方 sample import java.math.BigDecimal; //パッケージをインポート BigDecimal a = new BigDecimal("0.3"); //double型の誤差を防止するため文字列で変数宣言 ※BigDecimal.valueOf(double);でも可能 【参考リンク】 BigDecimal.valueOf(double)の話(@xx2xyyyさん) 3.BigDecimalクラス使い方 ①足し算・引き算 sample import java.math.BigDecimal; //パッケージをインポート // 足し算 BigDecimal a = new BigDecimal("0.3"); BigDecimal b = new BigDecimal("1"); BigDecimal answer = a.add(b); /*================================== 【出力】1.3 ==================================*/ // 引き算 BigDecimal a = new BigDecimal("0.3"); BigDecimal b = new BigDecimal("1"); BigDecimal answer = a.subtract(b); /*================================== 【出力】-0.8 ==================================*/ ②掛け算 sample import java.math.BigDecimal; //パッケージをインポート BigDecimal a = new BigDecimal("0.3"); BigDecimal b = new BigDecimal("10"); BigDecimal answer = a.multiply(b); /*================================== 【出力】3.0 ==================================*/ ③掛け算 無限小数を丸めモードを指定することで計算結果を丸めることができる sample import java.math.BigDecimal; //パッケージをインポート import java.math.RoundingMode; //パッケージをインポート BigDecimal a = new BigDecimal("10"); BigDecimal b = new BigDecimal("3"); BigDecimal answer = a.divide(b, 4, RoundingMode.DOWN); //小数点4位以下非表示 /*================================== 【出力】3.3333 ==================================*/ 【参考リンク】 丸めモード一覧(Java好き)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Effective Java(第3版) 項目3 privateコンストラクタかenum型でシングルトンを強制する

シングルトンを実装する方法としては、privateコンストラクタを使用するか、enumを使用するというものです。 記載内容 enumによるシングルトン 特に理由が無ければ、シングルトンを実装したい場合、単一要素のenum型を使用すれば良い。 ただし、何らかの親クラスを拡張したい場合は、enumは使えない。 (インタフェースを実装することはできる) privateコンストラクタによるシングルトン enum型で実装しない場合はこちらを使用することになる。 この場合、方法は大きく二つに分かれる public static finalフィールドにインスタンスを保持する ファクトリメソッドにより単一インスタンスを返す 前者の方がシンプルであり、シングルトンであることが明示的である。 後者のメリットは、シングルトンかどうかを後から変更できることと、 ファクトリメソッドをSuuplier<?>として使えること。 この2つのメリットが重要でなければフィールドで保持すればよい。 シングルトンクラスをSerializableにしたい場合、privateコンストラクタによる方法では、 readResolveの実装が必要いなる。 考察 そもそも、シングルトンパターンが良いか、という問題がありますが、 シングルトンを採用するのであれば、この項目の記載に従うのが良いです。 あまり見かけないかもしれないが、特に理由が無ければ、enum型で実装してしまうのが良いと思われます。 ファクトリメソッドのメリットとして、Supplier<?>での使用について記載されていますが、 フィールドで保持する場合でも(enumの要素でも)、 () -> Singleton.INSTANCE とすれば良いだけなので、ファクトリメソッドのメリットとしてはあまり強くないと思います。 どちらかと言えば、ファクトリメソッド化することで、遅延初期化等、実装の詳細を隠ぺいできることが大きいです。 (遅延初期化も乱用するべきではないと思いますが)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Java8のアップデートについて

今更な情報ですが、Java8でアップデートされた機能についてまとめました。 ちょっと記憶が曖昧で理解できておらず…とても恥ずかしい思いをした出来事があったので今後「二度と、そして絶対に忘れるまい」と改めてここに書いてみた次第です。 まずは全体感と概要を掴む目的で…ソースコードも至ってシンプルな内容となっています。 それぞれのアップデートについて今後別記事にて深堀りしていければと思っています。 参考にして頂ければ幸いです。 Java7からJava8でアップデートされた主な機能 インターフェースのstaticメソッド インターフェースのデフォルトメソッド finalの省略(実質的final) ラムダ式(() -> {}) メソッド参照 コンストラクター参照 レシーバーパラメーター(メソッドの引数this) 日付時刻API StreamAPI 他 インターフェースのstaticメソッド インターフェース上にstaticメソッドを定義できるようになった。 下記例のようにMainクラスにインターフェースを継承してstaticなメソッドを呼ぶことができる。 Main.java public class Main implements A1{ public static void main(String[] args) { System.out.println(A1.getValue()); } } interface A1 { public static int getValue() { return 1; } } 実行結果 1 インターフェースのデフォルトメソッド インターフェースに処理本体が記述できるメソッド(抽象でないメソッド)が定義できるようになった。これを「デフォルトメソッド」と呼ぶ。 Main.java public class Main { public static void main(String[] args) { A a = new A(); System.out.println(a.getValue()); } } class A implements B1 { } interface B1 { default public int getValue() { return 3; } } 実行結果 3 finalの省略(実質的final) 実質的にfinal(事実上のfinal(effectively final))な変数にはfinalを付けなくてもよくなった。 ラムダ式の中で使われる変数が実質的にfinalとなってしまう例 name変数が実質的にfinalとなってしまう(final修飾子をつけてもOK) Main.java public class Main { public static void main(String[] args) { String name = "Java!"; HelloJava g = a -> System.out.println("Hello " + name); name = "World!"; //ここでコンパイルエラー g.test(name); } } interface HelloJava { void test(String name); } 実行結果 ラムダ式から参照されるローカル変数は、finalまたは事実上のfinalである必要があります ラムダ式(() -> {}) 関数インターフェース(抽象メソッドが1つだけ定義されているインターフェース)の変数に代入する箇所ではラムダ式を渡すことが出来る。 匿名クラスを使った例 Main.java public class Main { public static void main(String[] args) { B1 b = new B1(); b.test("Java"); } } class B1 implements A1 { @Override public void test(String n){ System.out.println("Hello " + n); } } interface A1 { void test(String name); } ラムダ式を使った例 Main.java public class Main { public static void main(String[] args) { String name = "Java"; A1 a = (n) -> { System.out.println("Hello " + n ); }; a.test(name); } } interface A1 { void test(String name); } 実行結果 Hello Java メリット 匿名クラス(一度だけしか使わないようなクラス)を用いる場合よりも関数型インターフェース(抽象メソッドを1つだけ持つインターフェース)の記述が簡潔になることにある。 ラムダ式で記述することによって、プログラムが冗長になることを防ぎ、より本質的な部分の記述に集中することができるようになる。 メソッド参照 関数型インターフェース(抽象メソッドが1つだけ定義されているインターフェース)の変数にメソッドそのものを代入することが出来る。 これを「メソッド参照」と呼ぶ。 Main.java public class Main { public static void main(String[] args) { String name = "Java"; A1 a = System.out::println; a.test("Hello " + name); } } interface A1 { void test(String name); } 実行結果 Hello Java コンストラクター参照 メソッド参照と同様に、コンストラクターも関数型インターフェース(抽象メソッドが1つだけ定義されているインターフェース)の変数に代入することが出来る。 これを「コンストラクター参照」と呼ぶ。 ※java.util.functonパッケージのSupplierインターフェースを使用 Main.java import java.util.function.Supplier; public class Main { public static void main(String[] args) { Supplier<B1> b = B1::new; System.out.println(b.get().getName("Java")); } } class B1 { public String getName(String name) { return "Hello " + name; } } 実行結果 Hello Java レシーバーパラメーター(メソッドの引数this) メソッドの先頭の引数にthisが指定できるようになった。 これを明示的なレシーバーパラメーター(explicit receiver parameters)(コンパイル時のエラーメッセージ的には「明示的なthisパラメーター」)と呼ぶ。 Main.java public class Main { public static void main(String[] args) { B1 b = new B1(); System.out.println(b.getName()); } } class B1 { public String getName(B1 this) { return "Hello Java"; } } 実行結果 Hello Java 日付時刻API java.time.LocalDateクラスが導入された。このクラスの特徴としてはimmutable(不変)であること。※一度フィールドの値が設定されるとそれ以降その値が変更されないオブジェクトである。 メリットとしては次のようなことが挙げられる そのオブジェクトの値が変更されたかどうかを確かめる必要がない。 スレッドセーフである。 データの複製を考える必要がない。 複数クライアントによるデータ共有が可能である。 Main.java import java.time.LocalDate; public class Main { public static void main(String[] args) { LocalDate a = LocalDate.of(2021, 4, 1); LocalDate b = LocalDate.parse("2021-04-01"); System.out.println(a); System.out.println(b); } } 実行結果 2021-04-01 2021-04-01 Stream API コレクション、配列、I/Oリソースなどのデータ提供元となるデータソースを元に、集計操作を行うAPI。 ストリームはある処理結果を次の処理のデータソースとして渡すことができる。そのため、データソースを元に様々な処理を通してデータを加工することができる。 streamを使わない例 Main.java import java.util.*; public class Main { public static void main(String[] args) { List<String> list = Arrays.asList("bb", "aa", "cc"); for (int i=0; i<list.size(); i++) { String str = list.get(i).toUpperCase(); list.set(i, str); } Collections.sort(list); for(String str : list) { System.out.print(str + " "); } System.out.println(); } } streamを使った例 Main.java import java.util.*; public class Main { public static void main(String[] args) { List<String> list = Arrays.asList("bb", "aa", "cc"); list.stream().sorted().map(s -> s.toUpperCase()).forEach(s -> System.out.print(s + " ")); } 実行結果 AA BB CC    参考にさせて頂いたサイト 実行確認
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Effective Java(第3版) 項目2 多くのコンストラクタパラメータに直面したときにはビルダーを検討する

インスタンスの生成に多数のパラメータ、特に多数のオプションのパラメータが必要な場合は、ビルダーを検討するべき、という内容です。 記載内容 メリット 多数のコンストラクタオーバーロードを用意するより、利用側のコードが分かりやすくなる オプションの項目を後からsetするような状況を避けることが出来る ビルダーが戻り値型の任意のサブタイプのインスタンスを返すことが出来る デメリット 特に記載されていません 考察 メリットについて ファクトリメソッドと同じく、不変クラスの生成に向いていると思います。 呼び出し側のコードが、他言語にある名前付きパラメータのようになるのも分かりやすいです。 ただ、呼び出し側のコードで、何番目のパラメータが何の項目を指定しているのかが分かりづらい、 というのは、IDEの補助があればさほど大きな問題にはならないかもしれません。 また、パラメータの数が多すぎる場合に、いくつかのパラメータをまとめたクラスを定義し、 そのインスタンスを渡すようにすれば解決できるかもしれません。 デメリットについて 記載されていませんが、ファクトリメソッドと同様に、 サブクラスが作れない プログラマがインスタンスの生成方法を見つけるのが難しい というデメリットは発生します。 また、ビルダークラス分のコード量が増える、というのはデメリットと思われます。 まとめ 本では「コンストラクタやstaticファクトリメソッドが多くのパラメータを持つクラスを設計する際には、Builderパターンは良い選択です」と記載されていますが、 実際にビルダーを導入するべきなのかは難しい判断だと思います。 ビルダー自体は決まりきったコードなので、実装は容易なのですが、 どの程度のパラメータ数なら導入するのか、 将来のパラメータ追加をどの程度考慮するべきなのか、 ビルダー分のコード量増加というデメリットとのバランスを考える必要が有ります。 一度publicコンストラクタを公開してしまえば、後からビルダーを導入することが難しくなる、 というのも判断を難しくしていると思います。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PostgreSQLのJDBCはバインドできるパラメーター数に限界がある

ずいぶん昔の事ですが、 JavaでListに入った条件の数だけIN (?)バインドパラメーターを増やすような実装で 条件を増やし続けると次のようなIOExceptionがthrowされるという事象がありました。 java.io.IOException: Tried to send an out-of-range integer as a 2-byte value: 32768 この問題に遭遇したのはかなり昔の事ですが、当時は何らかのデータ量制限に引っかかったのだろうと思い IN(?)の使用を取りやめてカラム名 = ANY(?)にSQLステートメントを変更、 パラメーターをjava.sql.Arrayに変換する事でパラメーター数を押さえたら エラーが発生しなくなったのでそれ以上の深追いはしていませんでした。 この事象を思い出したので調べてみると、 どうやらPostgreSQLサーバーとの通信プロトコルのパラメーター数が2バイトを超える数値に対応していないようです。 GitHubにもissueが存在しました。 この制約はorg.postgresql.core.PGStream#sendInteger2(int)に書かれており パラメーター数に限らず、sendInteger2(int)でサーバーにデータを送る処理は32,767を超えることが出来ないようです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Effective Java(第3版) 項目1 コンストラクタの代わりにstaticファクトリメソッドを検討する

使用者がクラスのインスタンスを生成出来るようにするために、publicコンストラクタの代わりにstaticなインスタンス生成メソッドを提供することを検討するべき、という内容です。 記載内容 メリット 以下の5つのメリットが挙げられています 名前を付けられる 呼び出しごとに新たなインスタンスを生成する必要が無い 戻り値型の任意のサブタイプのインスタンスを返すことが出来る 引数に応じて、返すインスタンスの型を変えらえる 返されるオブジェクトのクラスは、ファクトリメソッドが書かれた時点で実装されている必要が無い デメリット 以下の2つのデメリットが挙げられています サブクラスが作れない プログラマがインスタンスの生成方法を見つけるのが難しい 考察 メリットについて ファクトリメソッドは特に不変クラスと相性が良いと思います。 特に「呼び出しごとに新たなインスタンスを生成する必要が無い」は、 実装当初は毎回インスタンスを生成していても、将来、インスタンスのキャッシュ等を追加できます。 (コンストラクタをpublicで公開してしまったら、利用側のコードを修正しないとなりません) 返すインスタンス型に関する3つのメリットは、インタフェースにstaticファクトリメソッドを定義すると、より良いかもしれません。 定義としてはインタフェース自身を返すように記載しておき、実際に返すのは、パッケージプライベートの実装クラスにしておけば、 利用側に実装クラスを隠すことが出来、将来の拡張が容易になります。 デメリットについて デメリットの1つ目「サブクラスが作れない」は問題ないと思われます。 機能追加時に、継承よりもコンポジションを選択すれば良いためです。 (むしろメリットだと思えるくらいです) 「プログラマがインスタンスの生成方法を見つけるのが難しい」は少し問題です。 IDEの助けがあっても、 ファクトリメソッドの名前が分かりづらかったり、JavaDocの記載が不十分だったりすると、 適切な生成方法を見つけるのが難しくなりそうです。 9ページの命名規約は確認しておいたほうが良いです。 まとめ 特に、不変クラスを作成しているのであれば、ファクトリメソッドの提供(および、コンストラクタを非publicにすること)を検討したほうが良いと思います。 提供する場合は、命名規約に注意するべきです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

データベース一覧表示(Java,MySQL)

データベースに登録したデータを一覧表示させる方法について、 気づいた事も含め、下記にまとめました。 環境 Java version 1.8.0_231 MySQL 8.0 Tomcat 9.0 Eclipse 実装 下記に簡単なプログラムを作成し、実装してみました。 テーブル構成 mysql> select * from nakamura; +----------+ | name | +----------+ | 中村倫也 | | 中村アン | | 中村俊輔 | | 中村獅童 | +----------+ DAO NakamuraDAO.java package nakamura; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class NakamuraDAO{ private static final String url = "jdbc:mysql://localhost/qiita?serverTimezone=JST"; //URL private static final String user = "root"; //DBユーザー private static final String pass = "pw"; //DBパスワード/ private List<Nakamura> nlist = new ArrayList<>(); //リストに格納 //データベース一覧表示メソッド public List<Nakamura> showAllList() { //JDBC読み込み try (Connection con = DriverManager.getConnection(url,user,pass)){ //データベースから氏名を取得するSQL文 String sql ="select name from nakamura"; PreparedStatement ps = con.prepareStatement(sql); //SQL文の実行 ResultSet rs = ps.executeQuery(); if(rs.next()){ //データベースから取得した値をセット Nakamura nakamura = new Nakamura(); //氏名の取得 nakamura.setName(rs.getString("name")); nlist.add(nakamura); } rs.close(); ps.close(); }catch(SQLException e) { e.printStackTrace(); } return nlist; } } DTO Nakamura.java package nakamura; import java.io.Serializable; public class Nakamura implements Serializable { private static final long serialVersionUID = 1L; private String name; //氏名 //コンストラクタ public Nakamura(){} //氏名 public String getName(){ return name; } public void setName(String name){ this.name = name; } } Servlet servlet.java package nakamura; import java.io.IOException; import java.util.List; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; //登録データを一覧表示するクラス @WebServlet("/NakamuraListDisplay") public class NakamuraListDisplay extends HttpServlet{ private static final long serialVersionUID = 1L; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //データベース一覧表示 NakamuraDAO nd = new NakamuraDAO(); List<Nakamura> nlist = nd.showAllList(); //セッションの開始 HttpSession session = request.getSession(); //セッションスコープにデータ登録 session.setAttribute("nlist",nlist); RequestDispatcher rd = request.getRequestDispatcher("nakamura_list.jsp"); rd.forward(request, response); } } JSP jsp.java <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ page import="nakamura.Nakamura" %> <%@ page import="java.util.ArrayList" %> <%@ page import="java.util.List"%> <% //セッションスコープに保存されたデータを取得 List<Nakamura> nlist = (List<Nakamura>)session.getAttribute("nlist"); %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>DB登録一覧</title> </head> <body> <table> <%for(int i = 0; i < nlist.size(); i++){%> <%Nakamura nakamura = (Nakamura)nlist.get(i);%> <tr> <td><%=nakamura.getName()%></td> </tr> <% } %> </table> </body> </html> webアプリーケーションの実行。 ブラウザを見てみると、、、 ??? 一件のみしか取得できていなかった、、、。 何故なのか? 色々と調べてみた結果、 NakamuraDAO.java if(rs.next()){ DAOクラスのこの行が原因でした。 データを1行のみしか取得していないため、データが複数あったとしても最初の一行のみしか取得しない。 if文とwhile文の使い分け if文 if( 条件式 ){  処理内容 } 条件式がtrueの場合、処理内容を実施。 主キーで取得するようなSQLであれば、1件しかデータを取得しないため、if文を使用。 while文 while (条件式) { 処理内容 } 条件式がtrueである間、処理内容を繰り返し実施する。 複数のデータを取得する場合は、while文を使用。 以上を踏まえ、 while文に修正、Webアプリケーションの実行。 ブラウザを見てみると、、、 データベースの全件取得、一覧表示することができました。 参考記事
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む