Overriding BeanPropertyRowMapper to Support JodaTime DateTime

后端 未结 3 2093
清酒与你
清酒与你 2021-02-05 17:55

My Domain object has couple of Joda-Time DateTime fields. When I\'m reading database values using SimpleJdbcTemplate:

Patient patient = jdbc.

3条回答
  •  难免孤独
    2021-02-05 18:28

    Looking at BeanPropertyRowMapper implementation, the way it sets the fields is:

    Object value = getColumnValue( rs, index, pd );
    
    if (logger.isDebugEnabled() && rowNumber == 0) {
        logger.debug("Mapping column '" + column + "' to property '" +
        pd.getName() + "' of type " + pd.getPropertyType());
    }
    try {
        bw.setPropertyValue(pd.getName(), value);
    }
    

    where getColumnValue(rs, index, pd); delegates to JdbcUtils.getResultSetValue

    That pd field in getColumnValue is the actual "p roperty d escriptor", that is used ( pd.getPropertyType() ) in JdbcUtils as a type of the field to map to.

    If you look at JdbcUtils code for getResultSetValue method, you'll see that it simply goes from one if statement to another, to match pd.getPropertyType() to all standard types. When it does not find one, since DateTime is not a "standard" type, it relies on a rs.getObject():

    } else {
    // Some unknown type desired -> rely on getObject.
    

    Then if this object is a SQL Date it converts it to a Timestamp, and returns to be set to a DateTime field of your domain => where it fails.

    Hence, there does not seem to be a straight forward way to inject a Date/Timestamp to DateTime converter into a BeanPropertyRowMapper. So it would be cleaner (and more performant) to implement your own RowMapper.

    In case you'd like to see the mapping error in a console, set your logging level for org.springframework.jdbc to "debug" or better yet "trace" to see exactly what happens.

    One thing you can try, which I have not tested, is to extend a BeanPropertyRowMapper and override a property of DateTime type in:

    /**
     * Initialize the given BeanWrapper to be used for row mapping.
     * To be called for each row.
     * 

    The default implementation is empty. Can be overridden in subclasses. * @param bw the BeanWrapper to initialize */ protected void initBeanWrapper(BeanWrapper bw) {}

提交回复
热议问题