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

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

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

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

Q&A

解決済

3回答

1831閲覧

Java 主キー制約を書きたい

退会済みユーザー

退会済みユーザー

総合スコア0

Java

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

0グッド

0クリップ

投稿2021/05/12 02:52

編集2021/05/13 05:25

JavaでDB接続の際に社員番号項目を入力させるときに主キー制約をJava上で書きたいです。
どうしてもうまくいかず悩んでいます。

Java

1 2 3 4 final String URL = "jdbc:postgresql://localhost:5432/education?serverTimezone=JST"; 5 final String USERNAME = "postgres"; 6 final String PASSWORD = "postgres"; 7 8 String empno = null; 9 String ename = null; 10 String yomi = null; 11 String job = null; 12 String mgr = null; 13 String hiredate = null; 14 String sal = null; 15 String comm = null; 16 String deptno = null; 17 int x = 0; 18 19 Scanner scanner = new Scanner(System.in); 20 21 //trueの間データの登録人数を入力させる 22 while (true) { 23 24 try { 25 System.out.println("データの登録人数を入力してください。"); 26 x = scanner.nextInt(); 27 28 try ( 29 Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD); 30 31 Statement statement = connection.createStatement();) { 32 connection.setAutoCommit(false); 33 34 //データ登録人数分データ入力を繰り返す 35 for (int i = 0; i < x; i++) { 36 37 System.out.println(i + 1 + "人目のデータ入力です。"); 38 39 //各項目のデータ入力 40 while (true) { 41 System.out.println("社員No.を入力してください。"); 42 empno = new Scanner(System.in).nextLine(); 43 44 Pattern p = Pattern.compile("[0-9]{4}"); 45 Matcher m = p.matcher(empno); 46 47 if (m.matches()) { 48 try { 49 50 String sql = "INSERT INTO EDUCATION.EMPLOYEES values(empno)"; 51 PreparedStatement ps = connection.prepareStatement(sql); 52 int result = ps.executeUpdate(sql); 53 connection.commit(); 54 55 } catch (SQLException se) { 56 int errorCode = se.getErrorCode(); 57 58 if (errorCode == 1) { 59 60 System.out.println("主キーが重複しています。"); 61 62 } else { 63 break; 64 65 } 66 67 } 68 break; 69 70 } else { 71 System.out.println("数字四桁で入力してください。"); 72 } 73 74 } 75 76 //各項目データ入力させる 77              //コードは省略してます 78 } 79 //SQL文で入力させたデータを入れていく 80 String sql = "INSERT INTO EDUCATION.EMPLOYEES VALUES (" + "'" + empno + "'," + "'" + ename 81 + "'," 82 + "'" + yomi + "'," + "'" + job + "'," + "'" + mgr + "'," + "'" + hiredate + "'," 83 + "'" 84 + sal + "'," + "'" + comm + "'," + "'" + deptno + "')"; 85 } 86 87 //ロールバック処理 88 try { 89 connection.commit(); 90 System.out.println("登録成功"); 91 92 } catch (SQLException e) { 93 connection.commit(); 94 95 connection.rollback(); 96 System.out.println("登録失敗:ロールバック実行"); 97 98 e.printStackTrace(); 99 100 } 101 102 } catch (SQLException e) { 103 104 e.printStackTrace(); 105 106 } 107 //登録人数の無限ループ回避 108 if (x == x) { 109 break; 110 } else { 111 112 } 113 114 //登録人数のトライキャッチ 115 } catch (Exception e) { 116 System.out.println("数字で入力してください。"); 117 scanner.next(); 118 119 } 120 } 121 scanner.close(); 122 123 } 124 125} 126 127

長くて書き方とかもなってないと思うので、気になる点があったらどんどん教えてほしいです。
お願いします。
とりあえず社員番号入力させる項目の主キー制約の部分がうまくいっていません。
if (errorCode == 1) { System.out.println("主キーが重複しています。");

ここのerrorCode == なにをかけばいいかわからない

ていう感じです。

すごい見づらいと思うので、主キー制約の部分だけでも最悪大丈夫です‼
よろしくお願いします。

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

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

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

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

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

m.ts10806

2021/05/12 04:16

se.getErrorCode には何が返ってるのでしょうか。 それ次第ですし、さいあく、決め事です(自分で決めて組むだけ)。
退会済みユーザー

退会済みユーザー

2021/05/12 08:57 編集

この周辺は主キー制約の書き方がわからずとりあえずネットからコピペした感じで、私自身ちゃんとわかっていないのですが、、、 とりあえず、私のイメージではDBにつないですでに存在する社員番号を入力したらそれがerrorCodeになって返ってくるイメージです、、、
m.ts10806

2021/05/12 09:05

では「持ってきたコードを理解すること」が当面の課題ですね。 自身が把握してないコードが潜在的にあるのは脅威にしかなりませんので。
退会済みユーザー

退会済みユーザー

2021/05/13 04:56 編集

そうですよね。デバッグなど使って頑張ります。
m.ts10806

2021/05/13 00:09

debugなのでデバッグです。細かいけどこういうところは大事
退会済みユーザー

退会済みユーザー

2021/05/13 01:30

気を付けます!!
m.ts10806

2021/05/13 01:31

質問は編集できますので。タイトル含めて調整してください。
退会済みユーザー

退会済みユーザー

2021/05/13 05:09

度々すみません。質問タイトルを編集してほしいとのことですよね?デバッグに関しては、編集したのですが。。。 先ほどご指摘いただいた自分が理解していないコードを省けということでしょうか? タイトルに関しては何が間違っていますか??
m.ts10806

2021/05/13 05:12

質問本文編集が反映されていないようです。編集されたら編集履歴が見れるようになります。 >タイトルに関しては何が間違っていますか?? タグにあるような単語を並べただけで質問内容に合致していません。要件を記載してください(「質問するときのヒント」のページは必ず確認しましょう)
退会済みユーザー

退会済みユーザー

2021/05/13 05:17

なるほど!ご丁寧にありがとうございます。 編集してきます。
guest

回答3

0

} catch (SQLException se) { int errorCode = se.getErrorCode(); if (errorCode == 1) { ・・・・ } ・・・ }

このerrorCodeをSystem.out.println()などで出力してみました?
getErrorCode()で得られるエラーコードは1にはならないんじゃないかと。
参考:PostgreSQL 7.4.6 文書 / 付録 A. PostgreSQL エラーコード


<他、該当箇所辺りで気になったこと>

  • 一意制約違反 だということを判定するのに INSERT文を発行している
  • 最終的にINSERT文でデータを登録するのに、再度INSERT文を発行するので、ココで一意制約違反になる

⇒ チェックするのなら、PK で select して 結果が 0件 → OK / 1件(以上) → NG としたほうがよいかと。

  • String sql = "INSERT INTO EDUCATION.EMPLOYEES values(empno)";

⇒ これだとただの文字列になってて、変数empnoは使われないです。SQL文内は?で、setInteger()とかでセットするんじゃないでしたっけ?

  • SQL文を組み立てるときに+でガシガシ連結してる

⇒ 折角PreparedStatementを使用しているので、パラメータを?で指定しておき、set○○()でそれぞれセットしたほうがいいです。
⇒ これは余談だけど、Stringを+でいっぱい連結していくとメモリを喰うので、StringBufferStringBuilderを使ってappend()していったほうがいいです。

  • 最後のINSERT文を発行してない

⇒ ただの処理抜けですかな?

すいません、あとは細かく見てないです。


追記:
PreparedStatement の使い方案

Java

1//SQL文で入力させたデータを入れていく 2String sql = "INSERT INTO EDUCATION.EMPLOYEES VALUES (" + "'" + empno + "'," + "'" + ename 3 + "'," 4 + "'" + yomi + "'," + "'" + job + "'," + "'" + mgr + "'," + "'" + hiredate + "'," 5 + "'" 6 + sal + "'," + "'" + comm + "'," + "'" + deptno + "')";

↓↓↓

Java

1Sting sql = "INSERT INTO EDUCATION.EMPLOYEES VALUES (?,?,?,?,?,?,?,?,?)"; 2// パラメータセット(DBの型に合わせて適宜変更してください) 3PreparedStatement ps = connection.prepareStatement(sql); 4ps.setString(empno); // 社員No 5ps.setString(ename); // 名前 6ps.setString(yomi); // フリガナ 7ps.setString(job); // 役職 8ps.setString(mgr); // 上司 9ps.setString(hiredate); // 入社日 10ps.setString(sal); // 給与 11ps.setString(comm); // インセンティブ 12ps.setString(deptno); // 部署ナンバー 13 14// SQL発行 15int result = ps.executeUpdate(sql); // <- これがないよ、と言ってます。

投稿2021/05/12 05:47

編集2021/05/13 03:28
kaputaros

総合スコア1844

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

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

退会済みユーザー

退会済みユーザー

2021/05/12 08:46

ご指摘していただいた部分見直ししていきます! SQL +で連結してるの私も気になってたんですが、全体的に入れ子が多くてできなかったんです、、、 入れ子が多いことが原因かはわからないんですが、、 エラーチェックが多くてそのたびにwhile forなどで繰り返ししているのでやはりメソッドで分けて呼び出したほうがよろしいのでしょうか?? 最後のinsert文が発行されていないというのはどういう意味でしょうか、、、 勉強不足ですみません。 一応実行したところ、DBに入力したデータは入ります。
kaputaros

2021/05/13 03:26

入れ子が多くて、、、というのは「チェックしてるところが」ですよね? +で連結しているSQL作成部は特に入れ子がないように見えますが。 対話式でチェックしながら進めるやり方なので、メソッド化はあまり意味がないように見えますが、 処理を共通化できるのであればその部分だけをメソッド化してもいいかもしれないですね。 > エラーチェックが多くてそのたびにwhile forなどで繰り返ししているので... while (true) { break; } を頻繁に使用するのはあまりよくないかと思います。 変数が上で宣言されているので、 while(変数 == null) {} と 変数がnullの間だけ繰り返す方が自然な気はします。 また、Scannerクラスの使い方をもう少し調べてみてもいいかもしれないですね。 > 最後のinsert文が発行されていないというのはどういう意味でしょうか、、、 > 一応実行したところ、DBに入力したデータは入ります。 社員Noのチェック時に1つ目のINSERT文を発行しているので、あるはずですよね。 そのあとにもう一度、2つ目のINSERT文を作成しているんですが、発行していないので、何も起きてないんです。 データをよく見ると、社員Noしか入ってないんじゃないでしょうかね? PreparedStatementを使ったSQLの発行部分の修正案は回答に追記しておきました。 参考にしてみてください。
dodox86

2021/05/13 04:42

@kaputarosさん PreparedStatement#setStringは第1引数がパラメータのインデックスではなかったでしょうか。 (修正"案"ですから、イメージは充分伝わっていると思いますけれども)
退会済みユーザー

退会済みユーザー

2021/05/13 04:56

追記していいただいたコードの部分自分で修正しつつ実行してみたのですが全体のデータを入力させる部分がうまくいかなくなりました。SQLにいれる???の部分を書く場所を間違えたのでしょうか。。。 PreparedStatementの部分はもう少し自分で調べてから書き直してみます。 int result = ps.executeUpdate(sql); こちらのコード以前はあったのですがなぜかけしていました。イクリプスでresult変数の値は使われていない。という警告が出ていたため消したのを思い出しました。これが発行する文だったんですね。 いろいろ手直ししているうちにきちんとデータが入れられていなかったことに気が付きました。テストしっかりすることが大切ですね。 そのほかご指摘いただいた点改善していきます! ありがとうございます。
guest

0

主キー(プライマリキー)が重複してのINSERTをexecuteUpdateで実行した場合、ご提示のコードのようにSQLExceptionthrowされているはずですが、そこでエラーコードを取得するために使っているSQLException#getErrorCode()が返す値は、ベンダー固有のものです。

SQLException#getErrorCode - JavaSE 8

このSQLExceptionオブジェクトのベンダー固有の例外コードを取得します。

ここで「ベンダー固有」とは何かと言うと、その製品を開発、提供している会社などの組織を指します。要は、お使いのPostgreSQLというRDBMS製品を提供しているところが独自に定義したエラーコードです。JDBCのドライバーはPostgreSQL用だけでなく、Oracle Database、MySQL、Microsoft SQL Serverなどたくさんのものがあり、それぞれのシステム固有の動作もあるので、エラーコードはそれぞれ違います。そのエラーコード毎に何かしら処理を行いたいのであれば、該当のRDBMSのリファレンスにあたらなければ分かりません。例えばPostgreSQLの9.5.25で言えば、以下がそれに該当するはずです。

Appendix A. PostgreSQL Error Codes - PostgreSQL 9.5.25 Documentation

主キーの重複だけでなく、NULL制約違反など様々なものがあるでしょう。お使いのPostgreSQLのバージョンも含め、実際にどんな値が返ってくるかはご自身で確認してください。

尚、SQLException#getSQLStateメソッドだともう少しまとまったかんじの文字列でのエラー状態をStringで得られるようです。SQLExceptionに関する公式のリファレンスを改めてあたってみてください。

投稿2021/05/12 04:47

編集2021/05/12 04:56
dodox86

総合スコア9256

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

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

退会済みユーザー

退会済みユーザー

2021/05/12 08:48

ベンダー固有!!知りませんでした、、、勉強不足でした、、、 ありがとうございます!やってみます。
guest

0

ベストアンサー

dodox86さん

そうでした。インデクスが必要ですね(笑)
失念してました。
まぁ、イメージなので( ゚∀゚)アハハ

ck.さん

dodox86さんがおっしゃる通りなので、
使用しているJavaのAPIでメソッドの引数など確認してください。

eclipseの警告は、
int result = ps.executeUpdate(sql);
この変数 result をそのあと使ってないから出たやつです。
警告はエラーとは違うので、処理が必要なら消さないでね。

投稿2021/05/13 05:27

編集2021/05/14 05:47
kaputaros

総合スコア1844

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

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

退会済みユーザー

退会済みユーザー

2021/05/14 05:07

警告とエラーが違うのはわかるのですが、int result...の文はSQLに発行する際に必要な部分なのになぜ変数が使われていないからといってエラーを出してくるのでしょう、、さすがにそこまでは判断がつかないのですかね? 動くコードを作るのに必死で、基礎的なことがだいぶ抜けていることがわかりました。 勉強しなおしてきます。 たくさんありがとうございます。
kaputaros

2021/05/14 05:57

あ、すいません。 上の回答に入れたつもりで、新規に回答立ててしまってました。 ベストアンサーありがとうございます(*_ _)ペコリ > 警告とエラーが違うのはわかるのですが、int result...の文はSQLに発行する際に必要な部分なのになぜ変数が使われていないからといってエラーを出してくるのでしょう、、さすがにそこまでは判断がつかないのですかね? エラーを出してるんじゃなくて、「変数使ってないけど、この処理って必要なの?」ってわざわざ教えてくれてるんです。 eclipseのポリシー(だったかな?)を変更したら出なくなりますよ。 (設定のどっかだったかと。忘れたので、変えたかったら調べてください。) 余談にはなるのですが、 この変数はプリミティブ型なのでそこまではリソースを喰わないですが、Listなんかのオブジェクトだと参照が残りっぱなしでリソースが開放されず、メモリを圧迫してシステムが動かなくなる問題になる、ってこともあるので、警告してくれてるんだと思いますー。 奥が深いですね。 勉強頑張ってください!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問