question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Mapping Result of Primitive Type Field when using Native Query

See original GitHub issue

Hi @mirromutth, I faced this situation when I map result to object from native query.

Environment

  • Spring Boot 2.3.4.RELEASE
  • Kotlin (java compat w/ 1.8)
  • R2DBC-MySQL 0.8.2 (dev.miku:r2dbc-mysql:0.8.2.RELEASE)
  • if any other is needed, just let me know 😃

Observation

  • My DB has a table as below:
field1 (varchar) field2 (varchar) field3 (double)
first row 1.0
second row 2.0
third row null
  • Query I used is as below:
SELECT field1, field2, field3
FROM my_table
...

and mapped into object with its result like this:

data class ResultObject(val f1: String, val f2: String, val f3: Double?)

val ro: ResultObject = connection.createStatement(query).execute()
  .map { row, _ -> ResultObject(
    row.get(0, String::class.java)!!,
    row.get(1, String::class.java)!!,
    row.get(2, Double::class.java)!!,
  ) }

And I got an error java.lang.IllegalArgumentException: Cannot decode null for type 5.

Conjecture

  • From my analysis of code, r2dbc (this library) gets its type information from db (type 5 - DataTypes.DOUBLE) and guesses “this field should be mapped into proper java type (Double.class)” – maybe around this line (DefaultCodecs.java)
  • Next, when this field (Double.class in above) is primitive, do decodePrimitive(). – this line
  • Comment on decodePrimitive() is // If value is null field, then primitive codec should throw an exception instead of return null.. But I’d like to ask about this – when type of corresponding field is wrapper type, could be nullable though it is primitive(or numeric) type? In my understanding, not only Kotlin, but also Java, wrapper type is nullable and could have null value.
  • Note that, my workaround is mapping last field of ResultObject using row.get(2, Any::class.java) as Double?.
  • I’d happy if I could hear your thoughts on this 😃 (if you agree with my opinion – wrapper type could have null value; I’ll consider how it could be resolved 😃)

Issue Analytics

  • State:open
  • Created 2 years ago
  • Comments:5 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
mirromutthcommented, Sep 17, 2021

Hi, @btakeya,

Great thanks for @mp911de suggestion. Apologies for the late reply.

Well, this should be a little difference between Java and Kotlin.

In Java, double.class is a primitive class, which is different from Double.class, a boxed type. So that’s why I want to throw an exception when calling double someData = row.get(0, double.class) in Java. If I do not, it will be an NPE and thrown by unboxing instead of driver-side.

In Kotlin/JVM, Double::class.java is a primitive class, and Kotlin/JVM blurs the difference between boxed type and primitive type at the usage level, because Kotlin is a multi-platform language (e.g. Kotlin/Native, Kotlin/JS). And if Kotlin/JVM wants to do the same behavior as the Java boxed type, it should be java.lang.Double::class.java instead.

Actually, yes, considering cross-language compatibility, even if the type is a primitive class, it should return null. And then, if the Java code executes int someData = row.get(0, int.class) and the field is null, it will be NPE (thrown by unboxing) instead of IllegalArgumentException (thrown by r2dbc-mysql).

I will merge your PR soon.

Great regards,

1reaction
mp911decommented, May 12, 2021

R2DBC doesn’t support primitive values as T always has to be an object, therefore use the wrapper type class.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Result Set Mapping: The Basics - Thorben Janssen
SQL result set mappings provide a nice way to map the List returned by native queries in JPA. Lets have a look at...
Read more >
Mapping and querying a list of primitive types with JPA 2.0
Sometimes you just want to map a list of primitive types. For example, a Book entity has a list of tags and tags...
Read more >
Native SQL - Doctrine Object Relational Mapper (ORM)
With NativeQuery you can execute native SELECT SQL statements and map the results to Doctrine entities or any other result format supported by...
Read more >
Converting a native query result having NULL values to a POJO
Explicity mention the type e.g @ColumnResult(name = "count", type = Integer.class; For POJO fields use Class(Integer) and not primitive(int) ...
Read more >
A Guide to SqlResultSetMapping - Baeldung
The core functionality here involves mapping result sets from database SQL statements into Java objects. 2. Setup.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found