1

I’m converting a java project to kotlin but getting an error constructing a data object with the query results. The query is a join with a one to many relationship between Docs and Questions. This works in java but I can’t get it to work with kotlin. I’ve tried providing default values and using the no-args project. Not sure if this is a kotlin, jooq, or simple flat mapper issue.

Spring boot: 2.5.4
kotlin: 1.5.31

implementation 'org.simpleflatmapper:sfm-jooq:8.2.3'
implementation 'org.springframework.boot:spring-boot-starter-jooq'



@Repository
open class DocRepository(private val dslContext: DSLContext) {
    companion object : KLogging()

    private val docMapper = SelectQueryMapperFactory.newInstance().newMapper(
        Doc::class.java
    )

override fun getDocDetails(docId: Int): Doc {
        return docMapper.asList(
            dslContext.select(
                Tables.DOC.DOC_ID,
                Tables.DOC.TITLE,
                Tables.DOC.DESCRIPTION,
                Tables.DOC.QUESTION.QUESTION_ID,
                Tables.DOC.QUESTION.DOC_ID,
                Tables.DOC.QUESTION.QUESTION,
                Tables.DOC.QUESTION.ANSWER
            )
                .from(Tables.DOC).leftJoin(Tables.QUESTION)
                .on(Tables.QUESTION.DOC_ID.eq(Tables.DOC.DOC_ID))
                .where(Tables.DOC.DOC_ID.eq(docId))
        ).stream().findFirst().get()
    }

}




data class Doc(
    var docId: Int? = null,
    val title: String? = "",
    val description: String? = "",
    var questions: List<Question?>? = null,
)


data class Question(
    var questionId: Int? = null,
    var docId: Int? = null,
    var question: String? = "",
    var answer: String? = ""
)



org.jooq.exception.MappingException: No constructor available for class com.test.entity.Doc
at org.simpleflatmapper.jooq.SelectQueryMapper.getMapper(SelectQueryMapper.java:186)
at org.simpleflatmapper.jooq.SelectQueryMapper.asList(SelectQueryMapper.java:46)
user10993231
  • 111
  • 1
  • 1
  • 6
  • I'm not sure but if you add _@NoArgsConstructor_ you also need to add _@AllArgsConstructor_ to the Doc class. – lukas.j Nov 15 '21 at 18:37
  • That's a custom annotation created with the kotlin-noarg project. It doesn't seem to work for this problem. It's not a lombok annotation. – user10993231 Nov 15 '21 at 19:09
  • I just thought that it might be that the NoArgs annotation prevents the implicit constructor which is needed by jooq to be able to create instances of the Doc class. – lukas.j Nov 15 '21 at 19:15

1 Answers1

0

I cannot comment on your SimpleFlatMapper usage, but starting with jOOQ 3.15, there's a better way to nest collections if your underlying SQL database product supports SQL/JSON or SQL/XML in some way: Use the new MULTISET (or MULTISET_AGG) operator!

override fun getDocDetails(docId: Int): Doc {
    return dslContext.select(
            DOC.DOC_ID,
            DOC.TITLE,
            DOC.DESCRIPTION,
            multiset(
                select(
                    QUESTION.QUESTION_ID,
                    QUESTION.DOC_ID,
                    QUESTION.QUESTION,
                    QUESTION.ANSWER
                )
                .from(QUESTION)
                .where(QUESTION.DOC_ID.eq(DOC.DOC_ID))
            ).convertFrom { it.map(Records.mapping(::Question)) }
        )
        .from(DOC)
        .where(DOC.DOC_ID.eq(docId))
        .fetchSingle(Records.mapping(::Doc))
    }
}

This is all type safe and reflection free.

Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509