Retained data suitable for enumerations

Most projects have some kind of data that is essentially static between versions and well suited for use as an enumeration, such as statuses, transaction types, error codes, etc. For example, for the sake of, I just use a common list of states

public enum Status { ACTIVE(10, "Active"); EXPIRED(11, "Expired"); /* other statuses... */ /* constructors, getters, etc. */ } 

I would like to know what others are doing in terms of storing data like this. I see several options, each of which has some obvious advantages and disadvantages:

  • Save possible statuses in the status table and save all possible status domain objects cached for use throughout the application.
  • Use only the listing and don’t keep the list of available statuses, creating a consistency of holy war data between me and my database administrator
  • Keep statuses and maintain enumeration in code, but do not bind them together, creating duplicate data.

My advantage is the second option, although my database administrator claims that our end users may need access to raw data to create reports, and not to save statuses will lead to an incomplete data model (counter argument: this can be solved with the documentation).

Is there an agreement that most people use here? What are the experiences of people with each and are there other alternatives?

Edit:

After thinking about this for a while, my real hard struggle is with handling id values ​​associated with statuses in the database. These values ​​will be inserted as default data during application installation. At this point, they will have identifiers that can be used as foreign keys in other tables. I feel that my code should know about these identifiers so that I can easily get status objects and assign them to other objects. What should I do with this? I could add another field, such as “code”, to look at things, or just look at the statuses by name, which is not good.

+19
java enums design types persistence
Jan 29 '09 at 15:37
source share
8 answers

We store enum values ​​using some explicit string or character value in the database. Then, to move from the database value back to the enumeration, we write a static method in the enum class to repeat and find the correct one.

If you expect a lot of enumeration values, you can create a static mapping HashMap<String,MyEnum> for quick translation.

Do not save the actual enumeration name (ie, “ACTIVE” in your example), as this is easily reorganized by the developers.

+8
Jan 29 '09 at 15:42
source share

I use a combination of the three approaches you have documented ...

Use the database as an authoritative source for Enum values. Store the values ​​in the "code" table. Each time you create, create a class file for Enum that will be included in your project.

Thus, if the enumeration changes the value in the database, your code will be incorrectly invalidated and you will receive the corresponding compilation errors from your continuous integration server. You have a strongly typed binding to your listed values ​​in the database, and you don't have to worry about manually synchronizing the values ​​between the code and the data.

+3
Mar 31 '09 at 17:47
source share

Joshua Bloch provides an excellent explanation of enumerations and how to use them in his book Effective Java Second Edition (p. 147)

Here you can find all kinds of tricks, how to define your listings, save them and how to quickly compare them between the database and your code (p. 154).

During a conversation at Jazoon 2007, Bloch gave the following reasons to use an additional attribute to list transfers in the database fields and vice versa: the transfer is a constant, but the code is not. To make sure that the editor editing the source cannot accidentally break the database display by reordering enums or renaming, you must add a specific attribute (for example, "dbName") to the enumeration and use it to match it.

Enums have an internal identifier (which is used in the switch () statement), but this identifier changes when the order of the elements changes (for example, by sorting them or adding elements in the middle).

Thus, the best solution is to add the toDB () and fromDB () method and an additional field. I suggest using short, readable strings for this new field, so you can decode the database dump without looking at the enumerations.

+2
Jan 29 '09 at 16:36
source share

While I am not familiar with the idea of ​​“attributes” in Java (and I don’t know what language you work in), I usually used the idea of ​​a code table (or domain-specific tables), and I assigned my enum values ​​to more specific data such as user-readable strings (for example, if my enum value is NewStudent, I would assign it “New Student” as the display value). Then I use Reflection to check the data in the database and insert or update records to bring them into line with my code, using the actual enumeration value as the key identifier.

+1
Apr 02 '09 at 15:27
source share

What I used in several cases is to specify the enumeration in the code and the representation of the storage at the save level (DB, file, etc.), and then use the conversion methods to match them with each other. These conversion methods should only be used when reading or writing to persistent storage, and the application can use safe type enumerations everywhere. In conversion methods, I used switch statements to display. It also allows an exception to be thrown if a new or unknown state is to be converted (usually because the application or data is newer than the other, and new or additional states have been declared).

+1
Apr 03 '09 at 17:02
source share

If there is even a small chance that the list of values ​​will need to be updated, not 1. Otherwise, it will be 3.

+1
Apr 6 '09 at 11:45
source share

Well, we don’t have a database administrator, so we prefer option 2).

We simply store the Enum value in the database, and when we load data from the database and into our domain objects, we simply cast the integer value to the enumeration type. This avoids any of the headaches of synchronization with options 1) and 3). The list is defined once - in the code.

However, we have a policy in which no one accesses the database directly; they must go through our web services to access any data. That is why it works well for us.

+1
Apr 6 '09 at 12:09
source share

In your database, the primary key for this domain table should not be a number. Just use varchar pk and the description column (for the purposes of your dba). If you need to guarantee the order of your values ​​without relying on the alphabetical sor, just add a numerical column named "order" or "sequence".

In your code, create a static class with constants whose name (with camel or not) matches the description and values ​​of the cards with pk. If you need more than this, create a class with the necessary structure and comparison operators and use its instances as the value of constants.

If you do this too much, create a script to generate the setup / declaration code.

+1
Apr 6 '09 at 15:32
source share



All Articles