简体   繁体   English

Spring没有正确地将对象保存到MongoDB

[英]Spring doesn't save object to MongoDB correctly

Following question has been separated from this one: ArrayIndexOutOfBoundsException while Spring save data to MongoDB 以下问题已与以下问题分开: ArrayIndexOutOfBoundsException,而Spring将数据保存到MongoDB

I have problem with saving Object to MongoDB. 我将Object保存到MongoDB时遇到问题。 I've noticed that problem might be caused by too complex object. 我注意到这个问题可能是由太复杂的对象引起的。 I have following class hierarchy: 我有以下类层次结构: 在此输入图像描述

ClassA is superclass for ClassB and ClassC . ClassAClassBClassC超类。 ClassD contains map of maps. ClassD包含地图的地图。 ClassC contains ClassB . ClassC包含ClassB

Code which I invoke is following: 我调用的代码如下:

ClassC c = new ClassC()
c.setName("NAME");
mongoOperation.save(c, "Mongo"); // MongoOperations object

The problem is that Mongo doesn't save object's data. 问题是Mongo不保存对象的数据。 It saves only _id and _class . 它只保存_id_class

Actual data 实际数据

{
    "_id" : ObjectId("53e86cd9c506f66eafaa03cb"),
    "_class" : "com.sample.ClassC"
}

Expected data 预期数据

{
    "_id" : ObjectId("53e86cd9c506f66eafaa03cb"),
    "_class" : "com.sample.ClassC",
    "name" : "NAME"
}

Funny thing is that when I comment out map field in ClassD everything works fine. 有趣的是,当我在ClassD注释掉地图字段时,一切正常。

Is it possible to be caused by too complex object which I try to serialize? 是否有可能是由于我试图序列化的太复杂的对象造成的?


EDIT 编辑

When I remove bObject from ClassC it also works fine. 当我从ClassC删除bObject ,它也可以正常工作。


EDIT 2 编辑2

All classes are simple beans with setters and getters. 所有类都是带有setter和getter的简单bean。

eg 例如

public class ClassD{

    private TreeMap<String, TreeMap<String,String>> map;

    public TreeMap<String, TreeMap<String, String>> getMap() {
        return map;
    }

    public void setMap(TreeMap<String, TreeMap<String, String>> map) {
        this.map = map;
    }
}

EDIT 3 编辑3

Full example below, it has same class hierarchy as picture above. 下面的完整示例,它具有与上图相同的类层次结构。

public class Application implements CommandLineRunner {

    @Autowired
    private MongoTemplate mongoTemplate;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        ClassC cObject = new ClassC();
        cObject.setName("Jon");
        try {
            mongoTemplate.save(cObject);
        }catch(Exception e){
            e.printStackTrace();
        }
        mongoTemplate.save(cObject);
    }
}


class ClassA{

    private String name;

    private ClassD dObject;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public ClassD getdObject() {
        return dObject;
    }

    public void setdObject(ClassD dObject) {
        this.dObject = dObject;
    }
}

class ClassB extends ClassA {
}

class ClassC extends ClassA {
    private ClassB b;

    public ClassB getB() {
        return b;
    }

    public void setB(ClassB b) {
        this.b = b;
    }
}

class ClassD {

    private TreeMap<String, TreeMap<String, String>> map = new TreeMap<>();

    public TreeMap<String, TreeMap<String, String>> getMap() {
        return map;
    }
    public void setMap(TreeMap<String, TreeMap<String, String>> map) {
        this.map = map;
    }

}

The following code seems to work: 以下代码似乎有效:

@EnableAutoConfiguration
public class Application implements CommandLineRunner {

    @Autowired
    private MongoTemplate mongoTemplate;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        Customer customer = new Customer("myself");
        ClassB classB = new ClassB();
        TreeMap<String, TreeMap<String, String>> map =  new TreeMap<String, TreeMap<String, String>>();
        TreeMap<String, String> innermap = new TreeMap<String, String>();
        innermap.put("iam", "cool");
        map.put("innermap", innermap);
        TreeMap<String, String> innermap2 = new TreeMap<String, String>();
        innermap2.put("youare", "yellow");
        map.put("innermap2", innermap2);
        classB.setMap(map);
        customer.setClassB(classB);
        try {
            mongoTemplate.save(customer);
        } catch (Exception e) {
            e.printStackTrace();
        }
        mongoTemplate.save(customer);
        System.out.println(mongoTemplate.findAll(Customer.class));;
    }
}


public class ClassB {

    private TreeMap<String, TreeMap<String, String>> map = new TreeMap<String, TreeMap<String, String>>();

    public TreeMap<String, TreeMap<String, String>> getMap() {
        return map;
    }

    public void setMap(TreeMap<String, TreeMap<String, String>> map) {
        this.map = map;
    }
}


@Document(collection ="customer")
public class Customer {

    @Id
    private String id;

    private String name;

    private ClassB classB;

    public Customer() {
    }

    public Customer(String name) {
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public ClassB getClassB() {
        return classB;
    }

    public void setClassB(ClassB classB) {
        this.classB = classB;
    }

    @Override
    public String toString() {
        return "Customer [id=" + id + ", name=" + name + ", classB=" + classB
                + "]";
    }

}

But the ArrayIndexOutOfBoundsException-issue is still present. ArrayIndexOutOfBoundsException问题仍然存在。

I guess the MongoConverter in specific version of your spring-data-mongodb.jar works incorrectly. 我猜MongoConverter在弹簧数据mongodb.jar的特定版本的作品不正确。 Spring must convert your ClassC instance into DBObject format, then call DBCollection.save to save data into database. Spring必须将ClassC实例转换为DBObject格式,然后调用DBCollection.save将数据保存到数据库中。 You can check the content of DBObject parameter in method "com.mongodb.DBCollection.save" whether it contains correct data as you expect. 您可以在方法"com.mongodb.DBCollection.save"检查DBObject参数的内容, DBObject它是否包含您期望的正确数据。

I copy your ClassC with complete structure and test, it's fine and cannot reproduce what you described above. 我复制你的ClassC完整的结构和测试,它很好,不能重现你上面描述的。 I use spring-data-mongdb-1.2.3-RELEASE.jar. 我使用spring-data-mongdb-1.2.3-RELEASE.jar。 What's the version you adopt? 你采用的是什么版本?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM