2014-12-13 62 views
0

如何使用从数据库中读取的类型以及如何在代码中提供类型安全性?Java数据库字符串类型和类型安全性

前提

考虑与各种类型列的数据库表。列 “A” 中包含的字符串值 “A”,“B “C”。 “B” 列包含字符串值 “X”, “Y”, “Z”。

示例用法

在为了保证类型安全,我宁愿环绕枚举这些值,并使用类型,而不是直接使用值作为字符串

事情是这样的:

public class TypeSafetyExample { 

    /** 
    * TypeA: map string type to enum type. 
    */ 
    public enum TypeA { 
     A("A"), 
     B("B"), 
     C("C"); 

     String id; 

     TypeA(String id) { 
      this.id = id; 
     } 

     public static TypeA get(String id) { 

      for(TypeA item: EnumSet.allOf(TypeA.class)) { 
       if(item.id.equals(id)) { 
        return item; 
       } 

      } 

      throw new IllegalArgumentException("Unsupported enum id: " + id); 
     } 
    } 

    /** 
    * TypeB: map string type to enum type and give it some other attribute. 
    */ 
    public enum TypeB { 
     X("X", true), 
     Y("Y", true), 
     Z("Z", false); 

     String id; 
     boolean someAttribute; 

     TypeB(String id, boolean someAttribute) { 
      this.id = id; 
      this.someAttribute = someAttribute; 
     } 

     public boolean isSomeAttribute() { 
      return this.someAttribute; 
     } 

     public static TypeB get(String id) { 

      for(TypeB item: EnumSet.allOf(TypeB.class)) { 
       if(item.id.equals(id)) { 
        return item; 
       } 

      } 

      throw new IllegalArgumentException("Unsupported enum id: " + id); 
     } 
    } 

    /** 
    * Object using enums as types. 
    */ 
    public static class MyObjectTyped { 
     TypeA typeA; 
     TypeB typeB; 

     public String toString() { 
      return "Type A: " + typeA + ", Type B: " + typeB; 
     } 
    } 

    /** 
    * Object using strings as types. 
    */ 
    public static class MyObjectUntyped { 
     String typeA; 
     String typeB; 

     public String toString() { 
      return "Type A: " + typeA + ", Type B: " + typeB; 
     } 
    } 

    /** 
    * Example usage. 
    * @param args 
    */ 
    public static void main(String[] args) { 

     MyObjectTyped objTyped; 
     MyObjectUntyped objUntyped; 

     // ... here we would read data from the database and create our typed objects ... 

     objTyped = new MyObjectTyped(); 
     objTyped.typeA = TypeA.get("A"); 
     objTyped.typeB = TypeB.get("X"); 

     System.out.println(objTyped); // Type A: A, Type B: X 

     objTyped = new MyObjectTyped(); 
     objTyped.typeA = TypeA.get("A"); 
     objTyped.typeB = TypeB.get("?"); // Runtime Error during database read: java.lang.IllegalArgumentException: Unsupported enum id: ? 

     objUntyped = new MyObjectUntyped(); 
     objUntyped.typeA = "???"; // no error at all, probably we'll get a runtime error or some inconsistency later, but never during database loading 
     objUntyped.typeB = "???"; // no error at all, probably we'll get a runtime error or some inconsistency later, but never during database loading 

     System.exit(0); 
    } 
} 

基本上是创建一个枚举所有类型并且数据库字符串类型被映射到那个枚举。在java代码中,只使用枚举,而不使用字符串。枚举

优势:从数据库加载枚举

缺点期间

  • 一致性检查:每当添加新类型

    • 代码改变必要

    s的优势trings:当一个新的类型被添加字符串

缺点

  • 无需更改代码需要:

    • 没有类型安全。数据库可以包含任何内容。运行期间可能出现错误。

    您对这些概念有什么看法?你更倾向哪个?或者有更好的方法吗?我宁愿坚持类型安全,因为代码的稳定性是值得的。另一方面,每当添加新类型时,代码更改也不是好习惯。

    谢谢您的意见!

回答

1

这一切都取决于你如何使用这些字符串。代码的逻辑取决于实际值,还是仅仅是您从数据库中读取的内容,或许以某种方式转换并呈现​​给用户或发送给其他使用者?

如果是前者,enum可能是有保证的。

另请注意,如果要确保字符串属于已知有效集,则可以在数据库级别强制执行约束。所以,“数据库可以包含任何东西”并不是真的。

一般来说,如果您使用的是数据库,它应该是您放在那里的数据一致性和有效性的“真相来源”。这就是数据库的用途,这就是他们擅长的。在你的数据存储中扔垃圾,依靠应用程序代码在出路上消毒它并不是一个好主意。

+0

谢谢。是的,逻辑取决于代码以及向用户显示的内容。该机制正在被用于各种类型。不幸的是,数据库设计不在我的手中,来自几个国家的几位开发人员混淆了它。所以我宁愿我可以立即证明不一致。我不知道你可以对数据库列的值进行约束。我会研究它。 – Roland 2014-12-13 00:39:10