Странное поведение с db4o после рефакторинга enum - PullRequest
0 голосов
/ 06 декабря 2011

Мы реорганизовали перечисление, используемое в нашей модели, чтобы включить новые значения. Теперь, когда приложение выполняется (используя файл базы данных, созданный старым приложением), некоторые операторы switch / case ведут себя очень странно.

Представление переменных отладки показывает, что, например, перечисление имеет значение «OLD», но отладчик переходит в строку «case NEW:».

Есть мысли? Ура! * * 1005

Обновление:

следующий код

ObjectSet<Project> 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 ==)");
    }
}

производит вывод

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

Мы пробовали db4o 6.4 и 7.12

Кроме того, в зависимости от типа рефакторинга перечисления, если мы удаляем значения перечисления, выдается следующее исключение:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
    at Main.$SWITCH_TABLE$model$ProjectStatus(Main.java:8)
    at Main.main(Main.java:37)

1 Ответ

2 голосов
/ 07 декабря 2011

Итак, я мог наблюдать это поведение:

У нас есть следующее перечисление:

public enum SomeState { 
 One, 
 Two 
} 

и оператор switch для этого:

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

We 'мы сохранили объект с состоянием Два, поэтому он «переключится» на второй случай.

Теперь мы проведем рефакторинг enum.Мы переименовываем второе значение и добавляем новое:

public enum SomeState { 
 One, 
 NewTwo, 
 OldTwo 
} 

И новый оператор switch:

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

Теперь этот объект «переключится» в состояние «NewTwo»,что совершенно неправильно!

К сожалению, это ошибка: я добавил сюда запись (http://tracker.db4o.com/browse/COR-2268).) Основная проблема заключается в странной обработке перечисления в db4o. На самом деле он хранит сам объект перечисления. При загрузкеобъект из базы данных восстанавливает состояние enum, даже материал в статических переменных! Если за это время рефакторинг состоялся, весь материал испорчен. В основном мы многократные перечисления с одинаковыми порядковыми номерами и испорченными именами.

На данный момент я бы порекомендовал избегать перечислений (на Java. В .Net работает обработка перечислений db4o) = (.

Редактировать: Предложение по миграции: Вы можете сделать это: Добавить 'refactored' перечисления какзаполните новые значения для перечисления. Затем загрузите все объекты, содержащие это перечисление, и измените значения на новые значения. После этого вы удалите старые значения перечисления.

...