0

I am trying to add a Map field in my oracle nosqltable (in the example given here https://docs.oracle.com/en/database/other-databases/nosql-database/21.1/java-driver-table/accessing-nosql-using-sdf.html) but when saving its not getting saved properly by Spring data.

Customer.java

@NosqlTable(storageGB = 1, writeUnits = 10, readUnits = 10)
 public class Customer {
        @NosqlId(generated = true)
        long customerId;
        String firstName;
        String lastName;
        Map hashMap;
        Date createdAt;

        @Override
        public String toString() {
            return "Customer{" +
               "customerId=" + customerId +
               ", firstName='" + firstName + '\'' +
               ", lastName='" + lastName + '\'' +
               ", createdAt='" + createdAt + '\'' +
               ", hashMap='" + hashMap + '\'' +
               '}';
        }
}

CustomerRepostory.java

import com.oracle.nosql.spring.data.repository.NosqlRepository;

public interface CustomerRepository
    extends NosqlRepository<Customer, Long>
{
    Iterable<Customer> findByLastName(String lastname);
}

When I call the following code to create a customer row :

Customer s1 = new Customer();
        s1.firstName = "John";
        s1.lastName = "Doe";
        HashMap s1Map = new HashMap() ;
        s1Map.put("name", "myMap") ;
        s1Map.put("use", true);
        s1.hashMap = s1Map;

        repo.save(s1);

It gets saved as

{
          "createdAt": null,
          "firstName": "John",
          "hashMap": {
                    "entrySet": null,
                    "keySet": null,
                    "loadFactor": 0.75,
                    "modCount": 2,
                    "size": 2,
                    "table": [
                              null,
                              null,
                              null,
                              null,
                              null,
                              null,
                              {
                                        "hash": 116102,
                                        "key": "use",
                                        "next": null,
                                        "value": true
                              },
                              null,
                              {
                                        "hash": 3373752,
                                        "key": "name",
                                        "next": null,
                                        "value": "myMap"
                              },
                              null,
                              null,
                              null,
                              null,
                              null,
                              null,
                              null
                    ],
                    "threshold": 12,
                    "values": null
          },
          "lastName": "Doe"
}

Can someone please help me with correct data type to use for nosql map ?

user3346812
  • 33
  • 1
  • 7

2 Answers2

1

Map (java.util.Map) is not currently supported, but it is a key roadmap item.

see here https://github.com/oracle/nosql-spring-sdk/issues/18

You can find the current Mapping Between Java and NoSQL JSON Types in the documentation - https://docs.oracle.com/en/database/other-databases/nosql-database/22.2/springsdk/persistence-model.html

In the meantime, it is possible to use the class oracle.nosql.driver.values.MapValue. Here is an example

import com.oracle.nosql.spring.data.core.mapping.NosqlId;
import oracle.nosql.driver.values.MapValue ;

@NosqlTable(storageGB = 1, writeUnits = 10, readUnits = 10)
public class Customer {
    @NosqlId(generated = true)
    long customerId;
    String firstName;
    String lastName;
    MapValue map;

    @Override
    public String toString() {
        return "Customer{" +
            "customerId=" + customerId +
            ", firstName='" + firstName + '\'' +
            ", lastName='" + lastName + '\'' +
            ", map='" + map + '\'' +
            '}';
    }
}

Here is an example of a call to create a customer row - using multiple types, including other nosql Classes oracle.nosql.driver.values.ArrayValue . As you can see the syntax is very similar to java.util.Map. When java.util.Map will be supported you can migrate easily

Customer c2 = new Customer();
c2.firstName = "John";
c2.lastName = "Josh";
c2.map = new MapValue();
c2.map.put("number field", 1);
c2.map.put("string_field", "string value");
c2.map.put("boolean_field", true);
ArrayValue arrayValue = new ArrayValue();
arrayValue.add(100);
arrayValue.add("102");
arrayValue.add(true);
c2.map.put("json-field", arrayValue);
repo.save(c2);
System.out.println("\nsaved: " + c2); 

System.out.println("\nfindAll:");
Iterable<Customer> customers = repo.findAll();

for (Customer s : customers) {
    System.out.println("  Customer: " + s);
}

System.out.println("\nfindByLastName: Josh");
customers = repo.findByLastName("Josh");

for (Customer s : customers) {
    System.out.println("  Customer: " + s);
}

Here are the outputs - application

saved: Customer{customerId=10, firstName='John', lastName='Doe', map='null'}

saved: Customer{customerId=11, firstName='John', lastName='Smith', map='null'}

saved: Customer{customerId=12, firstName='John', lastName='Josh', map='{"number field":1,"json-field":[100,"102",true],"string_field":"string value"}'}

findAll:
  Customer: Customer{customerId=12, firstName='John', lastName='Josh', map='{"json-field":[100,"102",true],"number field":1,"string_field":"string value"}'}
  Customer: Customer{customerId=10, firstName='John', lastName='Doe', map='null'}
  Customer: Customer{customerId=11, firstName='John', lastName='Smith', map='null'}

findByLastName: Josh
  Customer: Customer{customerId=12, firstName='John', lastName='Josh', map='{"json-field":[100,"102",true],"number field":1,"string_field":"string value"}'}

reading using the SQL for Oracle NoSQL Database Shell - if Cloud, you can use the OCI Console

sql-> mode json -pretty
Query output mode is pretty JSON
sql-> select * from customer;
{
  "customerId" : 13,
  "kv_json_" : {
    "firstName" : "John",
    "lastName" : "Doe",
    "map" : null
  }
}

{
  "customerId" : 14,
  "kv_json_" : {
    "firstName" : "John",
    "lastName" : "Smith",
    "map" : null
  }
}

{
  "customerId" : 15,
  "kv_json_" : {
    "firstName" : "John",
    "lastName" : "Josh",
    "map" : {
      "boolean_field" : true,
      "json-field" : [100, "102", true],
      "number field" : 1,
      "string_field" : "string value"
    }
  }
}

In order to run this example, you need to apply a fix, Otherwise, you will have the following error

Caused by: java.lang.IllegalArgumentException: Entity must not be null!

A fix will be published soon on this GitHub repository https://github.com/oracle/nosql-spring-sdk. Again more information here https://github.com/oracle/nosql-spring-sdk/issues/18

to learn more on MapValue

Dario
  • 440
  • 1
  • 3
  • 8
0

Map (java.util.Map) is supported in version 1.5.

see here https://github.com/oracle/nosql-spring-sdk/blob/main/CHANGELOG.md#150

Dario
  • 440
  • 1
  • 3
  • 8