0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MyBatisにおける例外処理(PresistenceException)

Posted at

やりたいこと

JAX-RS(Jersey)× CDI × MyBatisの構成で開発するRESTful APIにおいて、SQLExceptionに対する例外処理を実施したい。

不具合

ExceptionMapperを用いてJAX-RSランタイムにて発生したSQLExceptionをキャッチできるような処理を追加したのですが、SQLExceptiontnがthrowされず処理できません。

原因調査

下記IBM様の記事サイトに以下のような記述がありました。

JPA プロバイダー実装は通常、SQL 状態またはエラー・コードがデータベース・サーバー問題またはネットワーク問題を示す可能性のある SQLException を伴う一般 PersistenceException をスローするだけです。(下記サイトから引用)

今回O/RマッパーはJPAではなくMyBatisを使っていますが、どうやらフレームワークによってはSQLExceptionではなくSQLExceptionをラップしたPersistenceExceptionがスローされるようです。

解決策

SQLExceptiponではなく、PersistenceExceptionをキャッチするように書き換えれば処理できそうです。
以下、ExceptionMapperを実装してPersistenceExceptionをキャッチするサンプルコードです。
例)PersistenceExceptionMapper.java

package com.example.exception.exceptionmapper;

import java.sql.SQLException;

import jakarta.inject.Inject;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;

import org.apache.ibatis.exceptions.PersistenceException;

import com.example.dto.ExceptionDto;
import com.example.exception.exceptionjson.ExceptionJson;
import com.example.util.Message;

@Provider
public class PersistenceExceptionMapper implements ExceptionMapper<PersistenceException> {

	@Inject
	private ExceptionJson json;

	@Override
	public Response toResponse(PersistenceException exception) {
		
		SQLException e = (SQLException)exception.getCause();
		ExceptionDto dto = new ExceptionDto(); 
		dto.setCode(Message.CODE_500);
		
		if("08001".equals(e.getSQLState())) {
			dto.setMsg(Message.EXCEPTION_4);
			return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
					.entity(json.exceptionJson(dto))
					.type(MediaType.APPLICATION_JSON)
					.build();
		}else {
			dto.setMsg(Message.EXCEPTION_5);
			return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
					.entity(json.exceptionJson(dto))
					.type(MediaType.APPLICATION_JSON)
					.build();
		}
		
	}

}

以下のように、PersistenceExceptionからSQLExceptionを取り出すことで、SQLExceptionのステータス等詳細に応じた処理を記述することができます。

        //PersistenceExceptionからSQLExceptionを取り出す
        //(exceptionはPersistenceException型)
		SQLException e = (SQLException)exception.getCause();
		ExceptionDto dto = new ExceptionDto(); 
		dto.setCode(Message.CODE_500);

        //SQLExceptionのステータスが08001かそれ以外かで処理分岐
  		if("08001".equals(e.getSQLState())) {
			dto.setMsg(Message.EXCEPTION_4);
			return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
					.entity(json.exceptionJson(dto))
					.type(MediaType.APPLICATION_JSON)
					.build();
		}else {
			dto.setMsg(Message.EXCEPTION_5);
			return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
					.entity(json.exceptionJson(dto))
					.type(MediaType.APPLICATION_JSON)
					.build();
		}

ソースコード

上記サンプルコードはGithubにコミットしています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?