Issue
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
);
}
Solution
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<>();
...
}
Answered By - Mihai David
Answer Checked By - David Marino (JavaFixing Volunteer)