How to convert from Integer column to a custom type with Kotlin JOOQ and SimpleFlatMapper?

135 Views Asked by At

I have a Kotlin Project using JOOQ to connect with a MySQL database. I have a my_table table with an int int_column and I want to convert it to a MyCustomType class declared on MyTableJooqEntityfile. The configuration is done by using JOOQ forcedTypes specified on build.gradle file. But I am receiving a ClassCastException. What can I be doing wrong?

Now I will show some implementation details. I have the following MySQL table:

CREATE TABLE `my_table`
(
    `id`         int PRIMARY KEY AUTO_INCREMENT  not null,
    `int_column` int                             not null
);

Then I have this JOOQ entity mapping:

@Entity
@Table(name = "my_table")
data class MyTableJooqEntity(@Id
                             @Column(name = "id")
                             var Id: Int = -1,

                             @Column(name = "int_column")
                             var intColumn: MyCustomType)

And I have this build.gradle forcedTypes configuration:

forcedType {
    userType = "co.mycompany.MyCustomType"
    converter = "new co.mycompany.converters.IntegerToMyCustomTypeConverter()"
    includeExpression = "mydatabase.my_table.int_column"
}

And the custom converter:

package co.mycompany.converters

import co.mycompany.MyCustomType
import org.jooq.Converter

class IntegerToMyCustomTypeConverter : Converter<Integer, MyCustomType> {
    override fun from(databaseObject: Integer?): MyCustomType? {
        return MyCustomType.of(databaseObject)
    }

    override fun fromType(): Class<Integer> =
        Integer::class.java

    override fun to(userObject: MyCustomType?): Integer? {
        return userObject.toBigDecimal().toInt() as Integer 
       // I need to do some transformations before
       // convert it finally to java.lang.Integer 
       // (or Kotlin Int, but neither is working)
    }

    override fun toType(): Class<MyCustomType> =
        MyCustomType::class.java
}

Then when I run a select on my JooqDao:

fun selectById(Id: Int): MyTableJooqEntity? =
   withContext {
     val query = it.select(*table.fields())
                .from(table)
                .where(table.ID.eq(Id))
     return query.fetchOneInto(MyTableJooqEntity::class.java)
   }

And I am finally receiving this error, no matter what I try I can't convert int to any custom type:

 java.lang.IllegalArgumentException: argument type mismatch
      at co.mycompany.MyCustomTest.testConvert(MyCustomTest.kt:100)
  Caused by: java.lang.ClassCastException: Cannot cast java.lang.Integer to co.mycompany.MyCustomType
      at co.mycompany.MyCustomTest.testConvert(MyCustomTest.kt:100)
1

There are 1 best solutions below

2
rafalimaz On

The solution was to add a getter for MyCustomType to the JdbcMapperFactory. The forcedType especification is not enough in this case.

fun getJdbcMapperFactory(): JdbcMapperFactory =
        JdbcMapperFactory
            .newInstance()
            .addGetterForType(MyCustomType::class.java) { rs, i -> MyCustomType.of(rs.getInt(i)) }