ホームページ  >  記事  >  Java  >  Java はリフレクションを使用してオブジェクトを MongoDb 構造に変換します

Java はリフレクションを使用してオブジェクトを MongoDb 構造に変換します

coldplay.xixi
coldplay.xixi転載
2020-12-15 17:30:483749ブラウズ

java 基本チュートリアルこのコラムでは、オブジェクトを MongoDb 構造に変換する方法を紹介します

Java はリフレクションを使用してオブジェクトを MongoDb 構造に変換します

推奨 (無料): java 基本チュートリアル

リフレクションは Java の高度な技術であり、さまざまなオープンソース プロジェクトで広く使用されています。たとえば、Spring、Tomcat、Jetty、その他のプロジェクトはすべてリフレクションを広範囲に使用しています。

Java プログラマとしてリフレクションをうまく活用すれば、技術レベルを向上させるだけでなく、より良いプロジェクトを開発することもできます。

しかし、多くの人はリフレクションについて聞いたことはあっても、それをどこで使用すべきかは知りません。

そこで、実際の作業から始めて、リフレクションを使用してオブジェクトを MongoDb データ構造に変換します。この例を理解すると、リフレクションがどのように使用されるかが理解できるようになります。

要件分析

電子商取引システムでは、クエリのパフォーマンスを向上させるために、一部のデータを MongoDb に保存する必要があります。ただし、その前に、まずデータを MongoDb 構造に変換する必要があります。つまり、Java オブジェクトをDocuments に変換する必要があります。

たとえば、注文情報を MongoDb に保存する場合、注文オブジェクトを Document に変換する必要があります。

ただし、この方法では、各エンティティ クラスが 2Doc() メソッドを開発する必要があります。このメソッドには技術的な内容はなく、ドキュメントにさまざまなフィールドを挿入するだけです。また、フィールドが多すぎると、注意しないと間違ったコードを書いてしまいます。

public class Order {
    private Long id;
    private Long userId;
    private String orderNo;
    private BigDecimal amount;
    private String createTime;
    private String updateTime;
    // 省略无数字段
    
    // 转换方法:订单转doc
    public Document order2Doc(Order order) {
        Document doc = new Document();

        doc.put("id", order.getId());
        doc.put("userId", order.getUserId());
        doc.put("orderNo", order.getOrderNo());
        doc.put("amount", order.getAmount());
        doc.put("createTime", order.getCreateTime());
        doc.put("updateTime", order.getUpdateTime());
        // 省略无数put...

        return doc;
    }
}

さらに、MongoDb からデータを取得し、Document を Java オブジェクトに変換し直す必要があります。

public class Order {
    private Long id;
    private Long userId;
    private String orderNo;
    private BigDecimal amount;
    private String createTime;
    private String updateTime;
    // 省略无数字段
    
    // 转换方法:doc转订单
    public Order doc2Order(Document doc) {
        Order order = new Order();
        
        order.setId((Long) doc.get("id"));
        order.setUserId((Long) doc.get("userId"));
        order.setOrderNo((String) doc.get("orderNo"));
        order.setAmount((BigDecimal) doc.get("amount"));
        order.setCreateTime((String) doc.get("createTime"));
        order.setUpdateTime((String) doc.get("updateTime"));
        // 省略无数set...

        return order;
    }
}

注文クラスが 1 つだけでも非常に面倒です。言うまでもなく、そのようなクラスは複数あり、プロジェクトには常に新しい要件があります。1 つのフィールドが変更されると、大きな問題が発生し、場合によってはプロジェクト全体を引き返さなければなりません。

したがって、エラーを減らすために、これら 2 つの変換メソッドを最適化する必要があります。この最適化では、Java の 2 つの高度な機能、リフレクションとジェネリックを使用します。誰もがより直感的に理解できるように、2 つのバージョンに分けて説明します。

最初のバージョンでは、リフレクションを使用してエンティティ クラスの変換方法を簡素化しています。

2 番目のバージョンでは、ジェネリックスとリフレクションを使用して MongoDb ツール クラスを抽出しています。

次のステップを繰り返してみましょうステップごとに ~

リフレクションを使用してエンティティ クラスの変換メソッドを簡素化する

反復の最初のバージョンでは、エンティティ クラスの 2 つの変換メソッドを簡素化します。

Order クラスを例として、Java オブジェクトをDocuments に変換することから始めましょう。

最初に、オーダー クラスのすべてのフィールド情報をリフレクションを通じて取得します。次に、ループを使用してこれらのフィールドを走査します。最後に、ループ内でフィールドのアクセス権を解放し、フィールドを文書。

public class Order {
    // ...省略无数字段

    public Document order2Doc(Order order) throws Exception {
        Document doc = new Document();

        // 获取所有字段:通过 getClass() 方法获取 Class 对象,然后获取这个类所有字段
        Field[] fields = order.getClass().getDeclaredFields();
        for (Field field : fields) {
            // 开放字段操作权限
            field.setAccessible(true);
            // 设置值
            doc.put(field.getName(), field.get(order));
        }

        return doc;
    }
}

リフレクション変換後のコードは非常に単純になっていることがわかります。オブジェクトにいくつのフィールドがあるか、またはいくつの put 操作を記述する必要があるかに関係なく、わずか数行のコードで実行できます。 Java オブジェクトを MongoDb 構造に変換するのはそれほど面倒ではないようです。

このアイデアに従って、2 番目のメソッドを変換して、Document を Java オブジェクトに変換しましょう。

public class Order {
    // ...省略无数字段

    public Order doc2Order(Document doc) throws Exception {
        Order order = new Order();

        for (String key : doc.keySet()) {
            // 获取字段
            Field field = order.getClass().getDeclaredField(key);
            // 开放字段操作权限
            field.setAccessible(true);
            // 设置值
            field.set(order, doc.get(key));
        }

        return order;
    }
}

まず、ループを使用してドキュメントを走査します。ループ内で、リフレクションを使用して対応するフィールドを取得し、フィールドのアクセス権を解放し、ドキュメントの値を次のフィールドに設定します。オブジェクト。

この時点で、リフレクションを使用して 2 つのエンティティ クラスの変換メソッドを簡素化し、反復の最初のバージョンが基本的に完了しました。残りの作業は、各クラスをコピーして貼り付けて再形成することです。

しかし、この繰り返しを経て、かなり仕事は減りましたが、まだまだ無理なところがたくさんあります。

まず第一に、重複したコードがまだたくさんあります。各エンティティ クラスには 2 つの変換メソッドがありますが、これら 2 つのメソッドのコア ロジックは同じであるため、どこにでもコピーする必要はありません。

したがって、これはエンティティ クラスが引き受けるべき機能ではありません。エンティティ クラスはデータを一時的に保持することのみを担当し、永続化機能は担当しません。データをどこに保存するか、どのデータ構造に変換するかは、エンティティ クラスとは関係ありません。

つまり、2 回目の反復を行う必要があります。

ジェネリックとリフレクションを使用して MongoDb ツール クラスを抽出する

簡単に言うと、ジェネリックはスタイルまたはパラダイムです。最初に特定のパラメーターの型を指定する必要はありませんが、その後の決定を使用します。パラメータのタイプ。

ジェネリックとリフレクションを組み合わせると、多くの重複コードを減らすことができます。

2 回目の反復をどのように行うか見てみましょう。

まず、Java オブジェクトをドキュメントに変換します。まずジェネリック メソッドを宣言し、次にリフレクションを通じてジェネリック クラスのすべてのフィールド情報を取得し、ループを使用してこれらのフィールドを走査し、最後にループ内でフィールドを Document に配置します。

public class MongoDbUtils {

    // 定义泛型方法:
    // 1. 在返回值前,声明泛型参数 <参数名>;
    // 2. 传入参数时,指定一个泛型参数
    public static <T> Document obj2Doc(T obj) throws Exception {
        Document doc = new Document();

        // 获取所有字段:通过 getClass() 方法获取 Class 对象,然后获取这个类所有字段
        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field field : fields) {
            // 开放字段操作权限
            field.setAccessible(true);
            // 设置值
            doc.put(field.getName(), field.get(obj));
        }

        return doc;
    }
}

ジェネリックスを追加すると、重複コードが大幅に減り、エンティティ クラスで別の 2Doc() メソッドを記述する必要がなくなりました。使用する場合は、MongoDbUtils.obj2Doc() を呼び出すだけです。

同じ考え方に従って、2 番目のメソッドである Document を Java オブジェクトに変換します。

public class MongoDbUtils {

    // 定义泛型方法:
    // 1. 在返回值前,声明泛型参数 <参数名>;
    // 2. 传入参数必须是 Class,但这个 Class 是泛型参数,不限制类型
    public static <T> T doc2Obj(Document doc, Class<T> clazz) throws Exception {
        // 实例化泛型对象
        T obj = clazz.newInstance();

        for (String key : doc.keySet()) {
            // 获取字段
            Field field = clazz.getDeclaredField(key);
            // 开放字段操作权限
            field.setAccessible(true);
            // 设置值
            field.set(obj, doc.get(key));
        }

        return obj;
    }
}

首先,我们定义实例化一个泛型对象;然后,我们使用循环遍历 Document;最后,在循环中,使用反射获取相应的字段,把 Document 的值设置到泛型对象的字段里。

第二版的迭代就基本完成了。我们在第一版迭代的基础上,加入了泛型,得到了一个工具类 MongoDbUtils,这个工具类得到结果和以前完全一样,你可以看下测试代码。

public static void main(String[] args) throws Exception {
    Order order = new Order();
    order.setId(0L);
    order.setUserId(0L);
    order.setOrderNo("1");
    order.setAmount(new BigDecimal("0"));
    order.setCreateTime("2");
    order.setUpdateTime("3");
    System.out.println("原始数据:" + order);

    Document document = MongoDbUtils.obj2Doc(order);
    System.out.println("转换doc数据:" + document);

    Order order1 = MongoDbUtils.doc2Obj(document, Order.class);
    System.out.println("转换java数据:" + order1);
}

运行结果:
原始数据:Order(id=0, userId=0, orderNo=1, amount=0, createTime=2, updateTime=3)
转换doc数据:Document{{id=0, userId=0, orderNo=1, amount=0, createTime=2, updateTime=3}}
转换java数据:Order(id=0, userId=0, orderNo=1, amount=0, createTime=2, updateTime=3)

这样一来,我们就不用保留实体类上的转换方法了,剩下的工作就是删代码。

MongoDb 和 Java 对象的互相转换就完成了。我们做了两次迭代,第一次迭代利用了反射,把大量手动 set/get 操作给去掉了;第二次迭代在原来的基础上,加入了泛型的应用,又去掉了一堆重复代码。

以上がJava はリフレクションを使用してオブジェクトを MongoDb 構造に変換しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。