如何使用write这个用法

aaaa 0 Reputation points
2023-07-02T09:52:42.9066667+00:00

如何使用write这个用法不太懂

SD関連トランザクションコード一覧

販売管理

受注

T-code 名称 更新/照会
VA01 受注伝票登録 更新
VA02 受注変更 更新
VA03 受注照会 照会
VA05 受注伝票一覧 照会
V.02 不完全受注伝票一覧 照会

 

分納契約

T-code 名称 更新/照会
VA31 分納契約の登録 更新
VA32 分納契約変更 更新
VA33 分納契約照会 照会

 

出荷

T-code 名称 更新/照会
VL01N 出荷伝票登録 (受注参照) 更新
VL02N 出荷伝票変更 更新
VL03N 出荷伝票照会 照会
VL06F 一般出荷一覧-アウトバウンド出荷伝票 照会
VL09 出荷取消 更新
VL10B 出荷伝票登録 (発注参照) 更新
VL10G 今回出荷対象の伝票 更新
VLPOD 出荷証明変更 照会

 

入荷

T-code 名称 更新/照会
VL31N 入荷伝票登録 更新
VL32N 入荷伝票変更 更新
VL33N 入荷伝票照会 照会

 

シップメント

T-code 名称 更新/照会
VT01N シップメント登録(BKG登録) 更新
VT02N シップメント変更(BKG) 更新
VT03N シップメント照会(BKG) 照会
VT11 シップメント選択: 品目計画(BKG) 照会
VT70 出力: シップメント(S/I) 照会

 

請求

T-code 名称 更新/照会
VF01 輸出書類登録(INV・P/L) 更新
VF02 請求伝票変更 更新
VF03 請求伝票の照会 照会
VF05 請求伝票一覧 照会
VF05N 請求伝票一覧 照会
VF11 請求伝票取消 更新
VF31 請求伝票からの出力 照会
VFX3 ブロック中請求伝票一覧 照会

 

運賃

T-code 名称 更新/照会
VI01 運賃登録 更新
VI02 運賃変更 更新
VI03 運賃照会 照会
VI05 運賃一覧 照会
Microsoft 365 and Office | Excel | For business | Windows
0 comments No comments
{count} votes

16 answers

Sort by: Most helpful
  1. aaaa 0 Reputation points
    2023-07-05T21:38:06.0266667+00:00
    内部テーブルと構造は、どちらもABAPプログラムでデータを一時的に格納および操作するために使用されるデータ構造ですが、主な違いは以下のとおりです。
    
    ABAP,変数,構造,内部テーブル
    図1:変数 vs 構造 vs 内部テーブル
    内部テーブルは複数の行と列から成り立つメモリ領域。一方で構造(ワークエリア)は単一の行のみから構成されるメモリ領域です。
    
    
    内部テーブルの各行は、構造を使用して定義されることが一般的です。
    
    さらに詳しく学習しておきたい方は以下の記事をご覧ください。
    
    
    【ABAP】変数・構造・内部テーブル―データオブジェクトの違いを1分で解説
    【初心者向け】ABAPの基本―。変数・構造・内部テーブルとは何か?3つのデータオブジェクトの違いを初めてABAPを勉強する方向けに図解します。
    
    it-biz.online
    2021.01.10
    ステップ2:内部テーブルの宣言
    ステップ1で定義した構造(データ型)を使用して内部テーブルを宣言します。
    
    この際、内部テーブルのタイプ(標準テーブル、ソート済みテーブル、ハッシュテーブル)を指定することができます。
    
    参考 内部テーブルの分類と特徴
    
    * 内部テーブルの宣言(標準テーブル)
    DATA: it_employee TYPE STANDARD TABLE OF ty_employee.
    * ソート済みテーブルの宣言
    DATA: it_employee_sorted TYPE SORTED TABLE OF ty_employee WITH UNIQUE KEY id.
    * ハッシュテーブルの宣言
    DATA: it_employee_hashed TYPE HASHED TABLE OF ty_employee WITH UNIQUE KEY id.
    上記のサンプルコードでは標準テーブル(it_employee)、ソートテーブル(it_employee_sorted)、ハッシュテーブル(it_employee_hashed)の3種類の内部テーブルを宣言しています。
    
    構造を定義せずに内部テーブルを宣言するパターン①
    あまりおすすめできる方法ではないのですが、ステップ1の構造(データ型)を明示的に定義せずに内部テーブルを宣言するサンプルを以下に記載します。
    
    * 内部テーブルの宣言(標準テーブル)
    DATA: it_employee TYPE STANDARD TABLE OF ( id TYPE i, name TYPE string, age TYPE i ).
    この例では、内部テーブルit_employeeの宣言時に直接フィールドとデータ型を指定しています。
    
    ただし、この方法ではコードの再利用性と可読性が低くなるため、通常はデータ型を明示的に定義して使用することが推奨されます。
    
    構造を定義せずに内部テーブルを宣言するパターン②
    SAPの標準テーブルを参照して内部テーブルを宣言することができます。
    
    これにより、既存のデータベーステーブルの構造を継承し、内部テーブルを定義することができます。以下に、SAP標準テーブル(例:MARA)を参照して内部テーブルを宣言する方法の例を示します。
    
    * 内部テーブルの宣言(標準テーブル)
    DATA: it_mara TYPE STANDARD TABLE OF MARA.
    
    この例では、MARA(マテリアルマスタデータテーブル)を参照して、内部テーブルit_maraを宣言しています。
    
    こちらはしばしば利用されるパターンで頭に入れておくと良いでしょう。
    
    SAP標準テーブルを参照して内部テーブルを宣言する場合でも、必要に応じて標準テーブル、ソートテーブル、ハッシュテーブルのいずれかのタイプを指定することができます。ただし、内部テーブルの操作に特定のキーが必要な場合、適切なキーを指定して宣言する必要があるため注意しましょう。
    
    ステップ3:ワークエリアの宣言
    最後に内部テーブルに対して操作を行う際に使用されるワークエリアを宣言します。ワークエリアは、内部テーブルの行構造と同じデータ型です。
    
    * ワークエリアの宣言
    DATA: wa_employee TYPE ty_employee.
    
    ステップ1~3をまとめて以下に記載します。
    
    * データ型の定義
    TYPES: BEGIN OF ty_employee,
             id TYPE i,
             name TYPE string,
             age TYPE i,
           END OF ty_employee.
    * 内部テーブルの宣言(標準テーブル)
    DATA: it_employee TYPE STANDARD TABLE OF ty_employee.
    * ソート済みテーブルの宣言
    DATA: it_employee_sorted TYPE SORTED TABLE OF ty_employee WITH UNIQUE KEY id.
    * ハッシュテーブルの宣言
    DATA: it_employee_hashed TYPE HASHED TABLE OF ty_employee WITH UNIQUE KEY id.
    * ワークエリアの宣言
    DATA: wa_employee TYPE ty_employee.
    内部テーブルを宣言する際にワークエリアを必ずしも一緒に宣言する必要があるわけではありません。ただし、ワークエリアは内部テーブルの操作に便利なため、一般的には両方を宣言します。
    
    ワークエリアは、主に以下のような目的で使用されます。
    
    ワークエリアを同時に宣言する目的
    内部テーブルへのデータの挿入や更新
    ワークエリアを使用して、内部テーブルにデータを追加(APPEND文)や更新(MODIFY文)することができます。
    内部テーブルからのデータの読み取り
    READ TABLE文を使用して、内部テーブルからデータを読み取り、ワークエリアに格納することができます。これにより、内部テーブルのデータを個別に処理することができます。
    内部テーブルのデータの削除
    DELETE文を使用して、ワークエリアに一致するデータを内部テーブルから削除することができます。
    ループ処理
    LOOP文を使用して、内部テーブルのすべての行をワークエリアにコピーしながら繰り返し処理を行うことができます。
    
    要するに、ワークエリアを使用することで、内部テーブルのデータを効率的に操作できる(ワークエリアを宣言せずに内部テーブルのデータを操作する方法も存在しますが、その場合、コードが複雑になり可読性が低くなる)ので、内部テーブルを宣言する際には、一般的にはワークエリアも一緒に宣言すると覚えておきましょう。
    
    内部テーブルの宣言方法:まとめ
    構造(データ型)定義後に標準テーブル、ソートテーブル、ハッシュテーブルのいずれかのタイプを指定して宣言。
    同時にワークエリアも宣言しておくのが一般的。
    * データ型の定義
    TYPES: BEGIN OF ty_employee,
             id TYPE i,
             name TYPE string,
             age TYPE i,
           END OF ty_employee.
    * 内部テーブルの宣言(標準テーブル)
    DATA: it_employee TYPE STANDARD TABLE OF ty_employee.
    * ソート済みテーブルの宣言
    DATA: it_employee_sorted TYPE SORTED TABLE OF ty_employee WITH UNIQUE KEY id.
    * ハッシュテーブルの宣言
    DATA: it_employee_hashed TYPE HASHED TABLE OF ty_employee WITH UNIQUE KEY id.
    * ワークエリアの宣言
    DATA: wa_employee TYPE ty_employee.
    
    0 comments No comments

  2. aaaa 0 Reputation points
    2024-01-29T14:07:52.81+00:00
    iBATISはSQLを利用することに注力したフレームワークです。高機能なO/Rマッピングフレームワークに比べて簡単に理解でき、レガシーなJDBC、ResultSetを使ったプログラミングから簡単に乗り換えられます。
    
     特にSQLを多用する人には使いやすいフレームワークです。
    
    SQLは使いたいがJDBCは低レベルすぎる
    高機能なO/Rマッピングフレームワークは難しすぎる
    ソースコードからSQLを分離したいが動的なSQLの実装も必要
     このようなケースで、iBATISは特に有効です。
    
     本記事では、たくさんのサンプルソースを解説することで、「iBATISを使えばこんな風に書ける」ということが分かるようにしています。環境設定や、設定ファイルについての細かい説明は簡略化してあります。
    
    対象読者
    Javaの基本をマスターしている人
    SQL文を理解している人
    必要な環境
     iBATIS 2.3.0、J2SE 5.0の環境を前提に解説しています。データベースの選択は自由ですが、サンプルプログラムはHSQLDBで動作確認しています。
    
    サンプルデータベース
     本記事で使用しているデータベースは1つのテーブルを使用しています。
    
    サンプルで利用するテーブル
    CREATE TABLE DEPT (
        DEPTNO     NUMERIC(2) NOT NULL,
        DNAME      VARCHAR(14),
        LOC        VARCHAR(13),
        CONSTRAINT PK_DEPT PRIMARY KEY (DEPTNO)
    );
    プログラミングの概要
     iBATISを使うとどのようなプログラムになるのかを説明します。iBATISはSQL文を自分で定義します。定義したSQL文はそのままJDBCから発行されるので、RDBMSに依存した関数を利用することもできます。
    
     SQL文はXMLファイルに定義し、idを割り振ります。
    
    SQL定義の例
    <select id="getDept" resultClass="examples.dto.Dept">
        SELECT * FROM DEPT
        WHERE DEPTNO = #value#
    </select>
     "getDept"というidでSQL文を定義しました。#value#が埋め込みパラメータだと簡単に予想できます。プログラムからはこのidを参照してSQLを利用します。
    
    Javaプログラムからの利用
    Dept dept = (Dept)sqlMap.queryForObject("getDept", 20);
     埋め込みパラメータを指定してSQLを実行すると、結果が格納されたオブジェクトが得られます。
    
     それでは、サンプルソースと併せてiBATISの利用例を紹介していきましょう。
    
    利用の準備
     プログラムからiBATISを利用するためにDB接続などの設定をします。
    
    「SqlMapConfig」は、iBATIS全体の設定を行うファイルで、複数のsqlMapを参照するXMLファイルです。
    「SqlMap」は、SQLやオブジェクトへのマッピングを記述するXMLファイルです。
    SqlMapConfig
     DB接続設定の記述や、使用するsqlMapファイルへの参照を記述します。このサンプルではDept.xml(後述)を参照しています。
    
    SqlMapConfig.xml
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE sqlMapConfig
    PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
    "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
    
    <sqlMapConfig>
        <!-- DB接続設定 -->
        <transactionManager type="JDBC">
            <dataSource type="SIMPLE">
                <property name="JDBC.Driver"
                          value="org.hsqldb.jdbcDriver"/>
                <property name="JDBC.ConnectionURL"
                          value="jdbc:hsqldb:hsql://localhost/"/>
                <property name="JDBC.Username" value="sa"/>
                <property name="JDBC.Password" value=""/>
            </dataSource>
        </transactionManager>
    
        <!-- sqlMapファイル参照する -->
        <sqlMap resource="examples/sqlmap/maps/SqlMap-Dept.xml"/>
    </sqlMapConfig>
    SqlMap
     1つのSELECT文(getDept)を定義したSqlMapです。SqlMapファイル1つにSQLを複数定義できます。SqlMapファイルをいくつ作成しても構いません。
    
    SqlMap-Dept.xml
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE sqlMap
    PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
    "http://ibatis.apache.org/dtd/sql-map-2.dtd">
    <sqlMap>
        <!-- 1件検索 -->
        <select id="getDept" resultClass="examples.dto.Dept">
            SELECT DEPTNO, DNAME, LOC as location FROM DEPT
            WHERE DEPTNO = #value#
        </select>
    </sqlMap>
    SqlMapClientを返す
     作成したSqlMapConfigを読みこみ、iBATISを利用するためのオブジェクトがSqlMapClientです。このオブジェクトは、長寿命でスレッドセーフであるため、アプリケーションで1つだけ生成すればOKです。SqlMapClientを一度だけ作成し取得するためのクラスを作成します。
    
    MyAppSqlConfig.java
    package examples;
    
    import java.io.Reader;
    import com.ibatis.common.resources.Resources;
    import com.ibatis.sqlmap.client.SqlMapClient;
    import com.ibatis.sqlmap.client.SqlMapClientBuilder;
    /**
    * SqlMapClientを返すためのクラス
    */
    public class MyAppSqlConfig {
        private static SqlMapClient sqlMap;
        static {
            try {
                String resource = "examples/SqlMapConfig.xml";
                Reader reader = Resources.getResourceAsReader(resource);
                sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        public static SqlMapClient getSqlMapInstance(){
            //Singletoneとして利用
            return sqlMap;
        }
    }
    
    
    
    Interceptor は、コントローラーの実行前後で共通の処理を追加するための仕組みです。 主にログ出力や認可処理などの用途で使用されます。
    HandlerInterceptor
    Interceptor 用のクラスは、HandlerInterceptorインターフェースを実装する形で作成します。
    public
     
    class
     
    MyInterceptor
     
    implements
     
    HandlerInterceptor
     {
      
    //...
    }
    HandlerInterceptorには以下の 3 つのメソッドがあり、これらをオーバーライドすることで処理を定義します。
    preHandle
    @
    Override
    public
     
    boolean
     
    preHandle
    (
    HttpServletRequest
     request,
        
    HttpServletResponse
     response, 
    Object
     handler) throws Exception {
      
    //...
      
    return
     
    true
    ;
    }
    preHandle()は、コントローラーの実行前の処理を定義します。 リクエスト内容のログ出力や認可処理などを行ったりします。
    戻り値の真偽値は、trueであればコントローラーの処理を実行し、falseであればコントローラーの処理を実行せずに200のレスポンスを返します。
    引数のhandlerは、リクエストに紐づくコントローラーメソッドに該当します。 以下のようにすることで、メソッドの情報を参照できます。
    Method
     
    method
     = ((HandlerMethod) handler).
    getMethod
    ();
    postHandle
    @
    Override
    public
     
    void
     
    postHandle
    (
    HttpServletRequest
     request, 
    HttpServletResponse
     response,
        
    Object
     handler, @
    Nullable
     
    ModelAndView
     modelAndView) throws Exception {
      
    //...
    }
    postHandle()は、コントローラーの実行後の処理を定義します。 正確には、MVC の場合はテンプレートエンジンによるレンダリングの前に実行される処理で、REST API の場合はレスポンス送信前の処理となります。
    引数のhandlerは、preHandle()と同様にコントローラーメソッドに該当します。
    modelAndViewは、MVC の場合に設定した Model と View の情報に該当します。 ここで処理に共通する情報を Model に追加するなどを行います。
    modelAndView
    .
    addObject
    (
    "info"
    , 
    "Hello World!"
    );
    REST API の場合は、関係のないものなのでmodelAndViewはnullとなります。
    コントローラーで例外がスローされた場合、postHandle()は実行されません。
    afterCompletion
    @
    Override
    public
     
    void
     
    afterCompletion
    (
    HttpServletRequest
     request, 
    HttpServletResponse
     response,
        
    Object
     handler, @
    Nullable
     
    Exception
     ex) throws Exception {
      
    //...
    }
    afterCompletion()は、クライアントへレスポンスを送信した後の処理となります。 MVC の場合は、テンプレートエンジンによるレンダリングが完了してレスポンスを送信していることになります。
    引数のhandlerは、他と同様にコントローラーメソッドに該当します。
    exは、レンダリングで発生した例外が設定されます。 コントローラーでスローされた例外が設定されるわけではないので注意してください。 REST API ではレンダリング処理がないため、必ずnullとなります。
    afterCompletion()はpostHandle()と異なり、コントローラーで例外がスローされても実行されます。 そのため、コントローラー実行後に必ず行いたい処理はafterCompletion()に定義するとよいです。
    Interceptor の登録
    登録手順
    作成した Interceptor を実行させるためには、WebMvcConfigurerインターフェースを実装したConfigurationクラスで登録する必要があります。
    @
    Configuration
    public
     
    class
     
    WebMvcConfig
     
    implements
     
    WebMvcConfigurer
     {
      
    //...
    }
    登録手順として、初めに作成した Interceptor を DI コンテナに登録します。
    @
    Bean
    MyInterceptor
     
    myInterceptor
    () {
      
    return
     
    new
     
    MyInterceptor
    ();
    }
    次に Interceptor 登録用のメソッドであるaddInterceptors()をオーバーライドします。
    @
    Override
    public
     
    void
     
    addInterceptors
    (
    InterceptorRegistry
     registry) {
      
    //...
    }
    最後に、引数のregistryに Interceptor を追加すれば完了です。
    registry
    .
    addInterceptor
    (
    myInterceptor
    ());
    コード全体は以下のようになります。
    @
    Configuration
    public
     
    class
     
    WebMvcConfig
     
    implements
     
    WebMvcConfigurer
     {
      @
    Bean
      
    MyInterceptor
     
    myInterceptor
    () {
        
    return
     
    new
     
    MyInterceptor
    ();
      }
    
      @
    Override
      
    public
     
    void
     
    addInterceptors
    (
    InterceptorRegistry
     
    registry
    ) {
        
    registry
    .
    addInterceptor
    (
    myInterceptor
    ());
      }
    }
    実行順序
    Interceptor は、以下のように複数登録することが可能です。
    registry
    .
    addInterceptor
    (
    myInterceptor1
    ());
    registry
    .
    addInterceptor
    (
    myInterceptor2
    ());
    基本的には登録した順に Interceptor の処理が実行されます。 もう少し詳しくすると、以下の順で実行されます。
    順序	クラス	メソッド
    1	MyInterceptor1	preHandle()
    2	MyInterceptor2	preHandle()
    3	Controller	hoge()
    4	MyInterceptor2	postHandle()
    5	MyInterceptor1	postHandle()
    6	MyInterceptor2	afterCompletion()
    7	MyInterceptor1	afterCompletion()
    実行順序を変更したい場合はorder()を使用します。 指定した数値の小さい順に Interceptor が実行されるようになります。
    registry
    .
    addInterceptor
    (
    myInterceptor1
    ()).
    order
    (
    2
    );
    registry
    .
    addInterceptor
    (
    myInterceptor2
    ()).
    order
    (
    1
    );
    パスパターン
    Interceptor は、パスパターンによって処理の実行を制御することができます。
    特定のパスで実行したい場合は、addPathPatterns()を使用します。 以下の例は/api/以下すべてのパスでのみ実行されます。
    registry
    .
    addInterceptor
    (
    myInterceptor
    ())
            .
    addPathPatterns
    (
    "/api/**"
    );
    パス	実行可否
    /api	●
    /api/user	●
    /api/user/0001	●
    /user	×
    /user/api	×
    対照的な処理としてexcludePathPatterns()があります。 これは指定したパス以外で Interceptor の処理を実行することができます。 以下の例はaddPathPatterns()とは逆の結果となります。
    registry
    .
    addInterceptor
    (
    myInterceptor
    ())
            .
    excludePathPatterns
    (
    "/api/**"
    );
    パス	実行可否
    /api	×
    /api/user	×
    /api/user/0001	×
    /user	●
    /user/api	●
    これら 2 つの処理は組み合わせることが可能です。 以下の例は、「/app/以下で実行するが、/api/userは対象外とする」となります。
    registry
    .
    addInterceptor
    (
    myInterceptor
    ())
            .
    addPathPatterns
    (
    "/api/**"
    );
            .
    excludePathPatterns
    (
    "/api/user"
    );
    
    
    0 comments No comments

  3. aaaa 0 Reputation points
    2024-01-29T14:28:38.2766667+00:00
    Binderの初期化について 
    (パラメタからモデルへの型変換)
    概要
    Binderによる型変換はSpringの一般的な機能です。
    
    ここでは、リクエストパラメタを様々な型に変換する方法を中心に見ていきます。
    
    グローバルなBinderの初期化にも触れてみたいと思います。
    
     
    
    ※概要については以下の記事を参照ください
    
    参考: 03.基本概念:バインダー(Binder)とは
    
     
    
     
    
     
    
     
    
     
    
     
    
    型変換初期化メソッド(initBinder)について
    型変換の方法を設定するには、Binderを初期化します。
    
    型変換初期化をするためのメソッドは、@InitBinderアノテーションをつけたメソッドです。
    
    メソッドはBinderを引数にとり、メソッド内で初期化します。
    
    InitBinderメソッドで行う処理は、たいていの場合、主に以下の2つです。
    
     
    
    ・型変換の方法の設定
    
    ・上書きを許可するプロパティの設定
    
     
    
     
    
    【記述例(リクエストパラメタを日付型に変換しています)】
    
    @InitBinder("form")
    
    public void initBinderForm(WebDataBinder binder) {
    
        //バインドするときの日付のフォーマット指定。
    
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
    
        dateFormat.setLenient(false);
    
        binder.registerCustomEditor(Date.class, "user.upDate", new CustomDateEditor(dateFormat, true));
    
        //Userオブジェクトのうち、user.ageとuser.upDateパラメタのみを受け取るようにする場合
    
        binder.setAllowedFields("user.age", "user.upDate");
    
    }
    
     
    
     
    
    型変換の方法の設定
    型変換の設定方法は、PropertyEditorクラスをregisterCustomEditor()メソッドで設定していくという形をとります。
    
    PropertyEditorクラスは型変換の方法を定義したクラスです。自作しても良いですが、すでにいくつか用意されています。
    
    また、いくつかはデフォルトで設定されているので、すべてを設定する必要がありません。
    
    おそらくDateとNumberの書式を指定するために登録するくらいかと思います。
    
     
    
    【設定の方法】
    
    registerCustomEditor()は2種類用意されています。
    
    上記の記述例のように、プロパティ名("user.upDate")を指定する方法と、全てのDate型に対して設定する方法です。
    
    単純に、プロパティ名の引数を削除して、
    
    registerCustomEditor(型, PropertyEditor)という記述にすればプロパティ名は関係なくすべての型に対して設定されます。
    
     
    
     
    
    【PropertyEditor型変換クラス一覧(Springドキュメントからの引用)】
    
    
     
    
     
    
     
    
    不正なリクエストパラメタを拒否する方法
    既に他の記事で書いていますが、Binderでは不正なリクエストパラメタを無視する機能があります。
    
    具体的には、許可するプロパティ名を指定するか、拒否するプロパティ名を指定するか、2つの方法があります。
    
     
    
    【記述例】
    
    binder.setAllowedFields("user.age", "user.upDate");
    
    binder.setDisallowedFields("user.feeId");
    
    binder.setDisallowedFields("menu.*", "*dis*");  //ワイルドカードも使用できます
    
     
    
    メソッド名がそのまま意味をなしているのでだいたい予想がつくかと思いますが、
    
    setDisallowedFieldsが拒否するプロパティ名を指定するメソッドです。
    
     
    
     
    
    パラメタ名のプレフィックスを指定する方法
    パラメタ名の先頭とモデルのプロパティ名が一致しないケースがありえます。
    
    例えば、パラメタ名に"form.user.age", "form.user.upDate"のように、すべて"form."がついているようなケースです。
    
    この場合、getForm()/setForm()というメソッドが存在しない場合、リクエストパラメタの値がバインドされません。
    
     
    
    こんな時はプレフィックスを設定します。
    
     
    
    【記述例】
    
    binder.setFieldDefaultPrefix("form.");
    
    こうすることで、パラメタ"form.user.age"が、form.getUser().setAge(21) に設定されます。
    
     
    
     
    
     
    
    Validatorの設定
    妥当性チェックもBinderの仕事ですので、当然ながらValidatorも設定できます。
    
    妥当性チェックについては他の記事で記述しますので、ここでは割愛します。
    
     
    
     
    
     
    
     
    
    グローバルなBinderの初期化
    もし全体を通して同じ設定の場合、Controller毎にBinderを初期化するのは大変です。
    
    もちろんSpringMVCでは、グローバルな初期化方法も用意されています。
    
    その方法を見てみます。
    
     
    
     
    
    WebBindingInitializerインターフェース
    【追記:2018/6/23】
    
    Spring3.2以降、ControllerAdviceを使用するらしいので、記事を修正しました。
    
    アノテーションを使用するので、XMLファイルに<mvc:annotation-driven />の記述は必要です。
    
    実は、WebBindingInitializerの派生クラスを作成するだけです。
    
    実際のコードと、Spring設定ファイルへの記述方法を見る方が早いので、さっそく見てみましょう。
    
     
    
    【サンプル(クラス): com.sample.contoller.GlobalBindingInitializer】
    
    @ControllerAdvice
    
    @Component
    
    public class GlobalBindingInitializer implements WebBindingInitializer {
    
     
    
     @InitBinder
    
     @Override
    
     public void initBinder(WebDataBinder binder, WebRequest req) {
    
      //Dateの書式を設定します
    
      SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss.SSS");
    
      dateFormat.setLenient(false);
    
      binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
    
     }
    
    }
    
     
    
    Dateの書式の設定の仕方は、Controllerのときと同じです。
    
    0 comments No comments

  4. aaaa 0 Reputation points
    2024-02-29T00:42:12.63+00:00

    Java・SpringBootを用いたAPI開発をスタート。しかし例外処理の実装する中で、様々な疑問にぶつかる日々、、(元々独学エンジニアだったので例外処理の理解が浅すぎた)
    その都度調べて解釈してを繰り返し、分かった気になってきたので、それをまとめてみます。
    今回は例外処理の解釈に焦点を当てているため、実装方法については触れません。

    例外処理をする意味

    まずは大前提として、__なぜ例外処理をするのか__について。 利用者視点

    • 例外的状況が起きた時専用の処理を設けることで、プログラムが強制終了するのを避けられる
      • 例えば、try-catch文を用いて、問題が起きている箇所だけプログラムを実行せずに飛ばしてあげる
        • その上で、__利用者に「ここの操作が間違っているよ!」__と知らせてあげることができる
          - 例えば、「送信するファイルの形式が間違っています!」と画面に表示させるなど
          

    開発者視点

    • どこで問題が発生したかを特定できる(=バグ修正が容易になる)
    • メソッドに例外処理の記述があることで、__事前に「このメソッドは問題が起こるかも知れない」__と把握することができる

    なんでIf文ではだめなの?

    例外処理を書いている中で、「これIf文で処理できるじゃん」って考えに一度はなるはず(私はなった)。結論から言うと、If文で処理することは基本的には悪手である。

    • 理由①
      • 理論上ではif文で全て処理することが可能だが、現実的には全て事前に対処するなんて不可能(そんなこと出来たらそもそもバグなんて作ってない)
      • 理由②
        • 例外的状況の処理と通常処理のコードの見分けが付きにくくなり、開発者的な視点から良くない

    throwとthrowsの使い分け

    例外の投げ方が色々あって、何を使うのが正解なんだーと悩んでた。
    結論から言うと、どれを使えばいいのかは__設計思想によるため正解というものはない__。
    正解に近づけるための第一歩として、まずはそれぞれの強み弱みを知ることが大事。 throwについて

    例外的状況が起こったメソッドの中で問題を処理するもの。特徴としては、例外を監視しているJVMに対して任意のタイミングで「例外的状況になりました」と伝えられる点。

    • ポジティブ
      • 独自に作った例外を投げたい時に使える
    throw
    
    • ネガティブ
      • いちいち例外処理を記述する必要があり、コードが冗長になりがち

    throwsについて

    「throws」をメソッドの後ろにつけることによって、メソッド内で例外が発生した時に自身のメソッド内でcatchするのではなく、呼び出し元に例外を投げられる

    private
    
    • ポジティブ
      • 呼び出し元でまとめて例外処理できるため、コードの記述量が少なく済む
         - try-catchをいちいち書かなくていい
        
            - ResponseEntityExceptionHandlerを継承したhandlerクラスを実装する際に相性がいい
        
                  - 「ResponseEntityExceptionHandlerを継承したhandlerクラス」については次の章で解説
        
                        - 正直ここの理解はまだ浅いため断定は避けたい(小声)
        
                        - ネガティブ
        
                           - 例外処理のバケツリレーがおこり、かえって可読性の悪いコードになる恐れも
        
                              - 呼び出し元で適切に例外処理を実装してくれるのかといった懸念が残る
        

    落とし所

    私自身の考える落とし所

    Java・Spring Bootを用いたAPI開発において、現状の私自身が考える使い分けとしては以下の通りである。

    • 自作例外を投げたい時
      • throwで投げる
      • その他
        • throwsで呼び出し元に任せる
          - 自作ハンドラークラス(ResponseEntityExceptionHandlerを継承したhandlerクラス)で一括処理
          

    他の方が考えた落とし所

    「非検査例外を扱いつつ、メソッド定義のthrows節に書くという方法がよいのではないか」と言う意見を発見。 詳しくはこの記事を参考に。 ResponseEntityExceptionHandlerを継承したhandlerクラスを作る意味

    SpringBootでAPIを作るときは、基本的にはResponseEntityExceptionHandlerを継承させたハンドラークラスを自作しましょーとのことです。

    0 comments No comments

  5. aaaa 0 Reputation points
    2024-02-29T00:47:11.35+00:00

    Spring Bootで使われるアノテーション

    【DIに関するアノテーション】

    @￰Autowired

    クラスのフィールドに付与することで、使いたいクラスをインスタンス化し、変数に設定してくれるアノテーション。 @￰Component

    インスタンス化させたいクラスに付与するアノテーション。
    このアノテーションを付与することでDIコンテナにBeanとして登録され、@￰Autowiredが付与されたフィールドにインスタンスが注入される。 @￰Controller

    インスタンス化させたいクラスに付与するアノテーションその2。
    クライアントとのデータ入出力を制御する(画面からHTTPリクエストを受け付ける)クラスに付与する。 @￰Service

    インスタンス化させたいクラスに付与するアノテーションその3。
    業務ロジックを提供するクラスに付与する。 @￰Repository

    インスタンス化させたいクラスに付与するアノテーションその4。
    データベースとのやりとりを行うクラスに付与する。 @￰Configuration

    アノテーションを使ってのDIコンテナへのBean登録が複雑な場合、JavaConfigと呼ばれるBeanを生成するクラスを作成する。そのJavaConfigに付与するアノテーション。 @￰Bean

    @￰Configurationが付与されたJavaConfig内のインスタンスを生成するメソッドに付与するアノテーション。 実装例

    @Configuration
    

    @￰Scope

    インスタンスの生成・破棄のタイミングを指定するアノテーション。 実装例

    @Controller
    

    @￰Primary

    優先的にDIを行いたいクラスに付与するアノテーション。 【Controllerクラスに関するアノテーション】

    @￰RestController 

    REST API 用のControllerクラスに付与するアノテーション。
    クラスにつけることでそのクラス内のメソッドの戻り値がHTTPのレスポンスボディとして返される。 @￰RequestMapping

    リクエストURLに対して、どのクラス・メソッドが処理を実行するか定義するアノテーション。クラスあるいはメソッドに付与する。
    GET・POSTといったHTTPメソッドを指定する「method」属性とURLのパスを指定する「value」属性を指定できる。 実装例

     
    

    @￰GetMapping

    @￰RequestMappingのGETリクエスト用アノテーション。
    使用することで@￰RequestMappingで記述していたmethod属性を省略することができる。 @￰PostMapping

    @￰RequestMappingのPOSTリクエスト用アノテーション。 @￰RequestParam

    URLに含まれるクエリパラメータや、リクエストボディに含まれるパラメータを受け取るために使用するアノテーション。
    下記属性を指定できる。

    • name属性・value属性:リクエストパラメータを指定する。nameとvalueの役割に違いはない。
    • required属性:パラメータはデフォルトでは必須になるため、パラメータの指定を任意にする場合、falseを指定する。
    • defaultValue属性:リクエストパラメータが指定されなかった時のデフォルト値を指定する。

    実装例

    @GetMapping(value
    

    @￰PathVariable

    URLに含まれる動的なパラメータを受け取るためのアノテーション。
    @￰RequestParamはクエリパラメータから値を抽出するのに対し、@￰PathVariableはURLパスから値を抽出する。 D実装例

    @GetMapping(value
    

    @￰ControllerAdvice

    クラスに付与することで全てのControllerで共有するメソッドを用意することができるアノテーション。アプリケーション全体で共通化したい例外処理などに使用する。
    以下のアノテーションがついたメソッドのみController間で共有できる。 @￰ExceptionHandler

    メソッドに付与することで例外処理を実装できるアノテーション。
    アノテーションの引数に例外クラスを指定することで、例外毎の処理を用意できる。 @￰InitBinder

    @￰RequestParamや@￰PathVariableなどで受け取った値をオブジェクトにバインド(設定)する際に行う処理を定義できるアノテーション。
    空文字の文字列項目をnullに変換する、文字列の空白を取り除く、といった処理を定義できる。 @￰ModelAttribute

    指定したクラスにリクエストパラメータをバインドするアノテーション。
    メソッドまたはメソッドの引数に付与できる。 SampleController.java

    @RestController
    

    SampleData.java

    @Data
    

    【Serviceクラスに関するアノテーション】

    @￰Transactional

    クラス・メソッドに付与することで、例外が発生すると自動でロールバックされるアノテーション。
    非検査例外(RuntimeException)及びそのサブクラスが発生した場合はロールバック(実行前への巻き戻し)されるが、検査例外(Exception及びそのサブクラスでRuntimeException以外)が発生した場合は、ロールバックされずコミット(処理の確定)される。 【Repositoryクラスに関するアノテーション】

    @￰Data

    クラスに付与することで全フィールドに対してgetter/setterでアクセスすることができるようになるアノテーション。
    hasCode()メソッドやequals()メソッド、toString()メソッドを自動生成してくれる。 @￰Entity

    ​​エンティティクラスであることを示すアノテーション。
    データベースのテーブルとマッピングするクラスにつけつろ、クラス名と同じテーブル名を生成してくれたりする @￰Table

    テーブル名を設定するアノテーション。
    通常はクラス名と同じテーブル名のデータをマッピングするため、クラス名とテーブル名が異なる場合はマッピングしたいテーブル名を設定する。 @￰Id

    フィールドに付与し、主キーであることを示すアノテーション。 @￰Transient

    マッピングしたくない(データベースに保存しない)フィールドに付与するアノテーション。 @￰Query

    メソッドに付与することで任意のSQLを実行できるメソッドを用意できるアノテーション。
    アノテーションの引数にクエリを書く。 @￰Modifying

    @￰Queryアノテーションを使ってinsert・update・deleteをする際に必ず不要する必要があるアノテーション。 実装例

    @Modifying
    

    @￰JoinColumn

    テーブル結合時、条件となる結合先テーブルのカラム名を指定するためのアノテーション。
    結合先の情報となるフィールドに付与する。
    name属性に結合先のキーとなるカラム名を指定する。 @￰OneToOne

    テーブルと結合先テーブルが一対一の関係の場合に付与するアノテーション。 @￰OneToMany

    テーブルと結合先テーブルが一対多の関係の場合に付与するアノテーション。 @￰ManyToOne

    テーブルと結合先テーブルが多対一の関係の場合に付与するアノテーション。 実装例

    @Entity
    

    【バリデーションに関するアノテーション】

    @￰Validated

    バリデーション(入力チェック)を行いたいパラメータ・クラスに付与するアノテーション。 @￰GroupSequence

    バリデーションの実行順を指定するアノテーション。
    左に設定されたものから実行していく。 @￰DataTimeFormat

    フォーマットを指定することで、受け取った値を日付型に変換するアノテーション。 @￰NumberFormat

    フォーマットを指定することで、受け取った値を数値型に変換するアノテーション。 @￰NonNull

    nullでないことをチェックするアノテーション。
    ※空文字・空白はOKになる @￰NotEmpty

    nullまたは空文字でないことをチェックするアノテーション。
    ※空白はOKになる @￰NotBlank

    null・空文字・空白でないことをチェックするアノテーション。 @￰Max

    指定した値以下であるかをチェックするアノテーション。 @￰Min

    指定した値以上であるかをチェックするアノテーション。 @￰Size

    文字列の長さやListのsizeが指定した範囲内になるかチェックするアノテーション。 @￰AssertTrue

    trueかどうかをチェックするアノテーション。 @￰AssertFalse

    falseかどうかをチェックするアノテーション。 @￰Pattern

    指定した正規表現に一致するかをチェックするアノテーション。 SampleData.java

    @Data
    

    SampleController.java

    @RestController
    

    【AOPに関するアノテーション】

    @￰Aspect

    横断的関心事を実装したメソッドであるAdviceを記述するAspectクラスに付与するアノテーション。 @￰Before

    中心的関心事の呼び出し前に実行したいメソッドに付与するアノテーション。 @￰After

    中心的関心事の呼び出し後に実行したいメソッドに付与するアノテーション。 @￰AfterReturning

    中心的関心事が正常終了した後に実行したいメソッドに付与するアノテーション。 @￰Around

    中心的関心事の呼び出し前・呼び出し後に実行したいメソッドに付与するアノテーション。 @￰AfterThrowing

    中心関心事が例外をスローした後に実行するメソッドに付与するアノテーション。 @￰annotation

    指定したアノテーションがついているメソッドを実行対象として指定するアノテーション。 実装例

    // @GetMappingが付与されたメソッドの呼び出し前に実行する
    

    @￰within

    指定したアノテーションがついているクラスの全てのメソッドがAOPの対象となる。 実装例

    // @Controllerが付与されたクラスの全メソッドの呼び出し前に実行する
    

    【セキュリティに関するアノテーション】

    @￰EnableWebSecurity

    クラスに付与することでセキュリティ設定クラスを実装できるアノテーション。
    実装時は、@￰Configurationをクラスに付与すること・WebSecurityConfigurerAdapterクラスを継承する必要がある。

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.