<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          想讓代碼更優(yōu)雅?Mybatis類型處理器了解一下!

          共 6113字,需瀏覽 13分鐘

           ·

          2021-08-03 05:14

          1. 明確需求

          在設計之初,sys_role表的enabled字段有2個可選值,其中0 代表禁用,1代表啟用,而且實體類中我們使用的是Interger類型:

          /**
          * 有效標志
          */

          private Integer enabled;

          public Integer getEnabled() {
          return enabled;
          }

          public void setEnabled(Integer enabled) {
          this.enabled = enabled;
          }

          如果要新增或者更新角色信息,我們肯定要校驗enabled字段的值必須是0或者1,所以最初的部分代碼可能是這樣的:

          if (sysRole.getEnabled() == 0 || sysRole.getEnabled() == 1) {
          sysRoleMapper.updateById(sysRole);

          sysRole = sysRoleMapper.selectById(2L);
          Assert.assertEquals(0, sysRole.getEnabled());
          } else {
          throw new Exception("無效的enabled值");
          }

          這種硬編碼的方式不僅看起來不友好,而且不利于后期維護,如果維護的程序員脾氣不好,還會罵你,哈哈。

          所以我們的需求就是,拒絕硬編碼,使用友好的編碼方式來校驗enabled字段的值是否有效。

          2. 使用MyBatis提供的枚舉類型處理器

          我們通常會使用枚舉來解決這種場景。

          首先新建com.zwwhnly.mybatisaction.type包,然后在該包下新建枚舉Enabled:

          package com.zwwhnly.mybatisaction.type;

          public enum Enabled {
          /**
          * 禁用
          */

          disabled,

          /**
          * 啟用
          */

          enabled;
          }

          其中,disabled對應的索引為0,enabled對應的索引為1。

          然后將SysRole類中原來為Integer類型的enabled字段修改為:

          /**
          * 有效標志
          */

          private Enabled enabled;

          public Enabled getEnabled() {
          return enabled;
          }

          public void setEnabled(Enabled enabled) {
          this.enabled = enabled;
          }

          此時原本硬編碼的代碼就可以修改為:

          if (sysRole.getEnabled() == Enabled.disabled || sysRole.getEnabled() == Enabled.enabled) {
          sysRoleMapper.updateById(sysRole);

          sysRole = sysRoleMapper.selectById(2L);
          Assert.assertEquals(Enabled.disabled, sysRole.getEnabled());
          } else {
          throw new Exception("無效的enabled值");
          }

          雖然上面的代碼很完美的解決了硬編碼的問題,但此時又引出一個新的問題:

          數據庫并不能識別Enabled枚舉類型,在新增,更新或者作為查詢條件時,需要將枚舉值轉換為數據庫中的int類型,在查詢數據時,需要將數據庫的int類型的值轉換為Enabled枚舉類型。

          帶著這個問題,我們在SysRoleMapperTest測試類中添加如下測試方法:

          @Test
          public void testUpdateById() {
          SqlSession sqlSession = getSqlSession();

          try {
          SysRoleMapper sysRoleMapper = sqlSession.getMapper(SysRoleMapper.class);

          // 先查詢出id=2的角色,然后修改角色的enabled值為disabled
          SysRole sysRole = sysRoleMapper.selectById(2L);
          Assert.assertEquals(Enabled.enabled, sysRole.getEnabled());

          // 修改角色的enabled為disabled
          sysRole.setEnabled(Enabled.disabled);

          if (sysRole.getEnabled() == Enabled.disabled || sysRole.getEnabled() == Enabled.enabled) {
          sysRoleMapper.updateById(sysRole);

          sysRole = sysRoleMapper.selectById(2L);
          Assert.assertEquals(Enabled.disabled, sysRole.getEnabled());
          } else {
          throw new Exception("無效的enabled值");
          }
          } catch (Exception e) {
          e.printStackTrace();
          } finally {
          sqlSession.close();
          }
          }

          運行測試代碼,發(fā)現拋出如下異常:

          3dcbd82e419284a8892cd3ad8aa48907.webp

          Error querying database. Cause: org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'enabled' from result set. Cause: java.lang.IllegalArgumentException: No enum constant com.zwwhnly.mybatisaction.type.Enabled.1

          這是因為MyBatis在處理Java類型和數據庫類型時,使用TypeHandler(類型處理器)對這兩者進行轉換。

          MyBatis為Java類型和數據庫JDBC中的常用類型類型提供了TypeHandler接口的實現。

          MyBatis在啟動時會加載所有的JDBC對應的類型處理器,在處理枚舉類型時默認使用org.apache.ibatis.type.EnumTypeHandler處理器,這個處理器會將枚舉類型轉換為字符串類型的字面值使用,對于Enabled枚舉來說,就是“disabled"和”enabled"字符串。

          而數據庫中enabled字段的類型是int,所以在查詢到角色信息將int類型的值1轉換為Enabled類型報錯。

          那么如何解決這個問題呢?

          MyBatis還提供了另一個枚舉處理器:org.apache.ibatis.type.EnumOrdinalTypeHandler,這個處理器使用枚舉的索引進行處理,可以解決此處轉換報錯的問題。

          使用這個處理器,需要在之前的resources/mybatis-config.xml中添加如下配置:

          <typeHandlers>
          <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler"
          javaType="com.zwwhnly.mybatisaction.type.Enabled"/>

          </typeHandlers>

          再次運行測試代碼,測試通過,輸出日志如下:

          DEBUG [main] - ==> Preparing: SELECT id,role_name,enabled,create_by,create_time FROM sys_role WHERE id = ?

          DEBUG [main] - ==> Parameters: 2(Long)

          TRACE [main] - <== Columns: id, role_name, enabled, create_by, create_time

          TRACE [main] - <== Row: 2, 普通用戶, 1, 1, 2019-06-27 18:21:12.0

          DEBUG [main] - <== Total: 1

          DEBUG [main] - ==> Preparing: UPDATE sys_role SET role_name = ?,enabled = ?,create_by=?, create_time=? WHERE id=?

          DEBUG [main] - ==> Parameters: 普通用戶(String), 0(Integer), 1(Long), 2019-06-27 18:21:12.0(Timestamp), 2(Long)

          DEBUG [main] - <== Updates: 1

          從日志中可以看出,在查詢角色信息時,MyBatis將1轉換為了Enabled.enabled,在更新角色信息時,MyBatis將Enabled.disabled轉換為了0。

          3. 使用自定義的類型處理器

          假設enabled字段的值既不是枚舉的字面值,也不是枚舉的索引值,此時org.apache.ibatis.type.EnumTypeHandlerorg.apache.ibatis.type.EnumOrdinalTypeHandler都不能滿足我們的需求,這種情況下我們就需要自己來實現類型處理器了。

          首先修改下枚舉類Enabled代碼:

          package com.zwwhnly.mybatisaction.type;

          public enum Enabled {

          /**
          * 啟用
          */

          enabled(1),

          /**
          * 禁用
          */

          disabled(0);

          private final int value;

          private Enabled(int value) {
          this.value = value;
          }

          public int getValue() {
          return value;
          }
          }

          然后在com.zwwhnly.mybatisaction.type包下新建類型處理器EnabledTypeHandler:

          package com.zwwhnly.mybatisaction.type;

          import org.apache.ibatis.type.JdbcType;
          import org.apache.ibatis.type.TypeHandler;

          import java.sql.CallableStatement;
          import java.sql.PreparedStatement;
          import java.sql.ResultSet;
          import java.sql.SQLException;
          import java.util.HashMap;
          import java.util.Map;

          /**
          * Enabled類型處理器
          */

          public class EnabledTypeHandler implements TypeHandler<Enabled> {
          private final Map<Integer, Enabled> enabledMap = new HashMap<Integer, Enabled>();

          public EnabledTypeHandler() {
          for (Enabled enabled : Enabled.values()) {
          enabledMap.put(enabled.getValue(), enabled);
          }
          }

          @Override
          public void setParameter(PreparedStatement preparedStatement, int i, Enabled enabled, JdbcType jdbcType) throws SQLException {
          preparedStatement.setInt(i, enabled.getValue());
          }

          @Override
          public Enabled getResult(ResultSet resultSet, String s) throws SQLException {
          Integer value = resultSet.getInt(s);
          return enabledMap.get(value);
          }

          @Override
          public Enabled getResult(ResultSet resultSet, int i) throws SQLException {
          Integer value = resultSet.getInt(i);
          return enabledMap.get(value);
          }

          @Override
          public Enabled getResult(CallableStatement callableStatement, int i) throws SQLException {
          Integer value = callableStatement.getInt(i);
          return enabledMap.get(value);
          }
          }

          自定義類型處理器實現了TypeHandler接口,重寫了接口中的4個方法,并且在無參構造函數中遍歷了枚舉類型Enabled并對字段enabledMap進行了賦值。

          想要使用自定義的類型處理器,也需要在resources/mybatis-config.xml中添加如下配置:

          <typeHandlers>
          <!--其他配置-->
          <typeHandler handler="com.zwwhnly.mybatisaction.type.EnabledTypeHandler"
          javaType="com.zwwhnly.mybatisaction.type.Enabled"/>

          </typeHandlers>

          運行測試代碼,輸出日志和上面的輸出日志一樣,這里不再重復貼出。

          瀏覽 62
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产怡红院 | 国产精品色在线 | 成人一级自拍网站 | 色综合狠狠色 | 天天日天天操心 |