How can I deserialize row to DTO?

Viewed 62

I have created method where I can pass SQL string, arguments and DTO class.

public <T> List selectObjectList(String sql, Object[] args, Class<T> dto) {
    return jdbcTemplate.query(
            sql,
            args,
            new BeanPropertyRowMapper(dto)
    );
}

So my DTO is

@Data
@NoArgsConstructor
public class SimpleDto{
    private Integer id;
    private Date createDate;
            ...
    private ArrayList<String> recipents;
    private ArrayList<Integer> objects;
            ...
}

Then I pass SQL "select * from simple_dto n where n.create_date >= now()", no argsuments and

ArrayList<Notification> notifications = 
        (ArrayList<Notification>) comDao.selectObjectList(sql, args, SimpleDto.class);

And I get exception:

Caused by: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'org.postgresql.jdbc.PgArray' to required type 'java.util.ArrayList' for property 'recipents'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'org.postgresql.jdbc.PgArray' to required type 'java.util.ArrayList' for property 'recipents': no matching editors or conversion strategy found

SQL script to create simple_dto table:

create table notification
(
    id          SERIAL PRIMARY KEY,
    create_date  timestamp not null,
    recipents          varchar ARRAY,
    objects            integer ARRAY
);

I know that problem in array. But how can I solve it ?

UPD: Main purpose to make DRY code. BeanPropertyRowMapper really cant deserialize arrays to list. But here method where you can put BeanPropertyRowMapper(DTO.class) and custom RowMapper both.

@Override
    public <T> List<T> selectObjectList(String sql, Object[] args, RowMapper<T> mapper) {
        return jdbcTemplate.query(
                sql,
                args,
                mapper
        );
    }
1 Answers

BeanPropertyRowMapper cannot map java.sql.Array to ArrayList

Create a RowMapper (implement also mapping of 'objects' like i did for "recipents" And also 'create_date')

public class NotificationMapper implements RowMapper<Notification> {
    @Override
    public Notification mapRow(ResultSet rs, int rowNum) throws SQLException {
        Notification employee = new Notification();
        employee.setId(rs.getInt("id"));
        String[] arr = (String[])rs.getArray("recipents").getArray();
        Collections.addAll(employee.getRecipents(), arr);
        return employee;
    }
}

And use it to map result set. (You can remove 'dto' param.)

jdbcTemplate.query(
            sql,
            args,
            new NotificationMapper()
    );

Note that your lists from the pojo need to be initialized

public class SimpleDto{
    private Integer id;
    private Date createDate;
            ...
    private ArrayList<String> recipents = new ArrayList<>();
    private ArrayList<Integer> objects = new ArrayList<>();
            ...
}
Related