Answer a question

tl;dr

  • Atempting to add an ArrayList in which Object may be an ArrayList to Persistance.
  • Tried to add an AttributeConverter > Failed
  • Plz Help
  • I have no idea what I am doing.
  • How stupid am I?

The Problem

Dependencies

  • spring-boot-starter-data-jpa 2.0.0
  • spring-boot-starter-data-mongodb 2.0.0
  • eclipselink 2.7.1 <- Probably don't need this one, not sure.

So here is my problem I am trying to add persistence in a Spring Boot Application for a MongoDB in this case I am using tables, the problem comes exactly on the TableRaw bean (a striped down version of Table just for persistance).

Document(collection = "rule_tables")
public class TableRaw {

    @Id
    private String _id;
    private String key;
    private String name;
    private String returns;
    private ArrayList<AxisRaw> axis;

    private ArrayList<Object> values = new ArrayList<>();
}

Everything else is just the default constructor (without _id) and getsetters.

So everything works fine with the exception of the values ArrayList. It works fine if it just a simple ArrayList with number and whatnot however in my case I want something like what I am inserting into the database (this is done every time it runs for testing purposes and the values inserted are using the MongoRepository, it works fine)

{
  "_id":"5ac20c8b8ee6e6360c8947be",
  "key":"1",
  "name":"Table 1",
  "returns":"Number",
  "axis":[
     {
       "name":"potato",
       "values":[
          {
             "_id":"BottomEdge","value":0
          },{
             "_id":"Range",
              "value":[1,2]
          },{
             "_id":"TopEdge",
             "value":3
          }
        ]
      }
   ],
  "values":[
      [1,2,3],
      [1,2,3],
      [1,2,3]
  ],
  "_class":"pt.i2s.gm.gm.rulehandler.tables.model.TableRaw"
}

(For usage in the code the axis length and number of axis matters but in this case it is completely irrelevant.)

Anyway as stated previously it inserts fine into MongoDB but when attempting to get the value the following error is presented.

 org.springframework.data.mapping.MappingException: Cannot convert [1, 2, 3] of type class java.util.ArrayList into an instance of class java.lang.Object! Implement a custom Converter<class java.util.ArrayList, class java.lang.Object> and register it with the CustomConversions. Parent object was: [empty]

First thing first I don't exactly know what Parent object was: [empty] means.

Second I tried creating an AttributeConverter as such:

@Component
@Converter(autoApply = true)
public class ArrayList2ObjectConverter implements 
AttributeConverter<ArrayList<Object>,Object> {

    @Override
    public Object convertToDatabaseColumn(ArrayList<Object> attribute) {
        return attribute;
    }

    @SuppressWarnings("unchecked") //If you don't like it suppress it
    @Override
    public ArrayList<Object> convertToEntityAttribute(Object dbData) {
        System.out.println("Converting...");
        return (ArrayList<Object>)dbData;
    }

}

And adding @Convert(converter = ArrayList2ObjectConverter.class) above the values attribute. However this wasn't even called.

For some reason I couldn't find any answers to this problem, possibly due to my bad coding and making something that is just stupid to do so nobody would do it like this cause it doesn't work.

So how do I do this? And thank you for reading.

Update regarding the Axis and Value amounts

thomi sugested something that would work if I knew from the get go what type of values the table added. I apreciate the answere however some clarification should be made regarding this.

  • I do not know how many Axis, and therefore nested arrays I will have, it may be 1 it may be 30.
  • I do not know what the class type of objects will be, it may be numbers, Strings, Booleans, dates, etc. the options are limited but still extensive.

Possible Solution Which I Do Not don't want to use

I could simply create an Object that held a string and an ArrayList which would probably work fine, however I wanted to avoid this resolution, as I don't want to add irrelevant information to the database.

Adopted Solution

By request of @user_531 I will add the solution to this problem.

As this was not working I altered my aproach to the utilization of a new object called ValueList which is simply a wrapper class for a single Object

private ArrayList<ValueList> values;

ValueList Class

public class ValueList {
  public Object value;
}

This allows me to add any type of object I want to the list, this does result however in tables looking like this:

{
  "key":1,
  ...... (Same as above)
  "values": [
       {
         "value": [
            {
              "value":1
            },
            {
              "value":2
            }
         ]
       },
       {
         "value": [
            {
              "value":3
            },
            {
              "value":4
            }
          ]
       }
    ]
}

Which does look hidious but it doesn't fail anymore and allows me to read values relativelly consistently by calling the "getValue()" method or "getValueList()" method acording to the result from "isValueList()".

Answers

I think you should not map something to an object. In your DB, you will surely have an idea of what datatype there will be in your Array, In your case, try and replace with:

@Document(collection = "rule_tables")
public class TableRaw {

  @Id
  private String _id;
  private String key;
  private String name;
  private String returns;
  private ArrayList<AxisRaw> axis;

  private List<List<Integer>> values; // no initialization.
}

This should map your structure just fine.

Logo

MongoDB社区为您提供最前沿的新闻资讯和知识内容

更多推荐