从数据库中的预定义值列表中存储值的最佳方法是什么?

时间:2010-06-22 14:26:13

标签: java database enums

假设我有一个预定义的值列表( RW,FW,4W ),表示车辆的驱动类型:

RW - 后轮

FW - Front Wheet

4W - 四轮

现在,我想从上面的3个值中取一个值作为我用户的输入,然后将其存储在数据库中。

据我所知,我可以借助以下任何一种方法执行此操作:

- 对UI上的值进行硬编码,以便UI显示仅包含上述3个值的下拉列表。然后将该值存储在String vehicleType对象的Vehicle vehicle字段中,然后将其作为String存储在数据库中。

  • 缺点:

    i)中。没有验证对象级别的值

    ⅱ)。没有验证数据库级别的值。

    ⅲ)。虽然很少需要为列表添加新值,但用户仍然无法在运行时添加新值

    - 优点:

    i)中。数据库中不需要join来检索vehicle对象

  • 在包含所有3个值的数据库中创建一个单独的表VEHICLE_TYPE,并将其与VEHICLE表通过。外键。然后从VEHICLE_TYPE表填充UI的下拉列表。将值存储在vehicle对象中String

    - 缺点:

    i)中。在对象级别没有验证

    ⅱ)。在DB处需要join来检索vehicle对象

    - 优点:

    i)中。验证DB级别的值(通过外键)

    ⅱ)。用户可以在运行时向列表中添加新值

  • 在数据库中创建一个单独的表VEHICLE_TYPE,其中包含所有3个值,但不要链接它使用VEHICLE表格。外键。然后从VEHICLE_TYPE表填充UI的下拉列表。将值存储在vehicle对象和数据库中String

    - 缺点:

    i)中。在对象级别没有验证

    ⅱ)。没有DB级别的验证

    - 优点:

    i)中。数据库级别不需要join

    ⅱ)。用户可以将新值添加到列表

  • 在包含所有3个值的数据库中创建一个单独的表VEHICLE_TYPE,并将其与VEHICLE表通过。外键。然后从VEHICLE_TYPE表填充UI的下拉列表。在java中创建enum VehicleType,然后在VehicleType vehicleType类中添加字段Vehicle。根据用户的输入,在VehicleType字段中存储vehicleType枚举的值。

    -Cons:

    i)中。必须在两个位置更新列表:VehicleType枚举和VEHICLE_TYPE表。可能导致不一致。

    ⅱ)。用户无法在列表中添加新值(他可以在表中添加值但不能更改枚举)

    - 优点:

    i)中。在UI级别进行验证

    ⅱ)。对象级别的验证

    ⅲ)。数据库级别的验证

问题: 还有其他方法可以执行上述没有任何上述缺点的任务吗?

4 个答案:

答案 0 :(得分:2)

不确定。你的第二个修改:

在DB中创建一个具有所有3个值的单独表VEHICLE_TYPE,并将其与VEHICLE表通过。外键。然后从VEHICLE_TYPE表填充UI的下拉列表。将值存储在车辆对象中String。调用vehicle.setVehicleType()时,通过检查数据库中的可能值来验证分配的值是否有效。如果它无效,则抛出InvalidArgumentException或子类。

现在您已在对象中进行验证。而且,我不认为必须加入骗局。没有加入表格,你无法做很多事情。这就是你有很多桌子的原因。

答案 1 :(得分:1)

我也会选择第二种方法。你已经回答了第一个问题。

关于第二个问题,如果性能如此重要,您可以使用以下方法之一:

  1. 如果类型车辆在应用中使用不多,则延迟加载车辆的类型。

  2. 如果您没有使用数据库ID,因为您使用车辆类型的代码作为主键,您可以将codeType属性添加到您的车辆类,并加载此属性而不是类型(可以也可以直接从车辆表中懒散地装载,视具体需要而定。那你就没有任何加入。

答案 2 :(得分:1)

我不认为联接应该引起您的关注 - 您可能会发现,为了减少JOIN的开销而牺牲设计很可能会浪费精力。您对db的网络延迟可能高于JOIN开销。

如何处理用户输入的其他值取决于您希望如何处理它们:

  1. 将它们视为真正的附加值。它们被添加到数据库中的VEHICLE_TYPE,一旦添加,就可供所有用户选择。

  2. 将它们视为该特定字段的自定义值。即VEHICLE_TYPE包含“其他”类型,用户可以在单独的字段中输入其他详细信息。这些不会与其他用户共享,也不会显示在下拉列表中。

  3. 要获得对象级验证,请针对VEHICLE_TYPE进行验证。这可以使用现代OIM和ORM框架自动完成。这些允许您在模型上定义验证规则,然后将其传播到UI以便及早捕获验证错误,然后向后传递到数据库以确保数据存储的一致性。

    您可以将车辆ID存储为常规键或类型字符串本身(RW,FW等)。如果使用类型字符串本身,则不必加入VEHICLE_TYPE表。您可以直接显示字符串,或者如果需要本地化,您可以从资源包中获取表示字符串。

    编辑:要了解ORM和OIM如何将模型验证元数据返回到数据库并返回到用户界面,请参阅DZone:Hibernate 4 ValidationMetawidget。使用JSR 303,您可以在UI,业务层和后端验证对象。

答案 3 :(得分:1)

创建一个单独的表Vehicle_type(Vehicle_type_id int,description varchar(您需要确定适当的大小))以用作下拉菜单的查找。如果您希望在查找更改时在主表中更改值(例如adimin将seden更改为sedan),则将typeid存储在车辆表中。如果您希望这是历史数据(可能不再有类型轿车,但旧车仍应标记为轿车),则将类型的描述存储在车辆表中。在第二种情况下,您无法强制执行FK关系,因此您需要确保插入(以及仅更新该值)不能选择当前不在表中的值。应用程序可能会执行此操作,但如果值可能在应用程序外部更改,则可以编写触发器来执行此操作。