2012-09-03 50 views
1

這基本上是後續問題或重新發布,因爲問題How to use enums with JPA似乎已以專有方式解決。這是2012年JPA的問題基本相同,這裏使用EclipseLink 2.3.2將名爲EMPLOYEE的枚舉映射到VARCHAR鑑別符值'M'

問題是如何將Java枚舉映射到具有不同名稱的DB字符串。有一個VARCHAR值爲'M','C','N''F'的DB列。它們是神祕而混合的英語和德語。爲了提高業務層我要地圖一個Java枚舉上述DB串:

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. 

嗯,是的。 : -/

Q: 什麼是非專有(JPA 2)的方式來解決這個問題(如果可能的話,在所有的,沒有去太遠的黑客戰壕)?

PS:無法更改DB值。

回答

3

媽的,我錯過了帕斯卡爾Thivent的偉大答案在這裏:https://stackoverflow.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); 
    } 

    ... 
} 

仍然有用在一定程度上。