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

JDBCMapper empty inner objects #653

Open marinflorin opened 5 years ago

marinflorin commented 5 years ago

Hey,

First of all thank you for this great library :)

Right now I have an issue with empty inner object matching. Relationships: User 1:1 company User 1:1 profile User 1:m groups

Query Result:

id first_name last_name username email external_id chat_id chat_team_id type profile_id profile_phone profile_avatar profile_privacy company_id company_name company_description company_floor company_phone company_external_id groups_id groups_name
19 FirstName LastName florin1 florin1@hotmail.com 14616e7d-1e11-4972-b8d1-9567c4fe686a {null} {null} 30 425 730313123 url_here 20 8 Company1 {null} 0 {null} {null} 426 Test Top-Managemnet
19 FirstName LastName florin1 florin1@hotmail.com 14616e7d-1e11-4972-b8d1-9567c4fe686a {null} {null} 30 425 730313123 url_here 20 8 Company1 {null} 0 {null} {null} 427 Primary
                                         

DTOs UserDTO.java

@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class UserDTO {

    @Key
    private Long id;
    private String firstName;
    private String lastName;
    private String email;
    private String username;
    private String externalId;
    private String chatId;
    private String chatTeamId;
    private int type;
    private ProfileDTO profile;
    private CompanyDTO company;
    private List<GroupDTO> groups;
}

ProfileDTO.java

@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class ProfileDTO {

    @Key
    private Long id;
    private String phone;
    private String avatar;
    private int privacy;
}

CompanyDTO.java

@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class CompanyDTO {

    @Key
    private Long id;
    private String name;
    private String externalId;
    private int floor;
    private String phone;
    private String description;
}

GroupDTO.java

@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class GroupDTO {

    @Key
    private Long id;
    private String name;
}

And the mapper:

JdbcMapper<UserDTO> mapper = JdbcMapperFactory.newInstance()
                .fieldMapperErrorHandler((key, source, target, error) -> {
                    System.out.println("Error ! on " + key + " " + error);
                })
                .rowHandlerErrorHandler((t, target) -> System.out.println("Error ! " + t))
//                .addKeys("id", "groups_id", "profile_id", "company_id", "cars_id", "departments_id")
                .addKeys("id", "groups_id", "profile_id", "company_id")
                .newMapper(UserDTO.class);

The Code:

 List<UserDTO> collect = null;
        try {
            collect = mapper.stream(users).collect(Collectors.toList());
        } catch (SQLException e) {
            e.printStackTrace();
        }

        for (UserDTO userDTO : collect) {
            System.out.println(userDTO);
            System.out.println(userDTO.getProfile());
            System.out.println(userDTO.getCompany());
            for (GroupDTO groupDTO : userDTO.getGroups()) {
                System.out.println(groupDTO);
            }
            break;
        }

And the result:

UserDTO(id=19, firstName=Florin Catalin, lastName=Marin, email=florin1@hotmail.com, username=florin1, externalId=14616e7d-1e11-4972-b8d1-9567c4fe686a, chatId=null, chatTeamId=null, type=30, profile=ProfileDTO(id=null, phone=null, avatar=null, privacy=0), company=CompanyDTO(id=null, name=null, externalId=null, floor=0, phone=null, description=null), groups=[GroupDTO(id=null, name=null), GroupDTO(id=null, name=null)])

ProfileDTO(id=null, phone=null, avatar=null, privacy=0) CompanyDTO(id=null, name=null, externalId=null, floor=0, phone=null, description=null) GroupDTO(id=null, name=null) GroupDTO(id=null, name=null)

NOTE: This happens to all my data, here I have showed only 1 example NOTE: I have tried removing and adding @Key and addKeys without success

Thank you, Florin

arnaudroger commented 5 years ago

hey what is the @key annotation package is the org.simpleflatmapper.map.annotation.Key one? is it using lombok I assume? which version? looks like the number of dto matches but the value are not set

arnaudroger commented 5 years ago

could you try just for testing purpose to manually add the constructors and getter on GroupDTO for example see if it's link to lombok, was there any error from the fieldMapperErrorHandler ? or rowHandlerErrorHandler?

marinflorin commented 5 years ago

Hey,

For @Key I am using import org.simpleflatmapper.map.annotation.Key; Sorry, forgot to add the versions:

        <!--        JOOQ        -->
        <dependency>
            <groupId>org.mariadb.jdbc</groupId>
            <artifactId>mariadb-java-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jooq</groupId>
            <artifactId>jooq</artifactId>
            <version>3.11.11</version>
        </dependency>
        <dependency>
            <groupId>org.jooq</groupId>
            <artifactId>jooq-meta</artifactId>
            <version>3.11.11</version>
        </dependency>
        <dependency>
            <groupId>org.jooq</groupId>
            <artifactId>jooq-codegen</artifactId>
            <version>3.11.11</version>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.197</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.simpleflatmapper/sfm -->
        <dependency>
            <groupId>org.simpleflatmapper</groupId>
            <artifactId>sfm</artifactId>
            <version>2.14.1</version>
        </dependency>
        <dependency>
            <groupId>org.simpleflatmapper</groupId>
            <artifactId>sfm-jdbc</artifactId>
            <version>6.6.2</version>
        </dependency>
<!--        <dependency>-->
<!--            <groupId>org.simpleflatmapper</groupId>-->
<!--            <artifactId>sfm-jooq</artifactId>-->
<!--            <version>6.6.2</version>-->
<!--        </dependency>-->
        <dependency>
            <groupId>org.jooq</groupId>
            <artifactId>jool</artifactId>
            <version>0.9.14</version>
        </dependency>
        <!--        End JOOQ        -->

Looks like the issue is raised by the constructors, even if I remove @NoArgsConstructor and @AllArgsConstructor and generate them from InteliJ the mapping dosent work, now I have removed the constructors and everything works as expected :)

Thank you, Florin

arnaudroger commented 5 years ago

which version of java are you compiling with? it should work with the constructor, could you send me the .class of GroupDTO that did not work?

arnaudroger commented 5 years ago

just did a test with lombok 1.16.12 and java8 and seems to be working fine

marinflorin commented 5 years ago
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.infotech.opensesame.src.user.user;

import org.simpleflatmapper.map.annotation.Key;

public class GroupDTO {
    @Key
    private Long id;
    private String name;

    public GroupDTO() {
    }

    public GroupDTO(Long id, String name) {
        this.id = id;
        this.name = name;
    }

    public Long getId() {
        return this.id;
    }

    public String getName() {
        return this.name;
    }

    public void setId(final Long id) {
        this.id = id;
    }

    public void setName(final String name) {
        this.name = name;
    }

    public boolean equals(final Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof GroupDTO)) {
            return false;
        } else {
            GroupDTO other = (GroupDTO)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                Object this$id = this.getId();
                Object other$id = other.getId();
                if (this$id == null) {
                    if (other$id != null) {
                        return false;
                    }
                } else if (!this$id.equals(other$id)) {
                    return false;
                }

                Object this$name = this.getName();
                Object other$name = other.getName();
                if (this$name == null) {
                    if (other$name != null) {
                        return false;
                    }
                } else if (!this$name.equals(other$name)) {
                    return false;
                }

                return true;
            }
        }
    }

    protected boolean canEqual(final Object other) {
        return other instanceof GroupDTO;
    }

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        Object $id = this.getId();
        int result = result * 59 + ($id == null ? 43 : $id.hashCode());
        Object $name = this.getName();
        result = result * 59 + ($name == null ? 43 : $name.hashCode());
        return result;
    }

    public String toString() {
        return "GroupDTO(id=" + this.getId() + ", name=" + this.getName() + ")";
    }
}

:: Spring Boot :: (v2.1.1.RELEASE)

florin@florin-UX430UAR:~$ java --version openjdk 11.0.2 2019-01-15 OpenJDK Runtime Environment (build 11.0.2+9-Ubuntu-3ubuntu118.04.3) OpenJDK 64-Bit Server VM (build 11.0.2+9-Ubuntu-3ubuntu118.04.3, mixed mode, sharing) lombok 1.18.4

marinflorin commented 5 years ago

BTW it looks like @AllArgsConstructor and @NoArgsConsturctor are working for UserDTO

arnaudroger commented 5 years ago

are you using 1.18.6? could you send me the .class by email arnaud.roger at gmail.com

arnaudroger commented 5 years ago

do you have any maven-compiler config?

marinflorin commented 5 years ago

Hey, I have a few plugins, that`s all

 <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>add-source</goal>
                        </goals>
                        <configuration>
                            <sources>
                                <source>target/generated-sources/jooq</source>
                            </sources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <groupId>org.jooq</groupId>
                <artifactId>jooq-codegen-maven</artifactId>

                <executions>
                    <execution>
                        <id>generate-jooq-sources</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <configuration>

                            <jdbc>
                                <driver>${jdbc.driver}</driver>
                                <url>${jdbc.url}</url>
                                <user>${jdbc.user}</user>
                                <password>${jdbc.password}</password>
                            </jdbc>

                            <generator>
                                <generate>
                                    <daos>true</daos>
                                    <pojosEqualsAndHashCode>true</pojosEqualsAndHashCode>
                                    <javaTimeTypes>true</javaTimeTypes>
                                </generate>
                                <database>
                                    <name>org.jooq.meta.mysql.MySQLDatabase</name>
                                    <includes>.*</includes>
                                    <!--<excludes></excludes>-->
                                    <inputSchema>${jdbc.database}</inputSchema>
                                </database>

                                <target>
                                    <clean>true</clean>
                                    <packageName>com.infotech.db</packageName>
                                    <directory>target/generated-sources/jooq</directory>
                                </target>
                            </generator>

                        </configuration>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>org.jooq</groupId>
                        <artifactId>jooq-meta-extensions</artifactId>
                        <version>3.11.9</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>