arnaudroger / SimpleFlatMapper

Fast and Easy mapping from database and csv to POJO. A java micro ORM, lightweight alternative to iBatis and Hibernate. Fast Csv Parser and Csv Mapper
http://simpleflatmapper.org
MIT License
437 stars 76 forks source link

Mapping sql-ResultSet to nested list structure #674

Open jimonthebarn opened 5 years ago

jimonthebarn commented 5 years ago

This is less of an issue and more of a 'how can this be achieved'- type of question.

Im trying to map the data retrieved via a ResultSet to a nested target structure whose simplified, pseudo-code structure looks like this:

data class ParentEntity(
       var parentId : Int,
        var children: MutableList<ChildEntity>
) 

data class ChildEntity(
       var parentId: Int,
       var childId: Int,
       var propA: String,
       var propB: String

      //some static method to create child entity
      fun build(parentId, childId, propA, propB) : ChildEntity
)

The type of children property was String before and everything was working with the mapper based on the following configuration:

JdbcMapperFactory.newInstance()
       .addKeys("parentId")
       .addAlias("children_column_in_db", "children")
       .newMapper(ParentEntity::class.java)

Since the children property now needs to contain a complex type it was changed to ChildEntity. As explained in https://github.com/arnaudroger/SimpleFlatMapper/wiki/Errors_CSFM_GETTER_NOT_FOUND I adjusted the Mapper configuration like such to tell the mapper which column maps to which field:

JdbcMapperFactory.newInstance()
       .addKeys("parentId", "childId")
       .addAlias("parentId", "children.parentId")
       .addAlias("childId", "children.childId")
        .addAlias("propFromResultSetA", "children.propA")
       .addAlias("propFromResultSetB", "children.propB")
       // this is my poor attempt to add a getter to let simpleflatmapper know how to create the ChildEntity which is obviously wrong since I cant access all the columns required here 
       .addGetterForType(ChildEntity::class.java) {
              ContextualGetter<ResultSet, ChildEntity> { s, context ->
                     ChildEntity.build("", "", "", "") }
              }
       .newMapper(ParentEntity::class.java)

Upon execution simpleflatmapper reports: Could not find eligible property for 'children.parentId' on class com...ParentEntity.

If I understood correctly this type of mapping should be supported. Im sure I configured something wrong here and would greatly appreciate a hint on where my config attempt went wrong. :)

Cheers, Ben

arnaudroger commented 5 years ago

yes I think it should work, the only it would not work might be link to the build function if it can't figure out the name of the parameter, could you try with a constructor? to see if that the case?\ what is the type of MutableList? is it eclipse collection? or kotlin list - that could also be the issue.

jimonthebarn commented 5 years ago

I added the constructor to no avail though. Yep the MutableList is a kotlin built-in interface. I fiddled around a little bit with different types for the children property but the error remains.

arnaudroger commented 5 years ago

I’ll try to reproduce but I don’t think I have kotlin lost support yet

Sent from my iPhone

On 13 Aug 2019, at 08:03, Ben Roth notifications@github.com wrote:

I added the constructor to no avail though. Yep the MutableList is a kotlin built-in interface. I fiddled around a little bit with different types for the children property but the error remains.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

arnaudroger commented 5 years ago

I'm trying to reproduce the pb with the following code

class Issue674Test {
    @Test
    fun test() {

        val builder = JdbcMapperFactory.newInstance().useAsm(false)
                .addKeys("parentId", "childId")
                .addAlias("parentId", "children.parentId")
                .addAlias("childId", "children.childId")
                .addAlias("propFromResultSetA", "children.propA")
                .addAlias("propFromResultSetB", "children.propB")
                .newBuilder(ParentEntity::class.java)

        builder.addKey("parentId")
        builder.addKey("childId")
        builder.addMapping("propFromResultSetA")
        builder.addMapping("propFromResultSetB")

        val mapper = builder.mapper();

        println("mapper = ${mapper}")
    }
}

data class ParentEntity(
        var parentId : Int,
        var children: MutableList<ChildEntity>
)

data class ChildEntity(
        var parentId: Int,
        var childId: Int,
        var propA: String,
        var propB: String
)

using the builder - static mapper - to avoid having to setup the database but it seems to be working .... the MutableList is actually working would you mind trying to reproduce it using that test as a base?

jimonthebarn commented 5 years ago

Sure I will. Whats the purpose of re-adding the keys after the instantiation of the builder? Do I need those as well? Great to hear that kotlin lists should be working out of the box already.

arnaudroger commented 5 years ago

no purpose redundant there ... my mistake