MongoDB DBRef 列表在 Spring Boot 中返回 null

Posted

技术标签:

【中文标题】MongoDB DBRef 列表在 Spring Boot 中返回 null【英文标题】:MongoDB DBRef list returning null in Spring Boot 【发布时间】:2019-11-23 02:29:29 【问题描述】:

我正在尝试使用 Spring Boot 在 MongoDB 中创建数据库。我想创建两个集合,一个 DbConnections 集合和一个 Configuration 集合。我想要做的是 DbConnections 集合中的每个连接都有自己的配置,就像使用外键的 SQL 引用一样。我试图使用@DBRef 注释来做到这一点:

@Document(collection = "connections")
public class DbConnection 
    @Transient
    public static final String SEQUENCE_NAME = "connection_sequence";
    @Id
    private long id;
    private String username;
    private String password;
    private String connectionUrl;
    private long fkIdUsuario;
    @DBRef(db = "configurations")
    private List<Configuration> configurations;

    public DbConnection() 
    

    public DbConnection(String username, String password, String connectionUrl) 
        this.username = username;
        this.password = password;
        this.connectionUrl = connectionUrl;
    

    public long getId() 
        return id;
    

    public void setId(long id) 
        this.id = id;
    

    public List<Configuration> getConfigurations() 
        return configurations;
    

    public void setConfigurations(List<Configuration> configurations) 
        this.configurations = configurations;
    

    public String getUsername() 
        return username;
    

    public void setUsername(String username) 
        this.username = username;
    

    public String getPassword() 
        return password;
    

    public void setPassword(String password) 
        this.password = password;
    

    public String getConnectionUrl() 
        return connectionUrl;
    

    public void setConnectionUrl(String connectionUrl) 
        this.connectionUrl = connectionUrl;
    

    public long getFkIdUsuario() 
        return fkIdUsuario;
    

    public void setFkIdUsuario(long fkIdUsuario) 
        this.fkIdUsuario = fkIdUsuario;
    

还有配置类:

@Document(collection = "configurations")
public class Configuration 
    @Transient
    public static final String SEQUENCE_NAME = "config_sequence";
    @Id
    private long id;
    private int fkIdConnection;
    private String name;
    private String query;
    private BasicDBObject values;
    private BasicDBObject result;

    public Configuration() 
    

    public Configuration(long id, int fkIdConnection, String name, String query, BasicDBObject values, BasicDBObject result) 
        this.id = id;
        this.fkIdConnection = fkIdConnection;
        this.name = name;
        this.query = query;
        this.values = values;
        this.result = result;
    

    public int getFkIdConnection() 
        return fkIdConnection;
    

    public void setFkIdConnection(int fkIdConnection) 
        this.fkIdConnection = fkIdConnection;
    

    public Map getValues()
        if(null != values)
            return values.toMap();
        
        return null;
    

    public void setValues()
        this.values = new BasicDBObject(values);
    

    public Map getResult()
        if(null != result)
            return result.toMap();
        
        return null;
    

    public void setResult()
        this.result = new BasicDBObject(result);
    

    public long getId() 
        return id;
    

    public void setId(long id) 
        this.id = id;
    

    public String getName() 
        return name;
    

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

    public String getQuery() 
        return query;
    

    public void setQuery(String query) 
        this.query = query;
    

我将这样的数据保存在控制器中: 对于 DbConnectionsController:

@PostMapping(value = "/conexion")
    public DbConnection addConnection(@RequestBody DbConnectionModel dbConnectionModel)
        DbConnection dbConnection = new DbConnection(dbConnectionModel.getUsername(), dbConnectionModel.getPassword(), dbConnectionModel.getConnectionUrl());
        dbConnection.setFkIdUsuario(getIdUsuario());
        return dbConnectionRepository.save(dbConnection);
    

以及配置控制器的保存方法:

@PostMapping
    public Configuration agregarConfiguracion(@RequestBody Configuration configuration)
        configuration.setId(sequenceGeneratorService.generateSequence(Configuration.SEQUENCE_NAME));

        return configurationRepository.save(configuration);
    

现在,当我保存 Connection 时,它在 mongo 对象中没有字段 configurations,当我创建新的 Configuration 时,它仍然没有在 DbConnection 中显示它。尝试使用 GET 请求获取 DbConnections 对象,但 DbConnectionsconfigurations 字段显示为空。为什么会发生这种情况,我该如何解决?

【问题讨论】:

【参考方案1】:

我遇到了类似的问题,DBRef 返回一个空数组。帮助我诊断的几个步骤:

1) 您的 2 个集合 connectionsconfigurations 是否保存在 2 个单独的数据库中?如果不是,则需要删除@DBRef 之后的(db = "configurations")

@DBRef
private List<Configuration> configurations;

2) 直接连接到数据库时能找到对象吗?我使用 Robot 3T,这是一个 GUI 工具,可以直接查看 Mongo DB 以检查正在保存的数据的形状。确保您的connections 设置正确,您还应该看到每个connectionconfigurations,如下所示:

configurations: [
  
    "$ref": "configurations",
    "$id": ObjectId("asdfadsgasdfasdfa")
  
]

3) 你可以单步进入类 org.springframework.data.mongodb.core.convert.DefaultDbRefResolver,方法 fetch()。 (我使用的是 springboot 2.1.6.RELEASE 和相同版本的 spring-boot-starter-data-mongodb 依赖)

@Override
    public Document fetch(DBRef dbRef) 

        if (LOGGER.isTraceEnabled()) 
            LOGGER.trace("Fetching DBRef '' from ..", dbRef.getId(),
                    StringUtils.hasText(dbRef.getDatabaseName()) ? dbRef.getDatabaseName() : mongoDbFactory.getDb().getName(),
                    dbRef.getCollectionName());
        

        StringUtils.hasText(dbRef.getDatabaseName());
        return getCollection(dbRef).find(Filters.eq("_id", dbRef.getId())).first();
    

确保dbRef的所有属性(ie.collectionName, db, id)都正确,否则找不到相关对象。

【讨论】:

以上是关于MongoDB DBRef 列表在 Spring Boot 中返回 null的主要内容,如果未能解决你的问题,请参考以下文章

使用 QueryDSL 使用 Spring Data MongoDB 查询 DBRef

Spring Data MongoDB中的手动引用与DBRef?

使用 Jackson PTH 和 Spring Data MongoDB DBRef 生成额外目标属性的 Java 到 JSON 序列化

spring data mongo使用@DBRef,怎么查询指定字段的集合

Spring Mongo DB @DBREF

为啥 MongoDB 文档建议不要使用 DBREF?