重构枚举后db4o的奇怪行为

时间:2011-12-06 19:36:37

标签: java enums refactoring db4o

我们已经重构了我们模型中使用的枚举以包含新值。现在,当应用程序执行时(使用旧应用程序创建的数据库文件),某些switch / case语句表现得非常奇怪。

调试变量视图显示,例如枚举的值为“OLD”,但调试器会进入“case NEW:”行。

有什么想法?干杯!

更新

以下代码

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 个答案:

答案 0 :(得分:2)

所以我可以观察到这种行为:

我们有这样的枚举:

public enum SomeState { 
 One, 
 Two 
} 

和关于此的开关声明:

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

我们存储了状态为Two的对象,因此它将“切换”到第二种情况。

现在我们重构枚举。我们重命名第二个值并添加一个新值:

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的奇怪枚举处理。它实际上存储了枚举对象本身。从数据库加载对象时,它会恢复枚举状态,甚至是静态变量中的东西!如果同时重构已经发生,整个事情就搞砸了。基本上我们有多个具有相同序数的枚举和混乱的名称。

现在我建议避免枚举(在Java上。在.Net中db4o枚举处理工作)=(。

编辑:对迁移的建议:您可以这样做:将“重构”枚举作为完整的新值添加到枚举中。然后加载包含该枚举的所有对象,并将值更改为新值。之后,您将删除旧的枚举值。