Repository: ebean-orm/ebean

Issue #2148: PersistenceException: No ScalarType registered for class java.util.LinkedHashMap
Created: 2021-01-20T10:29:32Z
javax.persistence.PersistenceException: No ScalarType registered for class java.util.LinkedHashMap

	at io.ebeaninternal.server.persist.Binder.getScalarType(Binder.java:191)
	at io.ebeaninternal.server.persist.Binder.bindObject(Binder.java:216)
	at io.ebeaninternal.server.querydefn.OrmUpdateProperties$SimpleValue.bind(OrmUpdateProperties.java:78)
	at io.ebeaninternal.server.querydefn.OrmUpdateProperties.bind(OrmUpdateProperties.java:168)
	at io.ebeaninternal.server.query.CQueryPredicates.bind(CQueryPredicates.java:127)
	at io.ebeaninternal.server.query.CQueryPredicates.bind(CQueryPredicates.java:119)
	at io.ebeaninternal.server.query.CQueryUpdate.execute(CQueryUpdate.java:91)
	at io.ebeaninternal.server.query.CQueryEngine.executeUpdate(CQueryEngine.java:81)
	at io.ebeaninternal.server.query.CQueryEngine.update(CQueryEngine.java:76)
	at io.ebeaninternal.server.query.DefaultOrmQueryEngine.update(DefaultOrmQueryEngine.java:76)
	at io.ebeaninternal.server.core.OrmQueryRequest.update(OrmQueryRequest.java:394)
	at io.ebeaninternal.server.core.DefaultServer.update(DefaultServer.java:1334)
	at io.ebeaninternal.server.querydefn.DefaultOrmQuery.update(DefaultOrmQuery.java:1509)
	at io.ebeaninternal.server.expression.DefaultExpressionList.update(DefaultExpressionList.java:391)
	at org.tests.json.TestJsonMapBasic.updateQuery_bindingMap(TestJsonMapBasic.java:123)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
	at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
	at org.junit.rules.RunRules.evaluate(RunRules.java:20)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)

Steps to reproduce
    String s1 = "{\"docId\":222,\"contentId\":\"updatedDoc222\"}";
    Map<String, Object> content1 = EJson.parseObject(s1);

    final int rows = DB.update(EBasicJsonMap.class)
      .set("content", content1)
      .where().eq("id", bean.getId())
      .update();

Duplicate issue #2117: Update statement on (Jackson) ObjectNode fields throws "javax.persistence.PersistenceException: No ScalarType registered for class"
Created: 2020-11-25T15:42:21Z
Expected behavior
I expected that update statements would work the same as setting the fields and calling the database#update(bean)
Actual behavior
I got an exception with a json field. I can work around (using H2, not sure postgres would like) by calling the node#toString() and by using setters (which I would really like to avoid). With setters the generated query (H2):
update some_table set input_data=?, async_state=?, async_state_changed_at=?, async_output_data=? where id=?; -- bind({"foo":"bar"},TERMINATED,2020-11-25T15:37:53.869001,{"someField":"6041b523-80e3-4178-a34a-5bb665331...,6041b523-80e3-4178-a34a-5bb665331b71)
(Because of the setter, now the input_data field also is sent, which is also an objectnode)
Steps to reproduce
class SomeEntity {
    // ....
    @Enumerated(EnumType.STRING)
    @Column(name = "async_state", nullable = false)
    private SimulationRequestAsyncState asyncState;

    @Column(name = "async_state_changed_at", nullable = false)
    private LocalDateTime asyncStateChangedAt;

    @DbJson
    @Column(name = "async_output_data", nullable = true)
    private JsonNode asyncOutputData;
}

// database update method:
   @Override
    public int updateStateAndData(Database database, UUID id, SimulationRequestAsyncState state,
                ObjectNode outputData) {
            var query = new QSomeEntity(database);
            var update = query.id.eq(id).asUpdate().set("asyncState", state)
                    .set("asyncOutputData", outputData)
                    .set("asyncStateChangedAt", LocalDateTime.now(zoneId));
            int nrows = update.update();
            return nrows;
calling the method with non null inputs, yields the following stacktrace:
javax.persistence.PersistenceException: No ScalarType registered for class com.fasterxml.jackson.databind.node.ObjectNode at io.ebeaninternal.server.persist.Binder.getScalarType(Binder.java:191) at io.ebeaninternal.server.persist.Binder.bindObject(Binder.java:216) at io.ebeaninternal.server.querydefn.OrmUpdateProperties$SimpleValue.bind(OrmUpdateProperties.java:73) at io.ebeaninternal.server.querydefn.OrmUpdateProperties.bind(OrmUpdateProperties.java:164) at io.ebeaninternal.server.query.CQueryPredicates.bind(CQueryPredicates.java:127) at io.ebeaninternal.server.query.CQueryPredicates.bind(CQueryPredicates.java:119) at io.ebeaninternal.server.query.CQueryUpdate.execute(CQueryUpdate.java:91) at io.ebeaninternal.server.query.CQueryEngine.executeUpdate(CQueryEngine.java:81) at io.ebeaninternal.server.query.CQueryEngine.update(CQueryEngine.java:76) at io.ebeaninternal.server.query.DefaultOrmQueryEngine.update(DefaultOrmQueryEngine.java:76) at io.ebeaninternal.server.core.OrmQueryRequest.update(OrmQueryRequest.java:394) at io.ebeaninternal.server.core.DefaultServer.update(DefaultServer.java:1330) at io.ebeaninternal.server.querydefn.DefaultOrmQuery.update(DefaultOrmQuery.java:1477) at io.ebeaninternal.server.querydefn.DefaultUpdateQuery.update(DefaultUpdateQuery.java:64) at .....updateStateAndData()

Closing comment (2021-01-20T10:38:16Z): Effectively a duplicate of #2148 now.