一、引言
作為程序員,不可避免的會接觸到遺留系統(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)如下:
-
定義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());
}
}
-
定義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;
}
}
-
配合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中增加常量方便使用。