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

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

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

Oracleは、米オラクルが取り扱うリレーショナルデータベース管理システムです。メインフレームからPCまで、多様なプラットフォームに対応しています。

Java

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

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

例外

例外(exception)とは、プログラムの処理実行中に発生する、通常の処理の続行を妨げる特殊な事象のことを呼びます。この「例外」が発生した場合に、現在の処理を中断し、変わりに別の処理を実行させる事を「例外処理」と呼びます。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

Q&A

解決済

1回答

3111閲覧

SpringBootとJPAでOracleのSQLエラー(例外)を取得したい

akiras

総合スコア8

Oracle

Oracleは、米オラクルが取り扱うリレーショナルデータベース管理システムです。メインフレームからPCまで、多様なプラットフォームに対応しています。

Java

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

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

例外

例外(exception)とは、プログラムの処理実行中に発生する、通常の処理の続行を妨げる特殊な事象のことを呼びます。この「例外」が発生した場合に、現在の処理を中断し、変わりに別の処理を実行させる事を「例外処理」と呼びます。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

0グッド

0クリップ

投稿2018/05/17 04:35

前提・実現したいこと

SpringBootとJPAでOracleのデータ登録(Insert)を作っています。
実行時にSQLのエラーがあったとき、その例外を取得したいのです。

発生している問題・エラーメッセージ

・サンプルをもとに簡単な登録はできたのですが、SQLのエラー(例外)が取得できません
・Insertでキー重複になるデータを登録しても例外が発生しません
・例外が発生しないので、ブラウザには"success"が返ります

該当のソースコード

Oracleのテーブル(MEMBERS)

ID  NUMBER      No 1 NAME VARCHAR2(20 BYTE) Yes 2

.

Members.java(エンティティ) 

package com.example.demo; import javax.persistence.Entity; import javax.persistence.Id; import lombok.Data; @Data @Entity public class Members { @Id private Integer id; private String name; }

.
MembersService.java(サービス) 

package com.example.demo; import org.springframework.stereotype.Service; import lombok.RequiredArgsConstructor; @Service @RequiredArgsConstructor public class MembersService { private final MembersRepository membersRepository; public String create() { Members members = new Members(); members.setId(555555); members.setName("hansen"); membersRepository.save(members); return "success"; } }      ※キー重複時でも"success"が返ります

.

MembersController(コントローラー)

package com.example.demo; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import lombok.RequiredArgsConstructor; @RestController //@RequestMapping(value ="/members") @RequestMapping(value ="/members", method={RequestMethod.GET}) @RequiredArgsConstructor public class MembersController { private final MembersService membersService; @PostMapping public String create() { return membersService.create(); } }

試したこと

SQLを出力するよう設定しました。
具体的には・・・aoolication.propertiesに下記を記載

  '#SQLログ出力   logging.level.org.hibernate.SQL=debug   logging.level.org.hibernate.type.descriptor.sql.BasicBinder=trace   logging.level.org.hibernate.type.EnumType=trace

  - 結果 -

  1.正常時のメッセージ      select members0_.id as id1_0_0_, members0_.name as name2_0_0_ from members    members0_ where members0_.id=?    binding parameter [1] as [INTEGER] - [555555]    insert into members (name, id) values (?, ?)    binding parameter [1] as [VARCHAR] - [hansen]    binding parameter [2] as [INTEGER] - [555555]
  2.キー重複時のメッセージ      select members0_.id as id1_0_0_, members0_.name as name2_0_0_ from members    members0_ where members0_.id=?    binding parameter [1] as [INTEGER] - [555555]    ※キー重複時はInsertが実行される前にエラー?

.

Oracle内での実行結果

次のコマンドの行1の開始中にエラーが発生しました: insert into members (name, id) values ('sasasa', 555555) エラー・レポート: SQLエラー: ORA-00001: 一意制約(kkk.MEMBERS_PK)に反しています ※当然ですが、キー重複しています

開発環境

・Java 1.8.0_171
・Eclipse 4.7
・Oracle 11g

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2018/05/24 03:28

repository#save て戻り値で判断できたりするんじゃないの?(失敗時は null とか )
退会済みユーザー

退会済みユーザー

2018/05/24 03:59

キー重複時のエラーじゃなく正常にインサートできたからその結果の確認だな > 2.
akiras

2018/05/24 05:17

ありがとうございます。 Members model = membersRepository.save(members); System.out.println(model.toString()); → Members(id=1234500, name=hansen) ※キー重複でもsaveAndFlushでも結果はみな上記のとおりでした。 やはり登録後に検索しての判断しかないのですかね・・・残念ですが 下記URLの『制約エラーのハンドリング』とこで、一意制約違反などの制約系のエラーをハンドリングする必要がある場合は・・・とあるので、方法はあるようですが、私の頭では限界かもです。 https://terasolunaorg.github.io/guideline/public_review/ArchitectureInDetail/DataAccessJpa.html#id25
guest

回答1

0

ベストアンサー

SpringBootもJPAもわからないので、PL/SQLで実行します。

SQL

1CREATE TABLE MEMBERS 2 ( 3 ID NUMBER(2) NOT NULL 4 , NAME VARCHAR2(20) NOT NULL 5 , CONSTRAINT MEMBERS_PK PRIMARY KEY(ID) USING INDEX 6 ) ;

例外を取得するため、INSERTを実行するストアド・プログラムを用意します。

PL/SQL

1CREATE OR REPLACE PROCEDURE INSERT_MEMBERS 2 ( 3 I_ID IN MEMBERS.ID%TYPE 4 , I_NAME IN MEMBERS.NAME%TYPE 5 , O_ERRMSG OUT VARCHAR2 6 ) 7IS 8 CURSOR CUR_MEM 9 IS 10 SELECT ID 11 FROM MEMBERS 12 WHERE ID = I_ID ; -- 一意制約エラーはEXCEPTIONで取得できないので、あらかじめINSERTするキーの存在チェック 13 L_ID MEMBERS.ID%TYPE ; 14 EXP_DUPLICATE EXCEPTION ; -- IDがダブり 15 PRAGMA EXCEPTION_INIT(EXP_DUPLICATE, -20999) ; 16BEGIN 17 OPEN CUR_MEM ; 18 FETCH CUR_MEM INTO L_ID ; 19 IF CUR_MEM%NOTFOUND THEN 20 CLOSE CUR_MEM ; 21 INSERT INTO MEMBERS(ID, NAME) VALUES(I_ID, I_NAME) ; 22 O_ERRMSG := NULL ; 23 ELSE 24 CLOSE CUR_MEM ; 25 O_ERRMSG := 'TABLE MEMBERS ID DUPLICATE,' 26 || 'ID:'|| TO_CHAR(I_ID) 27 || ',NAME:' || I_NAME ; -- エラーを取得 28 RAISE EXP_DUPLICATE ; 29 END IF ; 30EXCEPTION 31 WHEN EXP_DUPLICATE THEN 32 RAISE_APPLICATION_ERROR(-20999, O_ERRMSG) ; 33 WHEN OTHERS THEN 34 O_ERRMSG := SQLERRM ; 35 RAISE ; 36END INSERT_MEMBERS ; 37/

-- 実行

PL/SQL

1DECLARE 2 L_ERRMSG VARCHAR2(2048) ; 3BEGIN 4 DBMS_OUTPUT.ENABLE(100000) ; 5 INSERT_MEMBERS(1, 'NAME1', L_ERRMSG) ; 6 INSERT_MEMBERS(2, 'NAME2', L_ERRMSG) ; 7 INSERT_MEMBERS(3, 'NAME3', L_ERRMSG) ; 8 INSERT_MEMBERS(3, 'NAME4', L_ERRMSG) ; 9 COMMIT ; 10EXCEPTION 11 WHEN OTHERS THEN 12 DBMS_OUTPUT.PUT_LINE(L_ERRMSG) ; -- エラー表示 13 ROLLBACK ; 14 RAISE ; 15END INSERT_MEMBERS ; 16/

-- 実行結果
DECLARE
*
行1でエラーが発生しました。:
ORA-20999: TABLE MEMBERS ID DUPLICATE,ID:3,NAME:NAME4
ORA-06512: 行14

バッチで大量のデータをINSERTするなら、あらかじめダブりを除いておく必要があります。

SQL

1SELECT ID 2 , COUNT(*) AS COUNTS 3FROM 元テーブル 4GROUP BY ID 5HAVING COUNT(*) = 1 ;

で一意なPRIMARY KEYがわかります。

PL/SQLについてはPL/SQL言語リファレンス を参照してください。

投稿2018/05/23 13:21

Orlofsky

総合スコア16415

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

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

akiras

2018/05/24 01:52

ありがとうございます。 一意制約エラーはEXCEPTIONで取得できないので、あらかじめINSERTするキーの存在チェック 作っていただいたサンプルコメントにある通り、一意制約では例外が発生しない(仕様?)のですね。 同じように、あらかじめSELECT文で確認してからの対応に変更します。 お世話になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問