带有MyBatis TypeHandler的空对象模式

时间:2013-02-14 12:09:21

标签: java mybatis typehandler

我一直在尝试在MyBatis中创建自定义TypeHandler,以便对于数据库中的null列,MyBatis返回Null Object pattern的实现,而不是{{1}在域类中。

谷歌搜索寻求帮助之后,我找到了一个优秀的项目mybatis-koans,即koan 19,它使用我正在使用的相同方法解决了这个问题,即扩展{ {1}}(是抽象的)。此时,我有一个与EmailTypeHandler in that koan类似的具体null

BaseTypeHandler<T>

不幸的是,似乎作者( midpeter444 )面临同样的问题:当数据库中的值为TypeHandler时,仍会返回null而不是在具体/** * 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 { } }

2 个答案:

答案 0 :(得分: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>返回适当的实现(在这种情况下,当数据库中的值为null时为NullObject implmentation),而不继承BaseTypeHandler

已编辑(以下是 quux00 的评论):当然,我们可以覆盖getResult的{​​{1}}方法,因为该功能方法BaseTypeHandler提供的方法很有用。

答案 1 :(得分:2)

感谢您的回答!它帮助我理解了我的问题以及如何克服它。我希望结果永远不会为空。

通过发布BaseTypeHandler的代码,它确认根据ResultSet.wasNull返回null,而不是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;
}