2013-02-14 2 views
4

Я пытался сделать обычай TypeHandler в MyBatis так что для null столбца в базе данных, MyBatis возвращает реализацию Null Object pattern вместо того, чтобы в классе домена в null.Null модели объекта с MyBatis TypeHandler

После прибегая к помощи за помощью, я достиг проект EXCELENT mybatis-koans, а именно koan 19, что обращается именно этот вопрос с таким же подходом я использую, то есть расширение BaseTypeHandler<T> (абстрактно). На данный момент, у меня есть конкретный TypeHandler, похожий на EmailTypeHandler in that koan:

/** 
* Acts as a factory method to return the appropriate implementation of an Email. 
* Returns a Null object if the email value in the database was null/empty 
*/ 
public class EmailTypeHandler extends BaseTypeHandler<Email> { 

    @Override 
    public Email getNullableResult(ResultSet rs, String colName) throws SQLException { 
    return createEmail(rs.getString(colName)); 
    } 

    @Override 
    public Email getNullableResult(ResultSet rs, int colNum) throws SQLException { 
    return createEmail(rs.getString(colNum)); 
    } 


    private Email createEmail(String s) { 
    System.out.println(s); 
    if (s == null || s.equals("")) { 
     return new NullEmail(); 
    } else { 
     return new EmailImpl(s); 
    } 
    } 

    @Override 
    public Email getNullableResult(CallableStatement arg0, int arg1) throws SQLException { 
    return null; 
    } 

    @Override 
    public void setNonNullParameter(PreparedStatement ps, int colNum, 
            Email e, JdbcType t) throws SQLException { 
    } 
} 

К сожалению, кажется, что автор (midpeter444) сталкивается с той же проблемой: когда значение в БД null, нуль является все еще вернулись вместо объекта, созданного в бетоне TypeHandler.

ответ

3

Я увидел решение сразу после размещения вопроса. В BaseTypeHandler код:

[...] 
    public T getResult(ResultSet rs, String columnName) throws SQLException { 
    T result = getNullableResult(rs, columnName); 
    if (rs.wasNull()) { 
     return null; 
    } else { 
     return result; 
    } 
    } 

    public T getResult(ResultSet rs, int columnIndex) throws SQLException { 
    T result = getNullableResult(rs, columnIndex); 
    if (rs.wasNull()) { 
     return null; 
    } else { 
     return result; 
    } 
    } 

    public T getResult(CallableStatement cs, int columnIndex) throws SQLException { 
    T result = getNullableResult(cs, columnIndex); 
    if (cs.wasNull()) { 
     return null; 
    } else { 
     return result; 
    } 
    } 

    public abstract void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException; 

    public abstract T getNullableResult(ResultSet rs, String columnName) throws SQLException; 

    public abstract T getNullableResult(ResultSet rs, int columnIndex) throws SQLException; 

    public abstract T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException; 
[...] 

Очевидно, что BaseTypeHandler собирается вернуться null, когда значение в базе данных null как cs.WasNull() в этом случае true. Таким образом, решение заключается в создании конкретного TypeHandler<T>, возвращающего соответствующую реализацию (в данном случае, имплементацию NullObject, когда значение в базе данных равно null) без подкласса BaseTypeHandler.

EDITED (folowing quux00 «s комментарий): Конечно, мы можем просто переопределить getResultBaseTypeHandler метод, при условии, что функциональные возможности, обеспечиваемые его метод setParameters может быть полезным.

+0

Красота открытого источника - прочитайте код ответа. Хороший анализ! Одна критика - вы все еще можете подклассифицировать BaseTypeHandler и просто переопределить методы getResult, нет? Чтобы реализовать TypeHander напрямую, вам также придется реализовать setParameters, который для этого случая может быть просто нерабочим, но в других сценариях вам может понадобиться функциональность, предоставляемая 'BaseTypeHandler # setParameters'. – quux00

+0

Вы правы ... Лучше просто переопределить метод getResult, чтобы использовать предоставленный метод setParameter в 'BaseTypeHandler'. – jalopaba

2

Спасибо за ваш ответ! Это помогло мне понять мою проблему и как ее преодолеть. Я хотел, чтобы результат никогда не был нулевым.

Вы отправляете код для BaseTypeHandler, он подтвердил, что значение null возвращалось в зависимости от ResultSet.wasNull, а не от самого результата, полученного от getNullableResult. Поэтому я переделал getResult в конкретный подкласс BaseTypeHandler. В пользовательских реализациях getResult вызывается super.getResult, а затем проверяется значение null. Ниже приведен пример:

public Money getResult (ResultSet rs, String columnName) throws SQLException 
{ 
    Money result = super.getResult (rs, columnName); 
    return result == null ? Money.ZERO : result; 
} 

public Money getResult (ResultSet rs, int columnIndex) throws SQLException 
{ 
    Money result = super.getResult (rs, columnIndex); 
    return result == null ? Money.ZERO : result; 
} 

public Money getResult (CallableStatement cs, int columnIndex) throws SQLException 
{ 
    Money result = super.getResult (cs, columnIndex); 
    return result == null ? Money.ZERO : result; 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^