Jaki jest najlepszy sposób zapisywania wyliczeń w bazie danych?
Wiem, że Java zapewnia name()
i valueOf()
metody konwersji wartości wyliczenia na ciąg znaków iz powrotem. Ale czy są jakieś inne (elastyczne) opcje przechowywania tych wartości?
Czy istnieje sprytny sposób przekształcania wyliczeń w unikatowe liczby ( ordinal()
nie jest bezpieczny w użyciu)?
Aktualizacja:
Dzięki za wszystkie niesamowite i szybkie odpowiedzi! Było tak, jak podejrzewałem.
Jednak uwaga do „zestawu narzędzi”; To jest jeden sposób. Problem w tym, że musiałbym dodać te same metody do każdego tworzonego przeze mnie typu Enum. To dużo zduplikowanego kodu, a obecnie Java nie obsługuje żadnych rozwiązań w tym zakresie (wyliczenie Java nie może rozszerzać innych klas).
Odpowiedzi:
Nigdy już nie przechowujemy wyliczeń jako liczbowych wartości porządkowych; to sprawia, że debugowanie i wsparcie jest zbyt trudne. Przechowujemy rzeczywistą wartość wyliczenia przekonwertowaną na ciąg:
a następnie przeczytaj:
W przeszłości problem polegał na wpatrywaniu się w Enterprise Manager i próbach rozszyfrowania:
wersety
ta ostatnia jest znacznie łatwiejsza. Pierwsza wymagała dotarcia do kodu źródłowego i znalezienia wartości liczbowych, które zostały przypisane członkom wyliczenia.
Tak, zajmuje więcej miejsca, ale nazwy członków wyliczenia są krótkie, a dyski twarde są tanie i o wiele bardziej opłaca się pomóc, gdy masz problem.
Ponadto, jeśli używasz wartości liczbowych, jesteś z nimi związany. Nie można ładnie wstawiać ani zmieniać kolejności elementów bez konieczności wymuszania starych wartości liczbowych. Na przykład zmiana wyliczenia koloru na:
musiałby się stać:
w celu zachowania starszych wartości liczbowych przechowywanych w bazie danych.
Jak posortować je w bazie danych
Pojawia się pytanie: powiedzmy, że chciałem uporządkować wartości. Niektórzy ludzie mogą chcieć posortować je według wartości porządkowej wyliczenia. Oczywiście porządkowanie kart według wartości numerycznej wyliczenia jest bez znaczenia:
To nie jest kolejność, której chcemy - chcemy, aby były one w kolejności wyliczania:
Ta sama praca, która jest wymagana przy zapisywaniu wartości całkowitych, jest wymagana przy zapisywaniu ciągów:
Ale to nie jest kolejność, której chcemy - chcemy, aby były one w kolejności wyliczania:
Uważam, że taki ranking należy do interfejsu użytkownika. Jeśli sortujesz elementy na podstawie ich wartości wyliczenia: robisz coś źle.
Ale jeśli naprawdę chcesz to zrobić, utworzyłbym
Suits
tabelę wymiarów:W ten sposób, jeśli chcesz zmienić swoje karty, aby używać Kissing Kings New Deck Order , możesz to zmienić do celów wyświetlania bez wyrzucania wszystkich swoich danych:
Teraz oddzielamy wewnętrzny szczegół programowania (nazwa wyliczenia, wartość wyliczenia) ustawieniem wyświetlania przeznaczonym dla użytkowników:
źródło
12.37 ms
zamiast tego trwa12.3702 ms
. To właśnie mam na myśli mówiąc „w hałasie” . Uruchom zapytanie ponownie i trwa13.29 ms
, lub11.36 ms
. Innymi słowy, losowość harmonogramu wątków drastycznie zapełni każdą mikrooptymalizację, którą teoretycznie posiadasz, a która nie jest w żaden sposób widoczna dla nikogo w żaden sposób.Jeśli nie masz konkretnych powodów wydajnościowych, aby tego uniknąć, zalecałbym użycie osobnej tabeli do wyliczenia. Użyj integralności klucza obcego, chyba że dodatkowe wyszukiwanie naprawdę cię zabije.
Tabela garniturów:
Tabela graczy
suit_id
) są niezależne od wartości wyliczenia, co ułatwia pracę z danymi z innych języków.źródło
public enum foo {bar}
iCREATE TABLE foo (name varchar);
to może łatwo stracić synchronizację.Twierdziłbym, że jedynym bezpiecznym mechanizmem jest tutaj użycie
name()
wartości String . Podczas pisania do bazy danych można użyć sproc do wstawienia wartości, a podczas czytania użyć widoku. W ten sposób, jeśli wyliczenia ulegną zmianie, istnieje pewien poziom pośredni w sproc / widoku, aby móc przedstawić dane jako wartość wyliczenia bez „narzucania” tego na DB.źródło
Jak mówisz, porządek jest nieco ryzykowny. Rozważmy na przykład:
Jeśli zapisałeś to jako liczby porządkowe, możesz mieć wiersze takie jak:
Ale co się stanie, jeśli zaktualizujesz wartość Boolean?
Oznacza to, że wszystkie twoje kłamstwa zostaną błędnie zinterpretowane jako „nie znaleziono pliku”
Lepiej po prostu użyć reprezentacji ciągu
źródło
W przypadku dużej bazy danych niechętnie tracę zalety rozmiaru i szybkości reprezentacji numerycznej. Często kończę z tabelą bazy danych reprezentującą Enum.
Możesz wymusić spójność bazy danych, deklarując klucz obcy - chociaż w niektórych przypadkach może być lepiej nie deklarować tego jako ograniczenia klucza obcego, które nakłada koszt na każdą transakcję. Możesz zapewnić spójność, okresowo sprawdzając, w wybranych przez siebie momentach:
Druga połowa tego rozwiązania polega na napisaniu kodu testowego, który sprawdza, czy wyliczenie Java i tabela wyliczeń bazy danych mają tę samą zawartość. Pozostawiamy to jako ćwiczenie dla czytelnika.
źródło
enumID
to cztery bajty, więc masz dodatkowe trzy bajty na wiersz, używając nazw. 3 bajty x 1 milion wierszy to 3 MB.enumId
pewnością mieści się w dwóch bajtach (dłuższe wyliczenia nie są możliwe w Javie), a większość z nich mieści się w jednym bajcie (który jest obsługiwany przez niektóre bazy danych). Oszczędność miejsca jest znikoma, ale szybsze porównanie i ustalona długość powinny pomóc.Po prostu przechowujemy samą nazwę wyliczenia - jest bardziej czytelna.
Mieliśmy kłopoty z przechowywaniem określonych wartości dla wyliczeń, w których istnieje ograniczony zestaw wartości, np. To wyliczenie, które ma ograniczony zestaw statusów, które reprezentujemy za pomocą znaku (bardziej znaczące niż wartość liczbowa):
a jeśli masz dużo wartości, musisz mieć Map w swoim wyliczeniu, aby metoda getFromXYZ była mała.
źródło
W przypadku zapisywania wyliczeń jako ciągów w bazie danych można utworzyć metody narzędziowe do (de) serializacji dowolnego wyliczenia:
źródło
Z całego mojego doświadczenia wynika, że najbezpieczniejszym sposobem na utrwalenie wyliczeń w dowolnym miejscu jest użycie dodatkowej wartości kodu lub identyfikatora (pewnego rodzaju ewolucja odpowiedzi @jeebee). To mógłby być dobry przykład pomysłu:
Teraz możesz korzystać z dowolnej trwałości odwołującej się do stałych wyliczenia za pomocą kodu. Nawet jeśli zdecydujesz się zmienić niektóre nazwy stałych, zawsze możesz zapisać wartość kodu (np.
DWARF("dwarf")
DoGNOME("dwarf")
)Ok, zanurkuj trochę głębiej z tą koncepcją. Oto kilka narzędzi, które pomogą Ci znaleźć dowolną wartość wyliczenia, ale najpierw rozszerzymy nasze podejście.
I niech nasz enum to zaimplementuje:
To jest czas na magiczną metodę wyszukiwania:
I użyj go jak uroku:
Race race = resolveByCode(Race.class, "elf")
źródło
Napotkałem ten sam problem, w którym moim celem jest utrwalenie wartości ciągu Enum w bazie danych zamiast wartości porządkowej.
Aby rozwiązać ten problem, użyłem
@Enumerated(EnumType.STRING)
i mój cel został rozwiązany.Na przykład masz
Enum
klasę:W klasie jednostki zdefiniuj
@Enumerated(EnumType.STRING)
:Podczas próby ustawienia wartości na bazę danych wartość ciągu zostanie utrwalona w bazie danych jako „
APPLE
”, „ORANGE
” lub „LEMON
”.źródło
Wiele wartości z relacją OR dla jednego pola wyliczenia. Koncepcja platformy .NET polegająca na przechowywaniu typów wyliczeniowych w bazie danych, takich jak bajt lub int, oraz przy użyciu FlagsAttribute w kodzie.
http://blogs.msdn.com/b/efdesign/archive/2011/06/29/enumeration-support-in-entity-framework.aspx
źródło
Możesz użyć dodatkowej wartości w stałej wyliczeniowej, która może przetrwać zarówno zmiany nazwy, jak i ponowne wykorzystanie wyliczeń:
Aby uzyskać identyfikator z wyliczenia:
Aby uzyskać wyliczenie z identyfikatora:
Sugeruję użycie wartości bez znaczenia, aby uniknąć nieporozumień, jeśli nazwy wyliczeń muszą zostać zmienione.
W powyższym przykładzie użyłem pewnego wariantu „Podstawowej numeracji wierszy”, pozostawiając spacje, więc liczby prawdopodobnie pozostaną w tej samej kolejności co wyliczenia.
Ta wersja jest szybsza niż użycie tabeli pomocniczej, ale sprawia, że system jest bardziej zależny od kodu i znajomości kodu źródłowego.
Aby temu zaradzić, możesz również skonfigurować tabelę z identyfikatorami wyliczeń w bazie danych. Lub przejdź w drugą stronę i wybierz identyfikatory wyliczeń z tabeli, dodając do niej wiersze.
Uwaga dodatkowa : zawsze sprawdzaj, czy nie projektujesz czegoś, co powinno być przechowywane w tabeli bazy danych i utrzymywane jak zwykły obiekt. Jeśli możesz sobie wyobrazić, że musisz dodać nowe stałe do wyliczenia w tym momencie, kiedy je konfigurujesz, jest to wskazówka, że może lepiej będzie utworzyć zamiast tego zwykły obiekt i tabelę.
źródło