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

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

ただいまの
回答率

90.61%

  • Java

    13522questions

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

  • SQL

    2328questions

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

  • Oracle

    592questions

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

  • Spring Boot

    468questions

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

  • 例外

    31questions

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

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

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 450

akiras

score 1

 前提・実現したいこと

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • asahina1979

    2018/05/24 12:28

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

    キャンセル

  • asahina1979

    2018/05/24 12:59

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

    キャンセル

  • akiras

    2018/05/24 14: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

    キャンセル

回答 1

checkベストアンサー

0

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

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

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

CREATE OR REPLACE PROCEDURE INSERT_MEMBERS
    (
    I_ID     IN  MEMBERS.ID%TYPE
  , I_NAME   IN  MEMBERS.NAME%TYPE
  , O_ERRMSG OUT VARCHAR2
    )
IS
    CURSOR CUR_MEM
    IS
        SELECT ID
        FROM MEMBERS
        WHERE ID = I_ID ;  -- 一意制約エラーはEXCEPTIONで取得できないので、あらかじめINSERTするキーの存在チェック
    L_ID  MEMBERS.ID%TYPE ;
    EXP_DUPLICATE  EXCEPTION ;  -- IDがダブり
    PRAGMA EXCEPTION_INIT(EXP_DUPLICATE, -20999) ;
BEGIN
    OPEN CUR_MEM ;
    FETCH CUR_MEM INTO L_ID ;
    IF CUR_MEM%NOTFOUND THEN
        CLOSE CUR_MEM ;
        INSERT INTO MEMBERS(ID, NAME) VALUES(I_ID, I_NAME) ;
        O_ERRMSG := NULL ;
    ELSE
        CLOSE CUR_MEM ;
        O_ERRMSG := 'TABLE MEMBERS ID DUPLICATE,'
                 || 'ID:'|| TO_CHAR(I_ID)
                 || ',NAME:' || I_NAME ;  -- エラーを取得
        RAISE EXP_DUPLICATE ;
    END IF ;
EXCEPTION
    WHEN EXP_DUPLICATE THEN
        RAISE_APPLICATION_ERROR(-20999, O_ERRMSG) ;
    WHEN OTHERS THEN
        O_ERRMSG := SQLERRM ;
        RAISE ;
END INSERT_MEMBERS ;
/

-- 実行

DECLARE
    L_ERRMSG VARCHAR2(2048) ;
BEGIN
    DBMS_OUTPUT.ENABLE(100000) ;
    INSERT_MEMBERS(1, 'NAME1', L_ERRMSG) ;
    INSERT_MEMBERS(2, 'NAME2', L_ERRMSG) ;
    INSERT_MEMBERS(3, 'NAME3', L_ERRMSG) ;
    INSERT_MEMBERS(3, 'NAME4', L_ERRMSG) ;
    COMMIT ;
EXCEPTION
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE(L_ERRMSG) ;  -- エラー表示
        ROLLBACK ;
        RAISE ;
END INSERT_MEMBERS ;
/

-- 実行結果
DECLARE

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

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

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


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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/24 10:52

    ありがとうございます。

    一意制約エラーはEXCEPTIONで取得できないので、あらかじめINSERTするキーの存在チェック

    作っていただいたサンプルコメントにある通り、一意制約では例外が発生しない(仕様?)のですね。
    同じように、あらかじめSELECT文で確認してからの対応に変更します。
    お世話になりました。

    キャンセル

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

  • ただいまの回答率 90.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Java

    13522questions

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

  • SQL

    2328questions

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

  • Oracle

    592questions

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

  • Spring Boot

    468questions

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

  • 例外

    31questions

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