将名为 EMPLOYEE 的枚举映射到 VARCHAR 鉴别器值“M”

Posted

技术标签:

【中文标题】将名为 EMPLOYEE 的枚举映射到 VARCHAR 鉴别器值“M”【英文标题】:Mapping an enum named EMPLOYEE to a VARCHAR discriminator value 'M' 【发布时间】:2012-09-03 18:49:46 【问题描述】:

这基本上是一个后续问题或重新发布,因为问题How to use enums with JPA 似乎已以专有方式解决。这个和2012年的JPA题基本一样,这里使用的是EclipseLink 2.3.2

问题是如何将 Java 枚举映射到具有不同名称的数据库字符串。有一个带有 VARCHAR 值 'M''C''N''F' 的 DB 列。它们很神秘,混合了英语和德语。为了改进业务层,我想将 Java 枚举映射到上述数据库字符串:

public enum TradingSector

    EMPLOYEE( "M" ), // Mitarbeiter
    CUSTOMER( "C" ),
    NOSTRO( "N" ),
    FUND( "F" );

// this works:
//    M( "M" ),
//    C( "C" ),
//    N( "N" ),
//    F( "F" );

    private final String ch;

    private TradingSector( String ch )
    
        this.ch = ch;
    

    @Override
    public String toString()
    
        return this.ch;
    

这是实体:

@Entity
@Table( name = "TRADES" )
@Inheritance( strategy = InheritanceType.SINGLE_TABLE )
@DiscriminatorColumn( name = "NOSTRO_FLAG", discriminatorType = DiscriminatorType.STRING, length = 1 )
public class Trade implements Serializable

    @Enumerated( EnumType.STRING )
    @Column( name = "NOSTRO_FLAG", insertable = false, updatable = false )
    private TradingSector discriminator;

    ...

这有点特殊,将枚​​举映射到已经是继承鉴别器的对象。然而,这应该可以工作,因为命名为 DB 字符串的枚举显示。

TRADES 表是目前整个上下文中最单一的表,将实体拆分为子类是非常理想的。

我原以为只需覆盖 toString 就可以从我读到的内容中工作,但这会导致:

Caused by: Exception [EclipseLink-116] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: No conversion value provided for the value [M] in field [TRADES.TRADING_SECTOR].
Mapping: org.eclipse.persistence.mappings.DirectToFieldMapping[discriminator-->TRADES.TRADING_SECTOR]
Descriptor: RelationalDescriptor(com.company.project.model.Trade --> [DatabaseTable(TRADES)])
    at org.eclipse.persistence.exceptions.DescriptorException.noFieldValueConversionToAttributeValueProvided(DescriptorException.java:1052)
    at org.eclipse.persistence.mappings.converters.ObjectTypeConverter.convertDataValueToObjectValue(ObjectTypeConverter.java:140)
    at org.eclipse.persistence.mappings.converters.EnumTypeConverter.convertDataValueToObjectValue(EnumTypeConverter.java:137)
    at org.eclipse.persistence.mappings.foundation.AbstractDirectMapping.getAttributeValue(AbstractDirectMapping.java:699)
    at org.eclipse.persistence.mappings.foundation.AbstractDirectMapping.valueFromRow(AbstractDirectMapping.java:1299)
    at org.eclipse.persistence.mappings.DatabaseMapping.readFromRowIntoObject(DatabaseMapping.java:1326)

http://wiki.eclipse.org/EclipseLink_Exception_Error_Reference_%28ELUG%29 的 EclipseLink 错误文档是这样说的:

 ECLIPSELINK-00116: No conversion value provided for the value [0] in field [1].
    Cause: The attribute conversion value for the fieldValue was not given in the object type mapping. 
    Action: Verify the field value, and provide a corresponding attribute value in the mapping. 

啊,是的。 :-/

: 解决此问题的非专有 (JPA 2) 方法是什么(如果可能的话,无需深入黑客攻击)?

PS:无法更改 DB 值。

【问题讨论】:

【参考方案1】:

该死,我在这里错过了 Pascal Thivent 的伟大答案:https://***.com/a/2751896/396732

这是最终的解决方案:

枚举:

public enum TradingSector

    EMPLOYEE( "M" ),
    CUSTOMER( "C" ),
    NOSTRO( "N" ),
    FUND( "F" );

    private final String ch;

    private TradingSector( String ch )
    
        this.ch = ch;
    

    public String getCharacter()
    
        return this.ch;
    

    public static TradingSector translate( String ch )
    
        for ( TradingSector ts : TradingSector.values() )
        
            if ( ch.equals( ts.getCharacter() ) )
            
                return ts;
            
        

        return null;
    

实体:

@Entity
@Table( name = "TRADES" )
@Inheritance( strategy = InheritanceType.SINGLE_TABLE )
@DiscriminatorColumn( name = "NOSTRO_FLAG", discriminatorType = DiscriminatorType.STRING, length = 1 )
public abstract class Trade implements Serializable

    @Column( name = "NOSTRO_FLAG", insertable = false, updatable = false )
    protected String discriminator;

    @Id
    @Column( name = "TRADE_ID" )
    protected Long id;

    ...

    protected Trade()
    
    

    public String getDiscriminator()
    
        return this.discriminator;
    

    public TradingSector getTradingSector()
    
        return TradingSector.translate( this.discriminator );
    

    ...

在某种程度上仍然有用。

【讨论】:

以上是关于将名为 EMPLOYEE 的枚举映射到 VARCHAR 鉴别器值“M”的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 JPA 和 Hibernate 映射 PostgreSQL 枚举

将嵌套对象作为道具映射到自定义组件

将枚举值映射到类型

如何使用 JPA 将 MySQL 枚举映射到 Java 枚举? [复制]

Grails:将枚举类型的mysql字段映射到域类

将某个 JSON 值映射到枚举值 C#