Home > Java > JavaBase > body text

Java uses reflection to convert objects into MongoDb structures

coldplay.xixi
Release: 2020-12-15 17:30:48
forward
3757 people have browsed it

java Basic TutorialThe column introduces how to convert objects into MongoDb structures

Java uses reflection to convert objects into MongoDb structures

Recommended (free): java Basic Tutorial

Reflection is an advanced technique in Java, which is widely used in various open source projects. For example, Spring, Tomcat, Jetty and other projects all use reflection extensively.

As Java programmers, if we use reflection well, we can not only improve our technical level, but also develop better projects.

However, although many people have heard of reflection, they don’t know where they should be used.

So, we will start from the actual work and use reflection to convert the object into MongoDb data structure. After you understand this example, you will understand how reflection is used.

Requirement Analysis

In the e-commerce system, some data must be saved to MongoDb to improve query performance. But before that, we must first convert the data into MongoDb structure, that is, convert Java objects into Documents.

For example, if order information is to be stored in MongoDb, the order object must be converted into a Document.

But in this way, each entity class must develop a 2Doc() method. This method has no technical content, it just puts various fields into the Document. And once there are too many fields, you will write wrong code if you are not careful. You can feel it.

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;
    }
}
Copy after login

In addition, we have to get the data from MongoDb and convert the Document back to a Java object. You can feel it again.

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;
    }
}
Copy after login

Just one order class is so troublesome, not to mention there are more than one such class, and the project always has new requirements. If one field is changed, you will be in big trouble, and you may have to turn over the entire project. Again.

Therefore, in order to reduce errors, these two conversion methods must be optimized, and this optimization uses two advanced features of Java: reflection and generics. In order to give everyone a more intuitive understanding, I will divide it into two version iterations.

The first version uses reflection to simplify the conversion method of entity classes;

The second version uses generics and reflection to extract MongoDb tool classes;

Next, Let’s iterate step by step~

Use reflection to simplify the conversion methods of entity classes

In the first version of iteration, we want to simplify the two conversion methods of entity classes.

Let’s start by converting Java objects to Documents, taking the Order class as an example.

First, we obtain all the field information of the order class through reflection; then, we use a loop to traverse these fields; finally, in the loop, we release the access rights of the fields and put the fields into the Document.

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;
    }
}
Copy after login

You can see that after reflection transformation, the code is much simpler. No matter how many fields an object has or how many put operations need to be written, it can be done with just these few lines of code. Converting Java objects into MongoDb structures seems less cumbersome.

Following this idea, let’s transform the second method, convert Document to Java object.

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;
    }
}
Copy after login

First, we use a loop to traverse the Document; in the loop, use reflection to obtain the corresponding fields, then release the access rights of the fields, and set the value of the Document to the fields of the object.

At this point, we used reflection to simplify the conversion method of the two entity classes, and the first version of iteration is basically completed. The remaining work is to copy and paste and reshape each class.

However, after this iteration, although a lot of work has been reduced, there are still many unreasonable places.

First of all, there are still a lot of duplicate codes. Each entity class has two conversion methods, but the core logic of these two methods is the same, so there is no need to copy them everywhere.

Then, this is not a function that entity classes should undertake. Entity classes are only responsible for temporarily retaining data and are not responsible for any persistence functions. Where you store the data and what data structure it should be converted into has nothing to do with entity classes.

In other words, we have to do a second iteration.

Use generics and reflection to extract MongoDb tool classes

Simply put, generics are a style or paradigm. You don’t need to specify the specific parameter type at the beginning, but use Then determine the parameter type.

If we combine generics and reflection, it can help us reduce a lot of duplicate code.

Let’s see, how to do the second iteration?

Start by converting Java objects to Document. We first declare a generic method; then, through reflection, obtain all field information of the generic class, and then use a loop to traverse these fields; finally, in the loop, put the fields into the 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;
    }
}
Copy after login

After adding generics, duplicate code has been greatly reduced, and entity classes no longer need to write a separate 2Doc() method. When using it, just call MongoDbUtils.obj2Doc().

Following the same idea, we continue to transform the second method, Document to Java object.

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;
    }
}
Copy after login

首先,我们定义实例化一个泛型对象;然后,我们使用循环遍历 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)
Copy after login

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

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

The above is the detailed content of Java uses reflection to convert objects into MongoDb structures. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:segmentfault.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template