如何優(yōu)雅的實(shí)現(xiàn)JPA對char類型字段的去空格

一、引言

作為程序員,不可避免的會接觸到遺留系統(tǒng),表字符串字段類型定義成char的情況。通常情況下,對應(yīng)定長的char字段的數(shù)據(jù),需要程序進(jìn)行去空格,但是每個char字段都進(jìn)行trim操作,程序結(jié)構(gòu)不夠優(yōu)雅。那么如何優(yōu)雅的實(shí)現(xiàn)char字段的trim呢?

二、去空格常見的寫法

當(dāng)Hibernate/JPA遇上char類型時,典型的寫法是在實(shí)體類的get()方法中進(jìn)行處理。假定name字段對應(yīng)表字段類型char。那么看一下常見的去空格寫法,示例如下:

@Entity
public class PExampleEntity {

    private String id;
    private String name;

    @Id
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        if (null != name) { //此處對char字段進(jìn)行去空格。
            return name.trim();
        }
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

看完上述例子,如果遺留表比較復(fù)雜,在每一個get方法上增加一段相識邏輯是很折磨的事。

三、如何優(yōu)雅的去空格

在尋找解決方法時,在網(wǎng)絡(luò)找到了多個不同版本去空格方式,經(jīng)過驗(yàn)證均存在一些副作用或者隱患(后續(xù)專寫一篇驗(yàn)證過程)。通過查看Hibernate源碼,總結(jié)了自己的解決方法,雖然還存在小瑕疵。接下來說說解決思路:即仿照Hibernate對String類型的處理,通過注解@Type指定字段類型,進(jìn)行去空格。

具體實(shí)現(xiàn)如下:

  1. 定義TrimString的Java類型的描述符處理器。

    • 復(fù)制StringTypeDescriptor代碼,將類名改成TrimStringTypeDescriptor。

    • 修改wrap方法,對字符串類型進(jìn)行trim()去空格。

        public class TrimStringTypeDescriptor extends AbstractTypeDescriptor<String> {
        
          public static final TrimStringTypeDescriptor INSTANCE = new TrimStringTypeDescriptor();
        
          public TrimStringTypeDescriptor() {
            super(String.class);
          }
        
          public String toString(String value) {
            return value;
          }
        
          public String fromString(String string) {
            return string;
          }
        
          public <X> X unwrap(String value, Class<X> type, WrapperOptions options) {
            //... 此時省略點(diǎn)代碼
          }
        
          public <X> String wrap(X value, WrapperOptions options) {
            if (value == null) {
              return null;
            }
            if (String.class.isInstance(value)) {
              // return (String) value; // 修改前
              return ((String) value).trim(); //修改后
            }
            if (Reader.class.isInstance(value)) {
              return DataHelper.extractString((Reader) value);
            }
            if (Clob.class.isInstance(value) || DataHelper.isNClob(value.getClass())) {
              try {
                return DataHelper.extractString(((Clob) value).getCharacterStream());
              } catch (SQLException e) {
                throw new HibernateException("Unable to access lob stream", e);
              }
            }
        
            throw unknownWrap(value.getClass());
          }
        }
  1. 定義TrimStringType類型映射char/varchar與String。

    • 復(fù)制StringType代碼,將類名改成TrimStringType。
    • 修改TrimStringType構(gòu)造方法,將StringTypeDescriptor.INSTANCE修改為TrimStringTypeDescriptor.INSTANCE。
    • 修改getName()方法。
        public class TrimStringType extends AbstractSingleColumnStandardBasicType<String> implements
            DiscriminatorType<String> {
        
          public static final String TYPE_NAME = "net.geektao.jpa.hibernate.TrimStringType";
        
          public TrimStringType() {
            // 此處,TrimStringTypeDescriptor.INSTANCE
            super(VarcharTypeDescriptor.INSTANCE, TrimStringTypeDescriptor.INSTANCE);
          }
        
          public String getName() {
            return "trimString";
          }
        
          @Override
          public String objectToSQLString(String value, Dialect dialect) throws Exception {
            return '\'' + value + '\'';
          }
        
          public String stringToObject(String xml) throws Exception {
            return xml;
          }
        
          public String toString(String value) {
            return value;
          }
        }
  1. 配合Hibernate注解@Type在方法或?qū)傩灾付愋汀?/p>

     @Entity
     public class PExampleEntity {
     
         private String id;
         private String name;
     
         @Id
         public String getId() {
             return id;
         }
     
         public void setId(String id) {
             this.id = id;
         }
     
         @Type(type = TrimStringType.TYPE_NAME)
         public String getName() {
             return name;
         }
     
         public void setName(String name) {
             this.name = name;
         }
     
     }
    

    提示:由于@Type注解參數(shù)type需要指定完整類名,在TrimStringType中增加常量方便使用。

  1. 參考資料
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,765評論 18 399
  • 一. Java基礎(chǔ)部分.................................................
    wy_sure閱讀 3,835評論 0 11
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,923評論 18 139
  • ¥開啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個線程,因...
    小菜c閱讀 6,523評論 0 17
  • 空間的雜亂是容易讓人覺得焦慮的。最近透過對家的清理,釋放更多的空間,讓自己感覺到專注。更重要的是,我發(fā)現(xiàn)哪些是我無...
    子祺的奇幻花園閱讀 190評論 3 3