Raar gedrag met db4o na refactoring enum

We hebben een enum in ons model aangepast om nieuwe waarden op te nemen. Wanneer de toepassing nu wordt uitgevoerd (met behulp van een databasebestand dat is gemaakt door de oude toepassing), gedragen sommige schakel-/caseoverzichten zich heel vreemd.

De foutopsporingsvariabelen-weergave toont dat, b.v. het enum heeft de waarde "OLD", maar de debugger stapt in de regel "case NEW:".

Wat denk jij? Proost!

Update:

De volgende code

ObjectSet set = db.query(Project.class);
System.out.println("Found " + set.size());
for (Project prj : set) {
   //this line makes no difference
    ProjectStatus otherStatus = ProjectStatus.valueOf(prj.getStatus().name());

   //debug
    System.out.println(otherStatus.name());

   //decide via switch/case
    switch (otherStatus) {
        case A:
            System.out.println("Project status is A (switch/case)");
            break;
        case B:
            System.out.println("Project status is B (switch/case)");
            break;
    }

   //decide via if
    if (otherStatus == ProjectStatus.A) {
        System.out.println("Project status is A (if ==)");
    }
    else if (otherStatus == ProjectStatus.B) {
        System.out.println("Project status is B (if ==)");
    }
}

produceert output

Found 1
B
Project status is B (if ==)

We hebben db4o 6.4 en 7.12 geprobeerd

Afhankelijk van het type enum-refactoring, wordt de volgende uitzondering gegenereerd als we de opsommingswaarden verwijderen:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
    at Main.$SWITCH_TABLE$model$ProjectStatus(Main.java:8)
    at Main.main(Main.java:37)
0
Ja, Java, hebben de tags bijgewerkt. De schakelaar is slechts een gewone switch (en ja, we dachten aan een 'break' in vorige case blocks :) met een enum als argument. Wil je het nog steeds zien?
toegevoegd de auteur Tom, de bron
In Java? Kun je het voorbeeld van de enum & switch-opdracht weergeven?
toegevoegd de auteur Gamlor, de bron
Hmm, alleen het toevoegen van opsommingswaarden lijkt hier te werken? Er is echter een enorm probleem in de implementatie van db4o enum. Het slaat het enum-object, inclusief het rangnummer, echt op. Dus wanneer u gegevens uit de database laadt, bevat het enum plotseling de oude ordinalen. Zolang je de waarden aan de onderkant toevoegt, is dat prima. Maar als je dingen tussendoor toevoegt, kan dit een groot probleem zijn. Of wanneer de waarden in het enum hetzelfde zijn. Hoe dan ook, voor meer hulp zou ik een codevoorbeeld nodig hebben.
toegevoegd de auteur Gamlor, de bron
Heb je een enum-waarde hernoemd? Dan kan ik dit gedrag produceren.
toegevoegd de auteur Gamlor, de bron

1 antwoord

Dus ik kon dit gedrag observeren:

We hebben een enum zoals dit:

public enum SomeState { 
 One, 
 Two 
} 

en een switch-statement hierover:

switch(object.getState()){ 
 case One: doSomething("State One");break; 
 case Two: doSomething("State Two");break; 
} 

We hebben een object opgeslagen met de staat Twee, zodat het 'overschakelt' naar het tweede geval.

Nu refactoren we de enum. We hernoemen de tweede waarde en voegen een nieuwe toe:

public enum SomeState { 
 One, 
 NewTwo, 
 OldTwo 
} 

En de nieuwe switch-statement:

switch(object.getState()){ 
 case One: doSomething("State One");break; 
 case NewTwo: doSomething("State New Two");break; 
 case OldTwo: doSomething("State Old Two");break; 
} 

Nu zal dat object 'overschakelen' naar de 'NewTwo'-status, wat helemaal verkeerd is!

Helaas is er een fout: ik heb hier een invoer toegevoegd (http://tracker.db4o.com/browse/COR-2268). Het onderliggende probleem is dat vreemde enum-afhandeling van db4o. Het slaat het enum-object zelf op. Bij het laden van het object uit de database herstelt het de enum-status, zelfs het spul in statische variabelen! Als ondertussen de refactoring heeft plaatsgevonden, is het hele spul in de war. In feite hebben we meerdere enums met dezelfde ordinals en verknoeide namen.

Voor nu zou ik aanraden om enums te vermijden (op Java. In .Net werkt de db4o enum-afhandeling) = (.

Bewerken: suggestie voor de migratie: dit zou kunnen: voeg de 'refactored' enums als compleet nieuwe waarden toe aan het enum. Laad vervolgens alle objecten met dat enum en verander de waarden naar de nieuwe waarden. Hierna verwijder je vervolgens de oude enum-waarden.

2
toegevoegd