tipo sirve semana roer resueltos que programacion programa para orientada objetos enum ejercicios duro disco dias dela java database enums

sirve - programacion orientada a objetos java ejercicios resueltos



Formas de guardar enumeraciones en la base de datos (10)

A menos que tenga razones específicas de rendimiento para evitarlo, le recomendaría usar una tabla separada para la enumeración. Use integridad de clave externa a menos que la búsqueda extra realmente lo mate.

Tabla de trajes:

suit_id suit_name 1 Clubs 2 Hearts 3 Spades 4 Diamonds

Tabla de jugadores

player_name suit_id Ian Boyd 4 Shelby Lake 2

  1. Si alguna vez refactoriza su enumeración para que sean clases con comportamiento (como prioridad), su base de datos ya lo modela correctamente
  2. Su DBA está feliz porque su esquema está normalizado (almacenando un solo entero por jugador, en lugar de una cadena completa, que puede tener o no errores tipográficos).
  3. Los valores de su base de datos ( suit_id ) son independientes de su valor de enumeración, lo que le ayuda a trabajar en los datos de otros idiomas también.

¿Cuál es la mejor manera de guardar enumeraciones en una base de datos?

Sé que Java proporciona los métodos name() y valueOf() para convertir los valores enum a String y viceversa. ¿Pero hay otras opciones (flexibles) para almacenar estos valores?

¿Existe alguna manera inteligente de hacer que las enumeraciones sean números únicos ( ordinal() no es seguro de usar)?

Actualizar:

¡Gracias por todas las increíbles y rápidas respuestas! Era como yo sospechaba.

Sin embargo, una nota para ''toolkit''; Esa es una forma. El problema es que tendría que agregar los mismos métodos a cada tipo de Enum que creo. Eso es una gran cantidad de código duplicado y, por el momento, Java no admite ninguna solución para esto (una enumeración Java no puede extender otras clases).


Como dices, ordinal es un poco arriesgado. Considera por ejemplo:

public enum Boolean { TRUE, FALSE } public class BooleanTest { @Test public void testEnum() { assertEquals(0, Boolean.TRUE.ordinal()); assertEquals(1, Boolean.FALSE.ordinal()); } }

Si almacenó esto como ordinales, puede tener filas como:

> SELECT STATEMENT, TRUTH FROM CALL_MY_BLUFF "Alice is a boy" 1 "Graham is a boy" 0

Pero, ¿qué ocurre si actualizaste Boolean?

public enum Boolean { TRUE, FILE_NOT_FOUND, FALSE }

Esto significa que todas tus mentiras serán malinterpretadas como ''archivo no encontrado''

Mejor usar solo una representación de cadena



Me he enfrentado al mismo problema en el que mi objetivo es mantener el valor de Enum String en la base de datos en lugar del valor ordinal.

Para superar este problema, he usado @Enumerated(EnumType.STRING) y mi objetivo se resolvió.

Por ejemplo, tienes una clase Enum :

public enum FurthitMethod { Apple, Orange, Lemon }

En la clase de entidad, defina @Enumerated(EnumType.STRING) :

@Enumerated(EnumType.STRING) @Column(name = "Fruits") public FurthitMethod getFuritMethod() { return fruitMethod; } public void setFruitMethod(FurthitMethod authenticationMethod) { this.fruitMethod= fruitMethod; }

Mientras intenta establecer su valor en la base de datos, el valor de cadena se conservará en la base de datos como " APPLE ", " ORANGE " o " LEMON ".


Para una base de datos grande, soy reacio a perder las ventajas de tamaño y velocidad de la representación numérica. A menudo termino con una tabla de base de datos que representa el Enum.

Puede exigir la coherencia de la base de datos declarando una clave externa, aunque en algunos casos podría ser mejor no declararlo como una restricción de clave externa, que impone un costo en cada transacción. Puede garantizar la coherencia al hacer un control periódicamente, en el momento que elija, con:

SELECT reftable.* FROM reftable LEFT JOIN enumtable ON reftable.enum_ref_id = enumtable.enum_id WHERE enumtable.enum_id IS NULL;

La otra mitad de esta solución es escribir algún código de prueba que compruebe que el enum de Java y la tabla enum de la base de datos tienen los mismos contenidos. Eso queda como un ejercicio para el lector.


Si guarda enumeraciones como cadenas en la base de datos, puede crear métodos de utilidad para (de) serializar cualquier enumeración:

public static String getSerializedForm(Enum<?> enumVal) { String name = enumVal.name(); // possibly quote value? return name; } public static <E extends Enum<E>> E deserialize(Class<E> enumType, String dbVal) { // possibly handle unknown values, below throws IllegalArgEx return Enum.valueOf(enumType, dbVal.trim()); } // Sample use: String dbVal = getSerializedForm(Suit.SPADE); // save dbVal to db in larger insert/update ... Suit suit = deserialize(Suit.class, dbVal);


Solo almacenamos el nombre enum en sí mismo, es más legible.

Nos metimos con el almacenamiento de valores específicos para enumeraciones donde hay un conjunto limitado de valores, por ejemplo, esta enumeración que tiene un conjunto limitado de estados que utilizamos un carácter para representar (más significativo que un valor numérico):

public enum EmailStatus { EMAIL_NEW(''N''), EMAIL_SENT(''S''), EMAIL_FAILED(''F''), EMAIL_SKIPPED(''K''), UNDEFINED(''-''); private char dbChar = ''-''; EmailStatus(char statusChar) { this.dbChar = statusChar; } public char statusChar() { return dbChar; } public static EmailStatus getFromStatusChar(char statusChar) { switch (statusChar) { case ''N'': return EMAIL_NEW; case ''S'': return EMAIL_SENT; case ''F'': return EMAIL_FAILED; case ''K'': return EMAIL_SKIPPED; default: return UNDEFINED; } } }

y cuando tiene muchos valores, necesita tener un Mapa dentro de su enumeración para mantener ese método getFromXYZ pequeño.


Toda mi experiencia me dice que la forma más segura de persistir enums en cualquier lugar es usar un valor de código o id adicional (algún tipo de evolución de la respuesta de @jeebee). Este podría ser un buen ejemplo de una idea:

enum Race { HUMAN ("human"), ELF ("elf"), DWARF ("dwarf"); private final String code; private Race(String code) { this.code = code; } public String getCode() { return code; } }

Ahora puede ir con cualquier persistencia haciendo referencia a sus constantes enum por su código. Incluso si decide cambiar algunos de los nombres constantes, siempre puede guardar el valor del código (por ejemplo, DWARF("dwarf") a GNOME("dwarf") )

Ok, zambúllete un poco más profundo con esta concepción. Aquí hay algún método de utilidad que le ayuda a encontrar cualquier valor enum, pero primero permite ampliar nuestro enfoque.

interface CodeValue { String getCode(); }

Y deje que nuestra enum lo implemente:

enum Race implement CodeValue {...}

Este es el momento para el método de búsqueda mágica:

static <T extends Enum & CodeValue> T resolveByCode(Class<T> enumClass, String code) { T[] enumConstants = enumClass.getEnumConstants(); for (T entry : enumConstants) { if (entry.getCode().equals(code)) return entry; } // In case we failed to find it, return null. // I''d recommend you make some log record here to get notified about wrong logic, perhaps. return null; }

Y Race race = resolveByCode(Race.class, "elf") como un amuleto: Race race = resolveByCode(Race.class, "elf")


Yo argumentaría que el único mecanismo seguro aquí es usar el valor String name() . Al escribir en la base de datos, puede usar un sproc para insertar el valor y al leer, use una vista. De esta manera, si las enumeraciones cambian, hay un nivel de direccionamiento indirecto en el sproc / view para poder presentar los datos como el valor enum sin "imponer" esto en el DB.


Nunca almacenamos enumeraciones como valores ordinales numéricos; hace que la depuración y el soporte sean demasiado difíciles. Almacenamos el valor de enumeración real convertido a cadena:

public enum Suit { Spade, Heart, Diamond, Club } Suit theSuit = Suit.Heart; szQuery = "INSERT INTO Customers (Name, Suit) " + "VALUES (''Ian Boyd'', %s)".format(theSuit.name());

y luego vuelve a leer con:

Suit theSuit = Suit.valueOf(reader["Suit"]);

El problema estaba en el pasado mirando a Enterprise Manager y tratando de descifrar:

Name Suit ================== ========== Shelby Jackson 2 Ian Boyd 1

versos

Name Suit ================== ========== Shelby Jackson Diamond Ian Boyd Heart

el último es mucho más fácil. El primero requería obtener el código fuente y encontrar los valores numéricos que se asignaron a los miembros de la enumeración.

Sí, toma más espacio, pero los nombres de los miembros de la enumeración son cortos, y los discos duros son baratos, y vale la pena ayudarlo cuando tiene un problema.

Además, si usa valores numéricos, está vinculado a ellos. No puede insertar o reorganizar los miembros sin tener que forzar los valores numéricos antiguos. Por ejemplo, cambiar la enumeración de Suit a:

public enum Suit { Unknown, Heart, Club, Diamond, Spade }

tendría que convertirse en:

public enum Suit { Unknown = 4, Heart = 1, Club = 3, Diamond = 2, Spade = 0 }

para mantener los valores numéricos heredados almacenados en la base de datos.