Java SQL アダプター

improve this page | report issue

概説

Java アダプターは、バックエンド・システムへの接続に対する制御権を開発者に与えます。 したがって、開発者の責任で、パフォーマンスおよびその他の実装の詳細についてのベスト・プラクティスを実現する必要があります。 このチュートリアルでは、MySQL バックエンドに接続し、REST 概念を使用して users テーブルに対する CRUD (作成、読み取り、更新、削除) 操作を行う Java アダプターの例を取り上げます。

前提条件:

  • 最初に必ず、 Java アダプターチュートリアルをお読みください。
  • このチュートリアルでは、SQL の知識があることを前提としています。

ジャンプ先

データ・ソースのセットアップ

MySQL サーバーに接続できるように MobileFirst Server を構成するには、構成プロパティーを使用してアダプターの XML ファイルを構成する必要があります。 これらのプロパティーは、後で MobileFirst Operations Console で編集できます。

adapter.xml ファイルを編集して、以下のプロパティーを追加します。

<mfp:adapter name="JavaSQL"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:mfp="http://www.ibm.com/mfp/integration"
	xmlns:http="http://www.ibm.com/mfp/integration/http">

	<displayName>JavaSQL</displayName>
	<description>JavaSQL</description>

	<JAXRSApplicationClass>com.sample.JavaSQLApplication</JAXRSApplicationClass>

	<property name="DB_url" displayName="Database URL" defaultValue="jdbc:mysql://127.0.0.1:3306/mobilefirst_training"  />
	<property name="DB_username" displayName="Database username" defaultValue="mobilefirst"  />
	<property name="DB_password" displayName="Database password" defaultValue="mobilefirst"  />
</mfp:adapter>

注: 構成プロパティー・エレメントは、必ず JAXRSApplicationClass エレメントの下に 配置する必要があります。
ここでは、デフォルト値を指定して接続設定を定義し、これらの接続設定を後で AdapterApplication クラスで使用できるようにしてあります。

アダプター・リソース・クラスへの SQL の実装

アダプター・リソース・クラスは、サーバーに対する要求を処理する場所です。

提供されているサンプル・アダプターでは、クラス名は JavaSQLResource です。

@Path("/")
  public class JavaSQLResource {
}

@Path("/") は、URL http(s)://host:port/ProjectName/adapters/AdapterName/ でリソースが使用可能であることを意味します。

DataSource の使用

アダプターをデプロイするとき、または MobileFirst Operations Consoleから構成を変更するたびに、アダプターの MFPJAXRSApplicationinit メソッドが呼び出されます。 これは、接続プロパティーをロードして DataSource を作成するのに適しています。

public class JavaSQLApplication extends MFPJAXRSApplication{

	public BasicDataSource dataSource = null;

	@Context
	ConfigurationAPI configurationAPI;

	@Override
	protected void init() throws Exception {		
		dataSource= new BasicDataSource();
		dataSource.setDriverClassName("com.mysql.jdbc.Driver");
		dataSource.setUrl(configurationAPI.getPropertyValue("DB_url"));
		dataSource.setUsername(configurationAPI.getPropertyValue("DB_username"));
		dataSource.setPassword(configurationAPI.getPropertyValue("DB_password"));
	}
}

リソース・クラスでは、ヘルパー・メソッドを作成して SQL 接続を取得します。 AdaptersAPI を使用して、現行の MFPJAXRSApplication インスタンスを取得します。

@Context
AdaptersAPI adaptersAPI;

public Connection getSQLConnection() throws SQLException{
  // Create a connection object to the database
  JavaSQLApplication app = adaptersAPI.getJaxRsApplication(JavaSQLApplication.class);
  return app.dataSource.getConnection();
}

ユーザーの作成

データベースに新規ユーザー・レコードを作成する場合に使用します。

@POST
public Response createUser(@FormParam("userId") String userId,
                            @FormParam("firstName") String firstName,
                            @FormParam("lastName") String lastName,
                            @FormParam("password") String password)
                                    throws SQLException{

    Connection con = getSQLConnection();
    PreparedStatement insertUser = con.prepareStatement("INSERT INTO users (userId, firstName, lastName, password) VALUES (?,?,?,?)");

    try{
        insertUser.setString(1, userId);
        insertUser.setString(2, firstName);
        insertUser.setString(3, lastName);
        insertUser.setString(4, password);
        insertUser.executeUpdate();
        //Return a 200 OK
        return Response.ok().build();
    }
    catch (SQLIntegrityConstraintViolationException violation) {
        //Trying to create a user that already exists
        return Response.status(Status.CONFLICT).entity(violation.getMessage()).build();
    }
    finally{
        //Close resources in all cases
        insertUser.close();
        con.close();
    }  
}

このメソッドでは @Path が指定されていないため、リソースのルート URL としてアクセスできます。 これは、@POST を使用するため、HTTP POST 経由でのみアクセス可能になります。
このメソッドには一連の @FormParam 引数があります。これは、これらの引数を HTTP 本体で x-www-form-urlencoded パラメーターとして送信できることを意味します。

また、@Consumes(MediaType.APPLICATION_JSON) を使用して、HTTP 本体でパラメーターを JSON オブジェクトとして渡すこともできます。この場合、メソッドには、JSONObject 引数か、JSON プロパティー名と一致するプロパティーが指定された単純 Java オブジェクトが必要です。

Connection con = getSQLConnection(); メソッドは、以前に定義されたデータ・ソースからの接続を取得します。

SQL 照会は PreparedStatement メソッドによってビルドされます。

挿入が成功した場合は、return Response.ok().build() メソッドを使用して、クライアントに 200 OK を返します。 エラーが発生した場合は、特定の HTTP 状況コードを持つ別の Response オブジェクトをビルドすることができます。 この例では、409 Conflict エラー・コードが送られます。 すべてのパラメーターが送信されているかどうかや (ここでは示されていません)、その他のデータ検証についても確認することをお勧めします。

重要: リソース (作成されたステートメントや接続など) を必ず閉じてください。

ユーザーの取得

データベースからユーザーを取得します。

@GET
@Produces("application/json")
@Path("/{userId}")
public Response getUser(@PathParam("userId") String userId) throws SQLException{
    Connection con = getSQLConnection();
    PreparedStatement getUser = con.prepareStatement("SELECT * FROM users WHERE userId = ?");

    try{
        JSONObject result = new JSONObject();

        getUser.setString(1, userId);
        ResultSet data = getUser.executeQuery();

        if(data.first()){
            result.put("userId", data.getString("userId"));
            result.put("firstName", data.getString("firstName"));
            result.put("lastName", data.getString("lastName"));
            result.put("password", data.getString("password"));
            return Response.ok(result).build();

        } else{
            return Response.status(Status.NOT_FOUND).entity("User not found...").build();
        }

    }
    finally{
        //Close resources in all cases
        getUser.close();
        con.close();
    }

}

このメソッドでは、@Path("/{userId}") を指定した @GET を使用します。つまり、HTTP GET /adapters/UserAdapter/{userId} 経由でメソッドが使用可能になります。また、{userId} は、メソッドの @PathParam("userId") 引数で取得されます。

ユーザーが検出されない場合は 404 NOT FOUND エラー・コードが返されます。
ユーザーが検出されると、生成された JSON オブジェクトから応答がビルドされます。

メソッドの前に @Produces("application/json") を指定することで、出力の Content-Type が正しいことを確認します。

すべてのユーザーの取得

このメソッドは、ResultSet をループする以外は、getUser と同じです。

@GET
@Produces("application/json")
public Response getAllUsers() throws SQLException{
    JSONArray results = new JSONArray();
    Connection con = getSQLConnection();
    PreparedStatement getAllUsers = con.prepareStatement("SELECT * FROM users");
    ResultSet data = getAllUsers.executeQuery();

    while(data.next()){
        JSONObject item = new JSONObject();
        item.put("userId", data.getString("userId"));
        item.put("firstName", data.getString("firstName"));
        item.put("lastName", data.getString("lastName"));
        item.put("password", data.getString("password"));

        results.add(item);
    }

    getAllUsers.close();
    con.close();

    return Response.ok(results).build();
}

ユーザーの更新

データベース内のユーザー・レコードを更新します。

@PUT
@Path("/{userId}")
public Response updateUser(@PathParam("userId") String userId,
                            @FormParam("firstName") String firstName,
                            @FormParam("lastName") String lastName,
                            @FormParam("password") String password)
                                    throws SQLException{
    Connection con = getSQLConnection();
    PreparedStatement getUser = con.prepareStatement("SELECT * FROM users WHERE userId = ?");

    try{
        getUser.setString(1, userId);
        ResultSet data = getUser.executeQuery();

        if(data.first()){
            PreparedStatement updateUser = con.prepareStatement("UPDATE users SET firstName = ?, lastName = ?, password = ? WHERE userId = ?");

            updateUser.setString(1, firstName);
            updateUser.setString(2, lastName);
            updateUser.setString(3, password);
            updateUser.setString(4, userId);

            updateUser.executeUpdate();
            updateUser.close();
            return Response.ok().build();


        } else{
            return Response.status(Status.NOT_FOUND).entity("User not found...").build();
        }
    }
    finally{
        //Close resources in all cases
        getUser.close();
        con.close();
    }

}

既存のリソースの更新時には @PUT (HTTP PUT の場合) を使用して、@Path でリソース ID を使用する手法が標準的です。

ユーザーの削除

データベースからユーザー・レコードを削除します。

@DELETE
@Path("/{userId}")
public Response deleteUser(@PathParam("userId") String userId) throws SQLException{
    Connection con = getSQLConnection();
    PreparedStatement getUser = con.prepareStatement("SELECT * FROM users WHERE userId = ?");

    try{
        getUser.setString(1, userId);
        ResultSet data = getUser.executeQuery();

        if(data.first()){
            PreparedStatement deleteUser = con.prepareStatement("DELETE FROM users WHERE userId = ?");
            deleteUser.setString(1, userId);
            deleteUser.executeUpdate();
            deleteUser.close();
            return Response.ok().build();

        } else{
            return Response.status(Status.NOT_FOUND).entity("User not found...").build();
        }
    }
    finally{
        //Close resources in all cases
        getUser.close();
        con.close();
    }

}

@DELETE (HTTP DELETE の場合) は、ユーザーを削除するために @Path でリソース ID と一緒に使用されます。

サンプル・アダプター

ここをクリック してアダプター Maven プロジェクトをダウンロードします。

アダプター Maven プロジェクトには、前に説明した JavaSQL アダプターが含まれています。
また、Utils フォルダーに SQL スクリプトも含まれています。

使用例

Inclusive terminology note: The Mobile First Platform team is making changes to support the IBM® initiative to replace racially biased and other discriminatory language in our code and content with more inclusive language. While IBM values the use of inclusive language, terms that are outside of IBM's direct influence are sometimes required for the sake of maintaining user understanding. As other industry leaders join IBM in embracing the use of inclusive language, IBM will continue to update the documentation to reflect those changes.
Last modified on February 28, 2020