首页 > 解决方案 > Spring Data MongoRepository 保存具有不同字段数的对象

问题描述

我将游戏状态存储在 MongoDB 数据库中,并使用 Spring Data 来管理我的数据库交互。我是 Spring Data 的新手,不确定如何处理以下情况。

我有一个“游戏”类型的文档,其中包含一些属性,例如 id、时间戳等……其中一个属性是用户采取的操作列表。这些动作的形式为:

{ type: 2 }, {type: 3, value: 4}, {type: 5, id: 1234}, {type 6}, {type: 5, value: 6, id: 56}

换句话说,一个动作可以具有三个属性:类型、值和id。但是,并非每个操作都需要存储所有三个值。我想避免在我的数据库中有一堆空值,并且希望我的数据库不包含和 id 或未指定的值。

使用 Spring Data 的 MongoRepository 模型,我不确定如何实现这一点。我可以创建一个 CRUD Game 类,并使其属性之一是 Action 列表(其中 Action 本身是一个具有属性 type、value 和 id 的 CRUD 类),但最终不会在数据库中存储空值,如果我没有指定值或id?

简而言之,我怎样才能使用 Spring Data 的 MongoRepository,但仍然保持能够存储具有不同参数或对象类型的对象列表的灵活性。

标签: springmongodbspring-datamongotemplatemongorepository

解决方案


我将通过一个示例来解释如何处理不同的字段。以下Game.javaPOJO 类表示到game集合文档的对象映射。

public class Game {

    String name;
    List<Actions> actions;

    public Game(String name, List<Actions> actions) {
        this.name = name;
        this.actions = actions;
    }

    public String getName() {
        return name;
    }

    public List<Actions> getActions() {
        return actions;
    }

    // other get/set methods, override, etc..


    public static class Actions {

        Integer id;
        String type;

        public Actions() {
        }

        public Actions(Integer id) {
            this.id = id;
        }

        public Actions(Integer id, String type) {
            this.id = id;
            this.type = type;
        }

        public Integer getId() {
            return id;
        }

        public String getType() {
            return type;
        }

        // other methods
    }
}

对于Actions该类,您需要为构造函数提供可能的组合。使用适当的构造函数和id,type等。例如,创建一个Game对象并保存到数据库:

Game.Actions actions= new Game.Actions(new Integer(1000));
Game g1 = new Game("G-1", Arrays.asList(actions));
repo.save(g1);

这存储在数据库集合game中,如下所示(从mongoshell 查询):

{
        "_id" : ObjectId("5eeafe2043f875621d1e447b"),
        "name" : "G-1",
        "actions" : [
                {
                        "_id" : 1000
                }
        ],
        "_class" : "com.example.demo.Game"
}

注意actions数组。由于我们只存储id了对象中的字段,因此Game.Actions只存储了该字段。即使您指定了类中的所有字段,也只会保留那些提供值的字段。

这是另外两个文档,Game.Actionstype使用并id + type使用适当的构造函数创建:

{
        "_id" : ObjectId("5eeb02fe5b86147de7dd7484"),
        "name" : "G-9",
        "actions" : [
                {
                        "type" : "type-x"
                }
        ],
        "_class" : "com.example.demo.Game"
}
{
        "_id" : ObjectId("5eeb034d70a4b6360d5398cc"),
        "name" : "G-11",
        "actions" : [
                {
                        "_id" : 2,
                        "type" : "type-y"
                }
        ],
        "_class" : "com.example.demo.Game"
}

推荐阅读