[英]What's the best way to store a value from a list of pre-defined values in a database?
Let's say I have a pre-defined list of values ( RW, FW, 4W ) representing drive type of a vehicle:
假设我有一个预定义的值列表( RW,FW,4W ),它们表示车辆的驾驶类型:
RW - Rear Wheel
RW-后轮
FW - Front Wheet
FW-前轮
4W - Four Wheel
4W-四轮
Now, I want to take a value from the above 3 values as an input from my user and then store it in a database. 现在,我想从上述3个值中取一个值作为用户的输入,然后将其存储在数据库中。
Upto my knowledge, I can perform this with the help of any of the following methods:
据我所知,我可以借助以下任何一种方法来执行此操作:
- Hard-code the values at the UI so that the UI shows a drop-down having only the above 3 values.
-在用户界面上对值进行硬编码,以便用户界面显示仅包含上述3个值的下拉菜单。
Then store that value in the
String vehicleType
field of the Vehicle vehicle
object and then store it in the DB as String
. 然后将该值存储在
Vehicle vehicle
对象的String vehicleType
字段中,然后将其作为String
存储在DB中。
Cons: 缺点:
i). 一世)。 No validation of the value at object level
没有在对象级别验证值
ii). ii)。 No validation of the value at DB level.
没有在数据库级别验证该值。
iii). iii)。 Though the need for adding a new value to the list is rare, but still user can't add a new value at runtime
尽管很少需要在列表中添加新值,但是用户仍然无法在运行时添加新值
- Pros:
-优点:
i). 一世)。 No need of
join
at DB to retrieve the vehicle
object 无需
join
DB即可检索vehicle
对象
OR
要么
Make a separate table VEHICLE_TYPE
in the DB having all the 3 values and link it with the VEHICLE
table via. 在具有所有3个值的DB中创建一个单独的表
VEHICLE_TYPE
,并通过将其与VEHICLE
表链接。 foreign key. 外键。 And then populate the drop-down at UI from the
VEHICLE_TYPE
table. 然后在
VEHICLE_TYPE
表中的UI下拉列表中进行填充。 Store the value in the vehicle
object as String
将值作为
String
存储在vehicle
对象中
- Cons:
-缺点:
i). 一世)。 No validation at object level
没有在对象级别进行验证
ii). ii)。 Need a
join
at DB to retrieve a vehicle
object 需要
join
在DB检索vehicle
对象
- Pros:
-优点:
i). 一世)。 validation of the value at DB level (by foreign key)
在数据库级别验证值(通过外键)
ii). ii)。 User can add a new value to the list at runtime
用户可以在运行时将新值添加到列表中
OR
要么
Make a separate table VEHICLE_TYPE
in the DB having all the 3 values but DON'T link it with the
VEHICLE
table via. 在DB中创建一个单独的表
VEHICLE_TYPE
,该表具有所有3个值,但不要通过VEHICLE_TYPE
将其链接到VEHICLE
表。 foreign key. 外键。 And then populate the drop-down at UI from the
VEHICLE_TYPE
table. 然后在
VEHICLE_TYPE
表中的UI下拉列表中进行填充。 Store the value in the vehicle
object and in the DB as String
将值存储为
vehicle
对象和DB中的String
- Cons:
-缺点:
i). 一世)。 No validation at object level
没有在对象级别进行验证
ii). ii)。 No validation at DB level
在数据库级别没有验证
- Pros:
-优点:
i). 一世)。 No
join
required at DB level 在数据库级别无需
join
ii). ii)。 User can add new value to the list
用户可以将新值添加到列表中
OR
要么
Make a separate table VEHICLE_TYPE
in the DB having all the 3 values and link it with the VEHICLE
table via. 在具有所有3个值的DB中创建一个单独的表
VEHICLE_TYPE
,并通过将其与VEHICLE
表链接。 foreign key. 外键。 And then populate the drop-down at UI from the
VEHICLE_TYPE
table. 然后在
VEHICLE_TYPE
表中的UI下拉列表中进行填充。 Make an enum VehicleType
in java and then add a field VehicleType vehicleType
in the Vehicle
class. 用Java
enum VehicleType
,然后在Vehicle
类中添加一个VehicleType vehicleType
字段。 Store a value from the VehicleType
enum in the vehicleType
field based on the input of the user. 根据用户的输入,将
VehicleType
枚举中的值存储在vehicleType
字段中。
-Cons:
-缺点:
i). 一世)。 Will have to update the list at two places:
VehicleType
enum and the VEHICLE_TYPE
table. 必须在两个位置更新列表:
VehicleType
枚举和VEHICLE_TYPE
表。 May cause inconsistency. 可能导致不一致。
ii). ii)。 User can't add a new value to the list (he can add a value in the table but can't change the enum)
用户无法向列表中添加新值(他可以在表中添加值,但不能更改枚举)
- Pros:
-优点:
i). 一世)。 validation at UI level
UI级别的验证
ii). ii)。 validation at object level
在对象级别进行验证
iii). iii)。 validation at DB level
在数据库级别进行验证
Question: Is there other way by which we can perform the above task which doesn't have any of the above disadvantages?
问题:我们是否可以通过其他方式执行上述任务,而没有上述缺点?
Sure. 当然。 Your second one with a modification:
您的第二个修改:
Make a separate table VEHICLE_TYPE
in the DB having all the 3 values and link it with the VEHICLE
table via. 在具有所有3个值的DB中创建一个单独的表
VEHICLE_TYPE
,并通过将其与VEHICLE
表链接。 foreign key. 外键。 And then populate the drop-down at UI from the
VEHICLE_TYPE
table. 然后在
VEHICLE_TYPE
表中的UI下拉列表中进行填充。 Store the value in the vehicle object as String
. 将值作为
String
存储在车辆对象中。 When calling vehicle.setVehicleType()
, verify that the value assigned is valid by checking the possible values from the DB. 调用
vehicle.setVehicleType()
,通过检查数据库中可能的值来验证分配的值是否有效。 If it's invalid, throw an InvalidArgumentException
or a subclass. 如果无效,则抛出
InvalidArgumentException
或子类。
Now you have validation in the object. 现在,您已经在对象中进行了验证。 And also, I don't consider having to do a join a con.
而且,我也不必考虑参加骗局。 You can't do much of anything without joining tables.
如果不加入表,您将无能为力。 That's why you have many tables.
这就是为什么您有很多表的原因。
I would chose also the second approach. 我也会选择第二种方法。 You have been already answered about the first con.
您已经获得有关第一个骗局的答复。
Regarding the second con, if performance is so important, you could use one of those approaches: 关于第二个缺点,如果性能是如此重要,则可以使用以下方法之一:
If the type vehicle is not used much in the application, lazy loading the type of the vehicle. 如果在应用程序中不使用类型车辆,请延迟加载车辆类型。
If you are not using database ids, because you are using the code of the type vehicle as primary key, you could add a codeType property to your vehicle class, and load this property instead of the type (which could also be loaded lazyly, depending on needs), directly from the vehicle table. 如果您没有使用数据库ID,因为您使用的是vehicle类型的代码作为主键,则可以向您的vehicle类添加一个codeType属性,然后加载该属性而不是type(也可以延迟加载,具体取决于(根据需要),直接从车辆表上获取。 Then you won't have any join.
这样,您将没有任何加入。
I don't feel that joins should be your cause for concern - you might well find that compromising the design to reduce the overhead of a JOIN is most likely going to be wasted effort. 我不认为联接应该引起您的关注,您很可能会发现,为了减少JOIN的开销而折衷设计可能很浪费时间。 Your network latency to the db could be higher than the JOIN overhead.
您到db的网络延迟可能高于JOIN开销。
How you deal with additional values entered by the user depends upon how you want them to be handled: 您如何处理用户输入的其他值取决于您希望如何处理它们:
Treat them as true additional values. 将它们视为真正的附加值。 They are added to the VEHICLE_TYPE in the database, and once added, are available for all users to select.
它们将被添加到数据库中的VEHICLE_TYPE,并且一旦添加,便可供所有用户选择。
Treat them as custom values for that particular field. 将它们视为该特定字段的自定义值。 Ie the VEHICLE_TYPE includes a type "Other" and the user can enter additional details in a separate field.
即VEHICLE_TYPE包含类型“其他”,用户可以在单独的字段中输入其他详细信息。 These are not shared with other users and do not appear in the dropdown list.
这些不会与其他用户共享,也不会出现在下拉列表中。
To get object-level validation, validate against the VEHICLE_TYPE. 要获得对象级验证,请针对VEHICLE_TYPE进行验证。 This can be done automatically with modern OIM and ORM frameworks.
这可以通过现代OIM和ORM框架自动完成。 These allow you to define validation rules on the model which are then propagated forward to the UI for early catching of validation errors, and backwards to the database to ensure data store consistency.
这些允许您在模型上定义验证规则,然后将其传播到UI以便尽早捕获验证错误,然后传播到数据库以确保数据存储的一致性。
You can store Vehicle ID as regular key, or the type string itself (RW,FW etc.). 您可以将“车辆ID”存储为常规键,也可以存储类型字符串本身(RW,FW等)。 If using the type string itself, you don't have to join to the VEHICLE_TYPE table.
如果使用类型字符串本身,则不必加入VEHICLE_TYPE表。 You could present the string directly, or you can fetch the presentation strings from resource bundles if localization is needed.
您可以直接显示字符串,或者如果需要本地化,则可以从资源包中获取显示字符串。
EDIT: To see how ORM and OIM can take model validation metadata back to the db and out to the UI, see DZone: Hibernate 4 Validation , and Metawidget . 编辑:要查看ORM和OIM如何将模型验证元数据带回db并返回到UI,请参见DZone: Hibernate 4 Validation和Metawidget 。 With JSR 303 you can validate your objects in the UI, business layer and back end.
使用JSR 303,您可以在UI,业务层和后端中验证对象。
Make a separate table Vehicle_type (Vehicle_type_id int, description varchar (you need to determine the appropraite size))to use as the lookup for the drop down menu. 制作一个单独的表Vehicle_type(Vehicle_type_id int,描述varchar(您需要确定适当的大小)),以用作下拉菜单的查找。 If you want the value to change in the main table when the look up changes (say an adimin changes seden to sedan), then store the typeid in the vehicle table.
如果您希望在查找更改时在主表中更改该值(例如将adimin从seden更改为sedan),则将typeid存储在车辆表中。 If you want this to be historical data (maybe there is no longer a type sedan but older vehicles should still be marked as sedan) then store the decription of the type in the vehicle table.
如果您希望将其用作历史数据(也许不再有类型的轿车,但仍应将较旧的车辆标记为轿车),则将类型的描述存储在车辆表中。 In the second case you can't enforce with an FK relationship, so you will need to ensure that inserts (and updates of that value only) cannot choose values not currently in the table.
在第二种情况下,您不能使用FK关系强制实施,因此您需要确保插入(和仅更新该值)不能选择表中当前不存在的值。 The application will likely do this although you could write a trigger to do so if values are likely to change outside the application.
应用程序可能会执行此操作,但是如果值可能会在应用程序外部更改,则可以编写触发器来执行此操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.