Home > Software design >  org.springframework.dao.IncorrectResultSizeDataAccessException Mongo Limit dosen't work?
org.springframework.dao.IncorrectResultSizeDataAccessException Mongo Limit dosen't work?

Time:06-08

GoodEvening i'm new about mongo, and i choose to use a mix & match of RepositoryPattern and Mongotemplate

Now i find a very strange error when i want to use MongoTemplate to retrive a specific value of an inner object in order to calculate a progressive ID It seems my code work for 0 or 1 document inside a collection, but when i have equal or more than 2 documents, the method will throw a

org.springframework.dao.IncorrectResultSizeDataAccessException: Query { "$java" : Query: {}, Fields: {}, Sort: {} } returned non unique result.

as if limit dosen't work. I have just, for now, a rest and a repository pattern, but in the service layer i have another autowire whit mongotemplate class, this template is used by just 1 method.

public DetailedOrder findTheBiggestBy(String byWhat){
        Query query = new Query();
        query.with(Sort.by(Sort.Direction.DESC,byWhat)).limit(1);
        return mongoDb.findOne(query,DetailedOrder.class);
    }

As you can see is pretty simple and it actually work, becouse before moving the Template inside Service it actually work whit various documents inside collection, when i autowired it over the rest layer.

There is something i miss and is not rly related to mongo but related to spring autowire?

My detailorderClass is

package com.service.backend.BK.Pojo;

import com.service.backend.BK.Constants.Constant;
import org.bson.codecs.pojo.annotations.BsonId;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
import org.springframework.data.mongodb.core.mapping.FieldType;
import org.springframework.data.mongodb.core.mapping.MongoId;


import java.util.List;
@Document("Orders")
public class DetailedOrder {

    @MongoId(FieldType.OBJECT_ID)
    private String id;
    @Field
    private List<Integer> category;
    // 1 junk to 10 Pristine
    @Field
    private Integer quality;
    @Field
    private BaseOrder baseOrder;
    @Field
    private String qualityDescription;

    public DetailedOrder(){}
    public DetailedOrder(String Description,Double price, List<Integer> category, Integer quality) {
        this.category = category;
        this.quality = quality;
        this.qualityDescription = qualityDescriptionPairFactory(quality);
        this.baseOrder=new BaseOrder(Description,price);
    }



    public List<Integer> getCategory() {
        return category;
    }
    public void setCategory(List<Integer> category) {
        this.category = category;
    }
    public Integer getQuality() {
        return quality;
    }
    public void setQuality(Integer quality) {
        this.quality = quality;
    }
    public String getQualityDescription() {
        return qualityDescription;
    }
    public void setQualityDescription(String qualityDescription) {
        this.qualityDescription = qualityDescription;}
    private String qualityDescriptionPairFactory(int quality){
        switch (quality){
            case 1:return Constant.Quality.NOGRAD.label;
            case 2:return Constant.Quality.HEAVYDMN.label;
            case 3:return Constant.Quality.LOOSE.label;
            case 4:return Constant.Quality.POOR.label;
            case 5:return Constant.Quality.LIGHTDMN.label;
            case 6:return Constant.Quality.GOOD.label;
            case 7:return Constant.Quality.EXCELENT.label;
            case 8:return Constant.Quality.NEARMINT.label;
            case 9:return Constant.Quality.MINT.label;
            case 10:return Constant.Quality.NEWUNRL.label;
            default:return Constant.Quality.NOGRAD.label;        }
    }
    @Override
    public String toString() {
        return "DetailedOrder{"  
                "id='"   id   '\''  
                ", baseOrder='"   getBaseOrder().returnBaseOrder()   '\''  
                ", category="   category  
                ", quality="   quality  
                ", qualityDescription='"   qualityDescription   '\''  
                '}';
    }

    public BaseOrder getBaseOrder() {
        return baseOrder;
    }

    public void setBaseOrder(BaseOrder baseOrder) {
        this.baseOrder = baseOrder;
    }

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

and that lead to baseOrderClass

package com.service.backend.BK.Pojo;

import org.joda.time.DateTime;
import org.springframework.data.mongodb.core.mapping.Document;

 public class BaseOrder {
     private String id;
     private String description;
     private Double desideredPrice;
     //Pending,active,Rejected,Hault,etc etc
     private int status;
     
     protected  BaseOrder(){}
     protected  BaseOrder(String description, Double desideredPrice) {
          this.description = description;
          this.desideredPrice = desideredPrice;
     }
     public String returnBaseOrder(){
          return "BaseOrder{"  
                  "id='"   id   '\''  
                  ", description='"   description   '\''  
                  ", desideredPrice="   desideredPrice  
                  ", status="   status  
                  '}';
     }
     
     public String getDescription() {
          return description;
     }
     public void setDescription(String description) {
          this.description = description;
     }
     public Double getDesideredPrice() {
          return desideredPrice;
     }
     public void setDesideredPrice(Double desideredPrice) {
          this.desideredPrice = desideredPrice;
     }
     public int getStatus() {
          return status;
     }
     public void setStatus(int status) {
          this.status = status;
     }
     public String getId() {
          return id;
     }
     public void setId(String id) {
          this.id = id;
     }
     //###############################################################################################################//

}

CodePudding user response:

The OPs question related to a spring context issue. By just accessing the repository directly the problem could be resolved.

Within the comments an additional question/target has been found, i would like to provide an answer for that.

How to have persistence access within the domain layer?

I have created a repository at GitHub where you can find a working solution. This code is not best practice but will provide a solution that works.

Every constructed domain object needs access to the declared repositories. That can be a problem when using dependency injection. In order to keep entity construction pristine an abstract class has been introduces that takes the task to get the concrete repositories.

The core idea is to make the Spring ApplicationContext accessable statically. Having this context an access to the repositories is just one call away.

Beans having the ApplicationContextAware interface will be called in a very early stage of Spring Boots startup. When using this class to access the context every consumer has to call it after Spring has been loaded. This can be achieved by using @Component, @Configuration, @Bean to run code and there will be no race condition.

Further details are within the repositories readme file.

I hope that this helps you :)

  • Related