使用Groovy将枚举映射到实体

使用Groovy将枚举映射到实体,groovy,enums,Groovy,Enums,我有以下数据库表: widget_types ------------ widget_type_id widget_type_name widget_type_alias widget_type_description 这对应于以下Groovy实体类: class WidgetType extends BaseLookupEntity { Long id String name String alias String description } 实际上,Wid

我有以下数据库表:

widget_types
------------
widget_type_id
widget_type_name
widget_type_alias
widget_type_description
这对应于以下Groovy实体类:

class WidgetType extends BaseLookupEntity {
    Long id
    String name
    String alias
    String description
}
实际上,
WidgetType
/
widget\u类型
确实应该是
enum
,因为它们是引用/查找类型,具有少量有效值:

  • RedWidget
  • SillyWidget
  • HappyWidget
  • BerserkingWidget
  • 香肠小部件
由于超出此问题范围的原因,我实际上不可能将
小部件类型
表映射到
枚举
。因此,我创建了一个“助手枚举”:

这里的想法是JPA/OR层将创建
WidgetType
实例,但为了能够真正使用它们(类型安全等),我希望能够将它们转换为
WidgetTypeLookups

// Inside some method...
WidgetType widgetType = getSomehowButStillNotSureWhichTypeItIs()
WidgetTypeLookup wtLookup = WidgetTypeLookup.toWidgetTypeLookup(widgetType)
switch(wtLookup) {
case Happy:
    // etc...
}

因此,我正在努力寻找一种在POGO类型和enum之间进行转换的高效“Groovy方式”。基本上实现了helper方法。有什么想法吗?

枚举是数量有限的固定元素,除非该表只有固定行,
Widget Red/Silly/etc
应该是子类

您可以在
WidgetType
类中实现helper方法,并从内部枚举操作专门化(尽管它们不能引用外部类)

我认为
widget.install()
更酷、更面向对象(从某种意义上说,我不需要拉着对象的内脏去做一些事情)

另一种解决方案是,如果
WidgetType
是一个抽象类,并且您的ORM将基于特定值实例化正确的具体类型:

abstract class WidgetType {
    Long id
    String name
    String alias
    String description

    abstract install(container)

    enum Type {
        RED(RedWidget), 
        SAUSAGE(SausageWidget), 
    }

    static WidgetType from(type, properties) {
        Type.values().find { it.name() == type }
            .clazz
            .newInstance(properties: properties)
    }
}

class RedWidget extends WidgetType {
    def install(container) { 'red installing into $container' }
}

class SausageWidget extends WidgetType {
    def install(container) { 'elongated component installing into $container' }
}
假ORM:

class ORM {
    def container = [
        (1) : [
            id: 1, 
            name: 'RED', 
            alias: 'my red alias',
            description: 'this art red' ],
        (2) : [
            id: 2, 
            name: 'SAUSAGE', 
            alias: 'long component', 
            description: 'sausage component' ] 
    ]

    def get(id) {
        container[it].with {
            WidgetType.from(it.name, id)
        }
    }
}
测试:

red = new ORM().get(1)
assert red.install('main') == 
        'red installing into main'

sausage = new ORM().get(2)
assert sausage.install('display') == 
        'elongated component installing into display'

我同意另一个答案,即可能有更好的方法通过改进OO设计来解决您的问题。尽管我会尽量适应你的方法

首先-您不能按照下面的步骤操作,并立即将名称映射为enum吗

class WidgetType extends BaseLookupEntity {
    Long id
    WidgetName name
    String alias
    String description

    enum WidgetName {
        Red,
        Silly,
        Happy,
        Berserking,
        Sausage
    }
}
Second-您想要实现的方法可以实现为:

static WidgetTypeLookup toWidgetTypeLookup(WidgetType type) {
    values().find {
        it.name() == type.name
    }
}
然而:

  • 如果名称不完全匹配,则可能需要调整条件
  • 当找不到匹配的枚举时,可能需要以某种方式处理该情况
  • 方法的名称应该是
    fromWidgetType()
    ,然后您将有类似
    WidgetTypeLookup.fromWidgetType(widgetType)
    的调用,而不是冗余的
    WidgetTypeLookup.toWidgetTypeLookup(widgetType)
第三个-groovy更应该实现如下自定义类型转换(我修改了原始类的名称以更好地反映它们是什么IMHO):

然后你可以这样做:

WidgetType widgetType = new WidgetTypeDetails(name: 'Red') as WidgetType

让我觉得“哦,哦”的部分是开关(wtLookup)块。你会在这样一个开关块中写些什么?Emanuel,任何类型的条件逻辑。也许“快乐”小部件应该向左,但“狂暴”小部件应该向右。我发现使用类型安全枚举更容易做到这一点,而不是像这样做:
if(widgetType.alias.equals('HAPPY')){goLeft()}
,等等。
static WidgetTypeLookup toWidgetTypeLookup(WidgetType type) {
    values().find {
        it.name() == type.name
    }
}
enum WidgetType {
    Red,
    Silly,
    Happy,
    Berserking,
    Sausage
}

class WidgetTypeDetails {
    Long id
    String name
    String alias
    String description

    Object asType(Class clazz) {
        if (clazz == WidgetType) {
            WidgetType.values().find {
                it.name() == this.name
            }
        }
    }
}
WidgetType widgetType = new WidgetTypeDetails(name: 'Red') as WidgetType