2011-10-11 56 views
10

Đối tượng Miền của tôi có vài trường Thời gian Joda-DateTime. Khi tôi đọc các giá trị cơ sở dữ liệu sử dụng SimpleJdbcTemplate:Ghi đè BeanPropertyRowMapper để Hỗ trợ Ngày giờ JodaTime

bệnh nhân Bệnh nhân = jdbc.queryForObject (sql, mới BeanPropertyRowMapper (Patient.class), patientId);

Nó chỉ thất bại và đáng ngạc nhiên, không có lỗi nào được ghi lại. Tôi đoán đó là do việc phân tích cú pháp timestamp thành DateTime không hoạt động với Jdbc.

Nếu nó có thể kế thừa và ghi đè BeanPropertyRowMapper và hướng dẫn để chuyển đổi tất cả các java.sql.Timestampjava.sql.Date-DateTime, nó sẽ là tuyệt vời và có thể tiết kiệm rất nhiều mã thêm.

Bạn có lời khuyên nào không?

Trả lời

21

Các điều đúng để làm là để phân lớp BeanPropertyRowMapper, ghi đè initBeanWrapper(BeanWrapper) và đăng ký Trình chỉnh sửa thuộc tính tùy chỉnh:

public class JodaDateTimeEditor extends PropertyEditorSupport { 
    @Override 
    public void setAsText(final String text) throws IllegalArgumentException { 
     setValue(new DateTime(text)); // date time in ISO8601 format 
             // (yyyy-MM-ddTHH:mm:ss.SSSZZ) 
    } 
    @Override 
    public void setValue(final Object value) { 
     super.setValue(value == null || value instanceof DateTime ? value 
             : new DateTime(value)); 
    } 
    @Override 
    public DateTime getValue() { 
     return (DateTime) super.getValue(); 
    } 
    @Override 
    public String getAsText() { 
     return getValue().toString(); // date time in ISO8601 format 
             // (yyyy-MM-ddTHH:mm:ss.SSSZZ) 
    } 
} 
public class JodaTimeSavvyBeanPropertyRowMapper<T> 
        extends BeanPropertyRowMapper<T> { 
    @Override 
    protected void initBeanWrapper(BeanWrapper bw) { 
     bw.registerCustomEditor(DateTime.class, new JodaDateTimeEditor()); 
    } 
} 
+0

Đây chính xác là những gì tôi đang tìm kiếm. Tuy nhiên, nó không thực sự làm việc cho tôi. Việc thực hiện dừng ngay khi ánh xạ DateTime xảy ra, tuy nhiên không có lỗi nào được ghi lại: 'DEBUG: com.keype.hawk.system.jdbc.support.HawkBeanPropertyRowMapper [mapRow]: Ánh xạ cột 'date_added' đến thuộc tính 'dateAdded' của kiểu lớp org. joda.time.DateTime' –

+0

Cuối cùng là quản lý khu vực sự cố. setValue() được gọi với đối tượng TimeStamp làm tham số, nhưng nó thực sự là một JodaTime Per logger của tôi: 'Un object được hỗ trợ 2011-10-12 00: 00: 00.0. Loại đối tượng: java.sql.Timestamp. Ngày giờ mong đợi ' –

+0

@firdousamir ok, tôi đã thay đổi mã ngay bây giờ. Hãy thử phiên bản này. –

2

Nhìn vào BeanPropertyRowMapper thực hiện, cách thức mà nó thiết lập các lĩnh vực là:

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); 
} 

nơi getColumnValue(rs, index, pd); đại biểu JdbcUtils.getResultSetValue

Đó pd trường trong getColumnValue là thực tế "p roperty d escriptor ", được sử dụng (pd.getPropertyType()) trong JdbcUtils dưới dạng loại của trường để ánh xạ tới.

Nếu bạn xem mã JdbcUtils cho phương thức getResultSetValue, bạn sẽ thấy rằng nó chỉ đơn giản là từ một câu lệnh if đến câu khác, để đối sánh pd.getPropertyType() với tất cả các loại tiêu chuẩn. Khi nó không tìm thấy một, vì DateTime không phải là "tiêu chuẩn" loại, nó dựa trên một rs.getObject():

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

Sau đó, nếu đối tượng này là một ngày SQL nó chuyển đổi nó vào một Timestamp, và trả về được thiết lập vào trường DateTime trong miền của bạn => nơi không thành công.

Do đó, dường như không có cách nào để chuyển tiếp một cách thẳng thắn để chèn một hình ảnh Date/Timestamp tới DateTime chuyển đổi thành BeanPropertyRowMapper. Vì vậy, nó sẽ được sạch hơn (và nhiều hơn nữa) để thực hiện RowMapper của riêng bạn.

Trong trường hợp bạn muốn xem lỗi ánh xạ trong bảng điều khiển, hãy đặt mức nhật ký của bạn cho org.springframework.jdbc thành "gỡ lỗi" hoặc "dấu vết" tốt hơn để xem chính xác điều gì xảy ra.

Một điều bạn có thể thử, mà tôi đã không kiểm tra, là mở rộng một BeanPropertyRowMapper và ghi đè lên một tài sản của DateTime gõ:

/** 
* Initialize the given BeanWrapper to be used for row mapping. 
* To be called for each row. 
* <p>The default implementation is empty. Can be overridden in subclasses. 
* @param bw the BeanWrapper to initialize 
*/ 
protected void initBeanWrapper(BeanWrapper bw) {} 
+0

Cảm ơn tolitius. Đó là những gì tôi đã làm. Tôi không thể tìm ra cách nào. Một hàng tùy chỉnh là vấn đề. –

1

Câu trả lời của @Sean Patrick Floyd là hoàn hảo cho đến khi bạn không có nhiều loại tùy chỉnh.

Ở đây nó là một tổng quát, cấu hình dựa trên phần mở rộng sử dụng:

public class CustomFieldTypeSupportBeanPropertyRowMapper<T> extends BeanPropertyRowMapper<T> { 
    private Map<Class<?>, Handler> customTypeMappers = new HashMap<Class<?>, Handler>(); 

    public CustomFieldTypeSupportBeanPropertyRowMapper() { 
    super(); 
    } 

    public CustomFieldTypeSupportBeanPropertyRowMapper(Class<T> mappedClass, boolean checkFullyPopulated) { 
    super(mappedClass, checkFullyPopulated); 
    } 

    public CustomFieldTypeSupportBeanPropertyRowMapper(Class<T> mappedClass) { 
    super(mappedClass); 
    } 

    public CustomFieldTypeSupportBeanPropertyRowMapper(Class<T> mappedClass, Map<Class<?>, Handler> customTypeMappers) { 
    super(mappedClass); 
    this.customTypeMappers = customTypeMappers; 
    } 

    @Override 
    protected Object getColumnValue(ResultSet rs, int index, PropertyDescriptor pd) throws SQLException { 
    final Class<?> current = pd.getPropertyType(); 
    if (customTypeMappers.containsKey(current)) { 
     return customTypeMappers.get(current).f(rs, index, pd); 
    } 
    return super.getColumnValue(rs, index, pd); 
    } 

    public void addTypeHandler(Class<?> class1, Handler handler2) { 
    customTypeMappers.put(class1, handler2); 
    } 

    public static interface Handler { 
    public Object f(ResultSet rs, int index, PropertyDescriptor pd) throws SQLException; 
    } 
} 
Các vấn đề liên quan