Springアクセスデータベース異常の処理方法

36549 ワード

テキストリンク:http://sarin.javaeye.com/blog/888458
今日はSpringがデータベースにアクセスする異常の処理方法についてお話しします.JDBC APIを使用する場合、javaを放出することを宣言する操作が多いです.sql.SQLException例外は、通常、例外処理ポリシーを設定します.
JDBC APIを使用する場合、javaの放出を宣言する操作が多い.sql.SQLException例外は、通常、例外処理ポリシーを設定します.SpringのJDBCモジュールは私たちに異常処理メカニズムを提供して、この異常システムのベースクラスはDataAccessExceptionで、それはRuntimeExceptionの一種で、それでは強制的に異常を捕まえる必要はありません.Springの異常システムは以下の通りです:Spring访问数据库异常的处理方法
SpringにおけるJDBCモジュールの異常を明確に処理していない.その異常処理メカニズムを理解するには,いくつかのテストを行う.次のテストコードを見てください.
public void insert(final Vehicle vehicle) {      

  String sql = "insert into vehicle  (ID,PLATE,CHASSIS,COLOR,WHEEL,SEAT) values  (:id,:plate,:chassis,:color,:wheel,:seat)";
  SqlParameterSource parameterSource = new BeanPropertySqlParameterSource(vehicle);
  getSimpleJdbcTemplate().update(sql, parameterSource); }
public void insert(final Vehicle vehicle) { String sql = "insert into vehicle(ID,PLATE,CHASSIS,COLOR,WHEEL,SEAT) values(:id,:plate,:chassis,:color,:wheel,:seat)"; SqlParameterSource parameterSource = new BeanPropertySqlParameterSource(vehicle); getSimpleJdbcTemplate().update(sql, parameterSource); }

 
public static void main(String[] args) {               

        ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:org/ourpioneer/vehicle/spring/applicationContext.xml");

        VehicleDAO vehicleDAO = (VehicleDAO) ctx.getBean("vehicleDAO");

        Vehicle vehicle = new Vehicle(" B-000000", "1A00000001", "RED", 4, 4);

        vehicle.setId(1);

        vehicleDAO.insert(vehicle);

        }         

    public static void main(String[] args) {          

        ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:org/ourpioneer/vehicle/spring/applicationContext.xml");

        VehicleDAO vehicleDAO = (VehicleDAO) ctx.getBean("vehicleDAO");

        Vehicle vehicle = new Vehicle(" B-000000", "1A00000001", "RED", 4, 4);

        vehicle.setId(1);

        vehicleDAO.insert(vehicle);

        } 

 
SQL文を修正して、自増プライマリ・キーの特性を使用しないで、ここで重複するプライマリ・キーを設定すると、プログラムを実行すると、フィールド重複の異常が報告されます.この例外をキャプチャします.
try {

        vehicleDAO.insert(vehicle);

        } catch (DataAccessException e) {

            SQLException sqle = (SQLException) e.getCause();

            System.out.println("Error code: " + sqle.getErrorCode());

            System.out.println("SQL state: " + sqle.getSQLState());

            }             

    try {              

        vehicleDAO.insert(vehicle);          

        } catch (DataAccessException e) {              

            SQLException sqle = (SQLException) e.getCause();              

            System.out.println("Error code: " + sqle.getErrorCode());              

            System.out.println("SQL state: " + sqle.getSQLState());          

        } 

エラー・コードとSQLステータスを取得できます(データベース・システムによって異なります):
Spring访问数据库异常的处理方法
HSQLデータベースのエラーコードについてはorg.hsqldb.トレースクラスでは、実行結果に負の番号があることに注意して、クラスでは負の番号が定義されていないことを確認します.これにより、104:一意制約検証に失敗したなど、このエラーの具体的な意味がわかります.これが私たちが故意に設定した重複プライマリ・キーの問題です.
SpringのJDBCモジュールはorgに格納されているいくつかのエラーコードを事前に定義しています.springframework.jdbc.supportパッケージのsql-error-codes.xmlファイルでは、HSQLについて説明する内容は次のとおりです.
<bean id="HSQL" class="org.springframework.jdbc.support.SQLErrorCodes">        

        <property name="databaseProductName">             

            <value>HSQL Database Engine</value>         

        </property>         

        <property name="badSqlGrammarCodes">             

            <value>-22,-28</value>         

        </property>         

        <property name="duplicateKeyCodes">             

            <value>-104</value>         

        </property>         

        <property name="dataIntegrityViolationCodes">             

            <value>-9</value>         

        </property>         

        <property name="dataAccessResourceFailureCodes">             

            <value>-80</value>         

        </property>     

        </bean>         

        <bean id="HSQL" class="org.springframework.jdbc.support.SQLErrorCodes">         

        <property name="databaseProductName">             

            <value>HSQL Database Engine</value>         

        </property>         

        <property name="badSqlGrammarCodes">             

            <value>-22,-28</value>         

        </property>         

        <property name="duplicateKeyCodes">             

            <value>-104</value>         

        </property>         

        <property name="dataIntegrityViolationCodes">             

            <value>-9</value>         

        </property>         

        <property name="dataAccessResourceFailureCodes">             

            <value>-80</value>         

        </property>     

    </bean> 

 
残りのデータベースのエラーコードの内容もこのファイルから取得できます.次に、例外処理をカスタマイズする方法を見てみましょう.私たちはorgにいることを知っています.springframework.jdbc.supportパッケージの下にsql-error-codesがあります.xmlファイルは、Spring起動時にこのファイルのエラーコードを自動的に読み取り、いくつかのエラーコードを事前に分類し、カスタマイズした例外を使用するために強化することができます.まず、例外クラスを定義し、前の-104エラーをカスタマイズします.HSQLの重複キーの問題です.
package org.ourpioneer.vehicle.exception;      

    import org.springframework.dao.DataIntegrityViolationException;      

    public class VehicleDuplicateKeyException extends DataIntegrityViolationException {          

        public VehicleDuplicateKeyException(String msg) {              

            super(msg);          

        }          

        public VehicleDuplicateKeyException(String msg, Throwable cause) {              

            super(msg, cause);          

        }      

    }     

    package org.ourpioneer.vehicle.exception;  

    import org.springframework.dao.DataIntegrityViolationException;  

    public class VehicleDuplicateKeyException extends DataIntegrityViolationException {      

        public VehicleDuplicateKeyException(String msg) {          

            super(msg);      

        }      

        public VehicleDuplicateKeyException(String msg, Throwable cause) {          

            super(msg, cause);      

        }  

    } 

その後、sql-error-codesを再作成します.xmlコードをクラスパスのルートディレクトリの下に配置すると、Springはそれを発見し、カスタマイズしたファイルを使用して、構成で以下のように定義します.
<bean id="HSQL" class="org.springframework.jdbc.support.SQLErrorCodes">             

        <property name="databaseProductName" value="HSQL Database Engine" />             

        <property name="useSqlStateForTranslation" value="false" />             

        <property name="customTranslations">                 

        <list>                     

            <ref local="vehicleDuplicateKeyTranslation" />                 

        </list>             

        </property>         

    </bean>         

    

    <bean id="vehicleDuplicateKeyTranslation" class="org.springframework.jdbc.support.CustomSQLErrorCodesTranslation">             

        <property name="errorCodes" value="-104" />             

        <property name="exceptionClass" value="org.ourpioneer.vehicle.exception.VehicleDuplicateKeyException" />         

    </bean>     

    

    <bean id="HSQL" class="org.springframework.jdbc.support.SQLErrorCodes">         

        <property name="databaseProductName" value="HSQL Database Engine" />         

        <property name="useSqlStateForTranslation" value="false" />         

        <property name="customTranslations">             

        <list>                 

            <ref local="vehicleDuplicateKeyTranslation" />             

        </list>         

        </property>     

    </bean>     

    

    <bean id="vehicleDuplicateKeyTranslation" class="org.springframework.jdbc.support.CustomSQLErrorCodesTranslation">         

        <property name="errorCodes" value="-104" />         

        <property name="exceptionClass" value="org.ourpioneer.vehicle.exception.VehicleDuplicateKeyException" />     

    </bean> 

HSQLのbeanの名前を変更しないで、useSqlStateForTranslationをfalseに設定すれば、私たちが定義した異常クラスを使用することができます.メイン関数からtry/catchブロックを削除し、プログラムを起動すると、次のように表示されます.
Spring访问数据库异常的处理方法
Springは起動情報から私たちがカスタマイズしたsql-error-codesを発見したことがわかります.xmlは、HSQLデータベースの処理部分を置き換え、我々が定義した例外を使用して、プライマリ・キーが繰り返す異常をシミュレートした後、VehicleDuplicateKeyExceptionが投げ出されます.このほか、SQLExceptionTranslatorインタフェースを実装し、JDBCテンプレートに実例を注入して異常制御を実装することもできます.まず、Translatorクラスを作成します.
package org.ourpioneer.vehicle.exception;      

    import java.sql.SQLException;      

    import org.springframework.dao.DataAccessException;      

    import org.springframework.jdbc.UncategorizedSQLException;      

    import org.springframework.jdbc.support.SQLExceptionTranslator;      

    public class VehicleDuplicateKeyTranslator implements SQLExceptionTranslator {          

        public DataAccessException translate(String task, String sql, SQLException ex) {              

            if (task == null) {                  

                task = "";

            }              

            if (sql == null) {              

                

            }              

            if (ex.getErrorCode() == -104) {                  

                return new VehicleDuplicateKeyException(buildMessage(task, sql, ex));              

            } else {                  

                return new UncategorizedSQLException(task, sql, ex);              

                }          

        }          

        private String buildMessage(String task, String sql, SQLException ex) {              

            return "       :" + task + "; SQL [" + sql + "]; " + ex.getMessage();          

        }      

    }     
package org.ourpioneer.vehicle.exception;  

    import java.sql.SQLException;  

    import org.springframework.dao.DataAccessException;  

    import org.springframework.jdbc.UncategorizedSQLException;  

    import org.springframework.jdbc.support.SQLExceptionTranslator;  

    public class VehicleDuplicateKeyTranslator implements SQLExceptionTranslator {      

        public DataAccessException translate(String task, String sql, SQLException ex) {          

            if (task == null) {              

                task = "";          

            }          

            if (sql == null) {          

                

            }          

            if (ex.getErrorCode() == -104) {              

                return new VehicleDuplicateKeyException(buildMessage(task, sql, ex));          

            } else {              

                return new UncategorizedSQLException(task, sql, ex);          

                }      

        }      

        

        private String buildMessage(String task, String sql, SQLException ex) {          

            return "       :" + task + "; SQL [" + sql + "]; " + ex.getMessage();      

        }  

    } 

ここでtranslateメソッドを上書きするには、メソッドには3つのパラメータがあり、taskは現在の操作が行うタスクが何であるかを示し、sqlは実行するsql文であり、exはSQLExceptionを表し、そこから異常情報を取得することができ、その処理コードはエラーコード-104(HSQLデータベース)のエラーのみをキャプチャし、残りの構成情報は必要に応じて自分で追加することができる.Springで再構成するには、次の手順に従います.
<bean id="vehicleDuplicateKeyTranslator" class="org.ourpioneer.vehicle.exception.VehicleDuplicateKeyTranslator">

    </bean> 

    

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">         

        <property name="exceptionTranslator" ref="vehicleDuplicateKeyTranslator" />         

        <property name="dataSource" ref="dataSource" />     

    </bean>   

    

    <bean id="vehicleDAO" class="org.ourpioneer.vehicle.dao.VehicleDAOImpl">         

        <property name="jdbcTemplate" ref="jdbcTemplate" />     

    </bean>  

    

    <bean id="vehicleDuplicateKeyTranslator" class="org.ourpioneer.vehicle.exception.VehicleDuplicateKeyTranslator">

    </bean>   

    

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">         

        <property name="exceptionTranslator" ref="vehicleDuplicateKeyTranslator" />         

        <property name="dataSource" ref="dataSource" />     

    </bean>     

    

    <bean id="vehicleDAO" class="org.ourpioneer.vehicle.dao.VehicleDAOImpl">         

        <property name="jdbcTemplate" ref="jdbcTemplate" />     

    </bean> 

 
DAO実装クラスのコードを調整します.
public class VehicleDAOImpl extends SimpleJdbcDaoSupport implements VehicleDAO {          

        …   …          

        public void insert(final Vehicle vehicle) {              

            String sql = "insert into vehicle(ID,PLATE,CHASSIS,COLOR,WHEEL,SEAT) values(?,?,?,?,?,?)";              

            getJdbcTemplate().update(sql, vehicle.getId(),vehicle.getPlate(),vehicle.getChassis(),vehicle.getColor(),vehicle.getWheel(),vehicle.getSeat());          

        }      

        …   …      

    }     

    

    public class VehicleDAOImpl extends SimpleJdbcDaoSupport implements VehicleDAO {      

        …   …      

        public void insert(final Vehicle vehicle) {          

            String sql = "insert into vehicle(ID,PLATE,CHASSIS,COLOR,WHEEL,SEAT) values(?,?,?,?,?,?)";          

            getJdbcTemplate().update(sql, vehicle.getId(),vehicle.getPlate(),vehicle.getChassis(),vehicle.getColor(),vehicle.getWheel(),vehicle.getSeat());      

        }  

        …   …  

    } 

 
テストを行うために、他のコードを変更することなく、sql-error-codesを実行し続けることができる.xmlファイルをクラスパスのルートパスから削除すると、次の結果が得られます.
Spring访问数据库异常的处理方法
SpringのJDBCモジュールはカスタム例外処理にも非常に柔軟で、自分の好きな方法を選んで実現できます.利用者に役に立つことを願って、交流を歓迎して、次の部分はSpringのORMを紹介します.