Skip to content

Commit

Permalink
Oracle NoSQL Database - Json type fix (#1772)
Browse files Browse the repository at this point in the history
This if fix + unit test for following case. Oracle NoSQL database allows store into JSON column type two kinds of values:

- String form which was currently supported
- Object tree based on `oracle.nosql.driver.values.MapValue`

Object tree wasn't supported before and there were incorrect results during various reading operations (find(...), query..)
At the Entity side is JSON stored as a `java.lang.String`.
This PR fixes conversion between JSON data stored as `oracle.nosql.driver.values.MapValue` and `java.lang.String` JPA field.

Signed-off-by: Radek Felcman <radek.felcman@oracle.com>
  • Loading branch information
rfelcman committed Jan 5, 2023
1 parent 4aa8582 commit 790bd17
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 35 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand Down Expand Up @@ -370,11 +370,13 @@ public DatabaseField buildField(DatabaseField field) {
if (isXMLFormat()) {
if(!(field instanceof XMLField)) {
String xPath = field.getName();
String columnDefinition = field.getColumnDefinition();
// Moxy requires /text on elements.
if ((xPath.indexOf('@') == -1) && (xPath.indexOf("/text()") == -1)) {
xPath = xPath + "/text()";
}
field = new XMLField(xPath);
field.setColumnDefinition(columnDefinition);
}
((XMLField)field).setNamespaceResolver(getNamespaceResolver());
((XMLField)field).initialize();
Expand Down
7 changes: 6 additions & 1 deletion foundation/org.eclipse.persistence.oracle.nosql/pom.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2019, 2022 Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2019, 2023 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0 which is available at
Expand Down Expand Up @@ -287,6 +287,11 @@
<version>2.0.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.parsson</groupId>
<artifactId>parsson</artifactId>
<scope>test</scope>
</dependency>
<!--JDBC driver dependencies-->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand All @@ -14,6 +14,7 @@
// Oracle - initial API and implementation
package org.eclipse.persistence.testing.models.jpa.nosql;

import jakarta.persistence.Cacheable;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
Expand All @@ -35,6 +36,7 @@
@NamedQuery(name = "DataTypesEntity.findByIdAndName", query = "SELECT t FROM DataTypesEntity t WHERE t.id = :id AND t.fieldString = :name")
})
@NoSql
@Cacheable(false)
public class DataTypesEntity {
@Id
private long id;
Expand All @@ -43,8 +45,10 @@ public class DataTypesEntity {
private byte[] fieldBinary;
@Column(name = "col_boolean")
private boolean fieldBoolean;
@Column(name = "col_json", columnDefinition = "JSON")
private String fieldJson;
@Column(name = "col_json_string", columnDefinition = "JSON")
private String fieldJsonString;
@Column(name = "col_json_object", columnDefinition = "JSON")
private String fieldJsonObject;
@Column(name = "col_null")
private String fieldNull;
@Column(name = "col_string")
Expand Down Expand Up @@ -83,12 +87,20 @@ public void setFieldBoolean(boolean fieldBoolean) {
this.fieldBoolean = fieldBoolean;
}

public String getFieldJson() {
return fieldJson;
public String getFieldJsonString() {
return fieldJsonString;
}

public void setFieldJson(String fieldJson) {
this.fieldJson = fieldJson;
public void setFieldJsonString(String fieldJsonString) {
this.fieldJsonString = fieldJsonString;
}

public String getFieldJsonObject() {
return fieldJsonObject;
}

public void setFieldJsonObject(String fieldJsonObject) {
this.fieldJsonObject = fieldJsonObject;
}

public String getFieldNull() {
Expand Down Expand Up @@ -121,7 +133,8 @@ public String toString() {
"id=" + id +
", fieldBinary=" + Arrays.toString(fieldBinary) +
", fieldBoolean=" + fieldBoolean +
", fieldJson='" + fieldJson + '\'' +
", fieldJsonString='" + fieldJsonString + '\'' +
", fieldJsonObject='" + fieldJsonObject + '\'' +
", fieldNull='" + fieldNull + '\'' +
", fieldString='" + fieldString + '\'' +
", fieldTimestamp=" + fieldTimestamp +
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
Expand All @@ -14,14 +14,23 @@
// Oracle - initial API and implementation.
package org.eclipse.persistence.testing.tests.jpa.nosql.sdk;

import jakarta.json.Json;
import jakarta.json.JsonObject;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.Persistence;
import jakarta.persistence.Query;
import jakarta.resource.cci.Connection;
import oracle.nosql.driver.NoSQLHandle;
import oracle.nosql.driver.ops.GetRequest;
import oracle.nosql.driver.ops.GetResult;
import oracle.nosql.driver.ops.PutRequest;
import oracle.nosql.driver.ops.PutResult;
import oracle.nosql.driver.ops.TableLimits;
import oracle.nosql.driver.ops.TableRequest;
import oracle.nosql.driver.values.ArrayValue;
import oracle.nosql.driver.values.JsonNullValue;
import oracle.nosql.driver.values.MapValue;
import org.eclipse.persistence.internal.nosql.adapters.sdk.OracleNoSQLConnection;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;
Expand All @@ -30,6 +39,7 @@
import org.junit.BeforeClass;
import org.junit.Test;

import java.io.StringReader;
import java.sql.Timestamp;
import java.util.List;

Expand All @@ -53,9 +63,20 @@ public class NoSQLJPADataTypesTest {
private static final long ID = 1L;
private static final byte[] FIELD_BINARY = {1, 2, 3, 4};
private static final boolean FIELD_BOOLEAN = true;
private static final String FIELD_JSON = "{\"a\": 1.006, \"b\": null," +
private static final String FIELD_JSON_STRING = "{\"a\": 1.006, \"b\": null," +
"\"bool\" : true, \"map\": {\"m1\": 5}," +
"\"ar\" : [1,2.7,3]}";
private static final MapValue FIELD_JSON_OBJECT = new MapValue()
.put("a", 1.006)
.put("b", JsonNullValue.getInstance())
.put("bool", true)
.put("map", new MapValue()
.put("m1", 5))
.put("ar", new ArrayValue()
.add(1)
.add(2)
.add(7)
.add(3));
private static final String FIELD_STRING = "abcd";
private static final Timestamp FIELD_TIMESTAMP = new Timestamp(123456L);

Expand All @@ -73,6 +94,12 @@ public void testJPAFind() {
assertEquals(ID, dataTypesEntity.getId());
assertArrayEquals(FIELD_BINARY, dataTypesEntity.getFieldBinary());
assertEquals(FIELD_BOOLEAN, dataTypesEntity.isFieldBoolean());
assertEquals(FIELD_JSON_STRING, dataTypesEntity.getFieldJsonString());
JsonObject jsonObjectFromStringField = Json.createReader(new StringReader(dataTypesEntity.getFieldJsonString())).readObject();
assertNotNull(jsonObjectFromStringField);
assertEquals(FIELD_JSON_OBJECT.toJson(), dataTypesEntity.getFieldJsonObject());
JsonObject jsonObjectFromObjectField = Json.createReader(new StringReader(dataTypesEntity.getFieldJsonObject())).readObject();
assertNotNull(jsonObjectFromObjectField);
assertNull(dataTypesEntity.getFieldNull());
assertEquals(FIELD_STRING, dataTypesEntity.getFieldString());
assertEquals(FIELD_TIMESTAMP, dataTypesEntity.getFieldTimestamp());
Expand Down Expand Up @@ -199,7 +226,7 @@ private static DataTypesEntity prepareEntity(long id) {
DataTypesEntity dataTypesEntity = new DataTypesEntity(id);
dataTypesEntity.setFieldBinary(FIELD_BINARY);
dataTypesEntity.setFieldBoolean(FIELD_BOOLEAN);
dataTypesEntity.setFieldJson(FIELD_JSON);
dataTypesEntity.setFieldJsonString(FIELD_JSON_STRING);
dataTypesEntity.setFieldNull(null);
dataTypesEntity.setFieldString(FIELD_STRING);
dataTypesEntity.setFieldTimestamp(FIELD_TIMESTAMP);
Expand All @@ -217,6 +244,8 @@ public static void testJPASetup() {
createTable(noSQLHandle);
testJPAPersist();
testJPAMerge();
//Update col_json_object with MapValue
updateRow(noSQLHandle);
em.getTransaction().commit();
em.close();
}
Expand All @@ -230,7 +259,8 @@ private static void createTable(NoSQLHandle handle) {
"(id INTEGER, " +
"col_binary BINARY, " +
"col_boolean BOOLEAN, " +
"col_json JSON, " +
"col_json_string JSON, " +
"col_json_object JSON, " +
"col_null STRING, " +
"col_string STRING, " +
"col_timestamp TIMESTAMP(3), " +
Expand All @@ -249,4 +279,21 @@ private static void dropTable(NoSQLHandle handle) {
handle.doTableRequest(tableRequest, 60000, 1000);
LOG.log(SessionLog.INFO, String.format("Table \t%s has been dropped", TABLE_NAME));
}

private static void updateRow(NoSQLHandle handle) {
// Fetch a row modify and update it back to DB
MapValue key = new MapValue().put("id", ID);
GetRequest getRequest = new GetRequest().setKey(key).setTableName(TABLE_NAME);
GetResult getResult = handle.get(getRequest);
MapValue value = getResult.getValue();
value.put("col_json_object", FIELD_JSON_OBJECT);
PutRequest putRequest = new PutRequest().setValue(value).setTableName(TABLE_NAME);
putRequest.setOption(PutRequest.Option.IfPresent);
PutResult putResult = handle.put(putRequest);
if (putResult.getVersion() != null) {
LOG.log(SessionLog.INFO, String.format("Updated row with ID: \t%s", value));
} else {
LOG.log(SessionLog.INFO,"Update failed");
}
}
}

0 comments on commit 790bd17

Please sign in to comment.