0

私は次のインターフェースを持っています:

public interface Mapper {

    public SomeType methodOne(HashMap<String, Object>);

    public OtherType methodTwo(HashMap<String, Object>);

    ...
}

methodOne次に、またはmethodTwo別のクラス内のパラメーターとして呼び出すことは可能ですか?

public class Other {
    public void doSomething(HashMap<String, Object> params, ????) {
        Mapper mapper = new ConcreteMapper();
        mapper.methodOne(params);
    }
}

Java リフレクションを試しましたがHashMap<String, Object>、コンパイル時に の型を取得できませんでした。この問題を回避する方法はありますか?
動機は、私が職場で遭遇した実際の問題から来ています。たとえば、各RESTメソッド呼び出しで異なるのはgetAddressPhoneとだけですAddressPhoneType。SQL セッションを開く、インスタンス化するなどのノイズの多い手順Mapperは、基本的に同じです。

public Response getAddressPhone(@PathParam("acc_nbr") String accNbr, @HeaderParam("AuthToken") String authToken) {
    SqlSession session = ConnectionFactory.getSqlSessionFactory().openSession();
    Logger log = LoggerFactory.getLoggerFactory();
    AddressPhoneType addressPhone = null;
    try {
        MyAccountMapper mapper = session.getMapper(MyAccountMapper.class);
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("acc_nbr", accNbr);
        addressPhone = mapper.getAddressPhone(map);
        if (addressPhone == null) {
            return Response.ok(null).status(Status.NOT_FOUND).build();
        }
    } catch (Exception e) {
        log.debug("getAddressPhone(map):" + e.getMessage());
        return Response.ok().status(Status.BAD_REQUEST).build();
    } finally {
        session.close();
    }
    return Response.ok(gson.toJson(addressPhone)).header("AuthToken", authToken).status(Status.OK).build();
}

EDIT MyBatisマッパーを 使用して MySql クエリを実行しているため、次のインターフェイスが呼び出されMyAccountMapperます。これらのメソッドはそれぞれ SQL クエリの id でマッピングされるため、定義はありません。

public interface MyAccountMapper {

    AddressPhoneType getAddressPhone(HashMap<String, Object> map);

    AdminUserInfoType getAdminUserInfo(HashMap<String, Object> map);

    DueDateInfoType getDueDateInfo(HashMap<String, Object> map);
    ....
}

今、すべての Web サービス呼び出し (私は JAX-RS を使用しています) で、これらのメソッドを呼び出してデータベースで何かを行う必要があります。上記の例からわかるように、マッパーのセットアップ、ロガーの作成などのほとんどのもの同じだ。唯一の違いは、メソッド呼び出しと戻り値の型です。

@GET
@Path("/admin/user/info/{acc_nbr}")
@Produces("application/json")
public Response getAdminUserInfo(@PathParam("acc_nbr") String accNbr) {
    SqlSession session = ConnectionFactory.getSqlSessionFactory().openSession();
    AdminUserInfoType adminUserInfoType = null;
    Logger log = LoggerFactory.getLoggerFactory();
    try {
        MyAccountMapper mapper = session.getMapper(MyAccountMapper.class);
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("acc_nbr", accNbr);
        adminUserInfoType = mapper.getAdminUserInfo(map);
        if (adminUserInfoType == null) {
            return Response.ok(gson.toJson(null)).status(Status.NOT_FOUND).build();
        }
    } catch (Exception e) {
        log.debug("getAdminUserInfo(map):" + e.getMessage());
        return Response.ok("getAdminUserInfo(map):"+ MyBatisErrorMessage.SELECT_ERROR).status(Status.BAD_REQUEST).build();
    } finally {
        session.close();
    }
    return Response.ok(gson.toJson(adminUserInfoType)).status(Status.OK).build();
}

@GET
@Path(value = "/address/phone/{acc_nbr}")
@Produces(MediaType.APPLICATION_JSON)
public Response getAddressPhone(@PathParam("acc_nbr") String accNbr,
        @HeaderParam("AuthToken") String authToken) {
    SqlSession session = ConnectionFactory.getSqlSessionFactory().openSession();
    Logger log = LoggerFactory.getLoggerFactory();
    AddressPhoneType addressPhone = null;
    try {
        MyAccountMapper mapper = session.getMapper(MyAccountMapper.class);
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("acc_nbr", accNbr);
        addressPhone = mapper.getAddressPhone(map);
        if (addressPhone == null) {
            return Response.ok(null).status(Status.NOT_FOUND).build();
        }
    } catch (Exception e) {
        log.debug("getAddressPhone(map):" + e.getMessage());
        return Response.ok("getAddressPhone(map):"+ MyBatisErrorMessage.SELECT_ERROR).status(Status.BAD_REQUEST).build();
    } finally {
        session.close();
    }
    return Response.ok(gson.toJson(addressPhone)).header("AuthToken", authToken).status(Status.OK).build();
}
4

4 に答える 4

2
public interface Method {
  public Object invoke(Map<> params);
}

public void invokeTheMethod(Map<> params, Method method) {
  // ... do common work here ...
  Object result = method.invoke(params);
  // ... handle result here ...
}

// run common invoker with Mapper.methodOne
invokeTheMethod(params, new Method() {
  public Object invoke(Map<> params) {
    return mapper.methodOne(params);
  });
于 2013-06-27T02:34:11.263 に答える
1

関数は Java のオブジェクトではないため (少なくともまだ)、単純な方法でやりたいことを実行することはできません。

戻り値を破棄してもかまわない場合 ( で行っているようにOther.doSomething)、インターフェイスといくつかの実装で問題を解決できます。実装はシングルトンにすることができます。

interface MethodCaller {
    void callMethod(HashMap<String, Object> args, Mapper mapper);
    MethodCaller methodOneCaller = new MethodCaller() {
        @Override
        public void callMethod(HashMap<String, Object> args, Mapper mapper) {
            mapper.methodOne(args);
        }
    }
    MethodCaller methodTwoCaller = new MethodCaller() {
        @Override
        public void callMethod(HashMap<String, Object> args, Mapper mapper) {
            mapper.methodTwo(args);
        }
    }
}

次に、呼び出し元の 1 つを使用したい人に渡すことができます。

public class Other {
    public void doSomething(HashMap<String, Object> params, MethodCaller caller) {
        Mapper mapper = new ConcreteMapper();
        caller.callMethod(params, mapper);
    }
}

Other other = . . .;
HashMap<String, Object> stuff = . . .;
other.doSomething(stuff, MethodCaller.methodOneCaller);
other.doSomething(stuff, MethodCaller.methodTwoCaller);
于 2013-06-27T02:34:09.703 に答える
1

具体的なインスタンスを指定して、リフレクションを使用していずれかのメソッドを呼び出す方法は次のとおりです。

    Mapper concreteMapper = new ConcreteMapper();

    Method method1 = concreteMapper.getClass().getMethod("methodOne", HashMap.class);
    Method method2 = concreteMapper.getClass().getMethod("methodTwo", HashMap.class);

    method1.invoke(concreteMapper, new HashMap<String, Object>());
    method2.invoke(concreteMapper, new HashMap<String, Object>());

しかし、ボイラー プレート コードを避けようとしている場合は、コマンド パターンのようなものを使用することを検討してください。または、Spring を使用している場合、これは AOP の適切な使用例になります。

于 2013-06-27T02:34:24.870 に答える
1

マッパー ファクトリが必要であり、マッパー インターフェイスも変更する必要があると思います。

public interface Mapper {
    public SomeType method(HashMap<String, Object> map);
}

public class MapperFactory {
    public static Mapper createMapper(some parameters here) {
        // create a mapper according to the parameters.
    }
}

// usage within another class
public class Other {
    public void doSomething(HashMap<String, Object> params, ????) {
        Mapper mapper = new MapperFactory.createMapper(......);
        mapper.method(params);
    }
}
于 2013-06-27T02:36:46.793 に答える