【问题标题】:Java database string types and type safetyJava 数据库字符串类型和类型安全
【发布时间】:2014-12-13 00:13:03
【问题描述】:

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

前提条件

Given 是一个包含各种类型列的数据库表。 “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 代码中只使用枚举,从不使用字符串。

枚举的优势:

  • 从数据库加载期间的一致性检查

枚举的缺点:

  • 添加新类型时需要更改代码

字符串的优点:

  • 添加新类型时无需更改代码

字符串的缺点:

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

您如何看待这些概念?你更倾向哪个?还是有更好的方法?我宁愿坚持类型安全,因为代码的稳定性是值得的。另一方面,每当添加新类型时进行代码更改也不是好的做法。

感谢您的意见!

【问题讨论】:

    标签: java type-safety


    【解决方案1】:

    这完全取决于您如何使用这些字符串。您的代码的逻辑 是否取决于实际值,或者它只是您从数据库中读取的东西,也许,以某种方式转换并呈现​​给用户或发送给其他消费者?

    如果是前者,则可能需要枚举。

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

    一般来说,如果您使用数据库,它应该是您放置在那里的数据的一致性和有效性的“事实来源”。这就是数据库的用途,也是它们擅长的。在您的数据存储中扔垃圾,并依靠应用程序代码在出路时对其进行清理根本不是一个好主意。

    【讨论】:

    • 谢谢。是的,逻辑取决于代码以及向用户显示的内容。该机制被用于各种类型。不幸的是,数据库设计超出了我的掌控,来自几个国家的几个开发人员都搞砸了。所以我宁愿我可以立即证明不一致。我不知道您可以对数据库列的值施加约束。我会调查的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-08
    • 2021-03-30
    • 1970-01-01
    • 1970-01-01
    • 2012-04-20
    相关资源
    最近更新 更多