这基本上是一个后续问题或重新发布,因为问题How to use enums with JPA似乎已经以专有方式解决了。这是2012年 JPA 基本相同的问题,这里使用 EclipseLink 2.3.2 。
问题是如何将Java枚举映射到具有不同名称的数据库字符串。有一个包含VARCHAR值'M'
,'C'
,'N'
和'F'
的数据库列。它们很神秘,混合了英语和德语。为了改进业务层,我想将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.
啊,是的。 : - /
问: 非专有(JPA 2)解决这个问题的方法是什么(如果可行的话,不会进入黑客攻击范围太远)?
PS:无法更改数据库值。
答案 0 :(得分:3)
该死的,我在这里错过了Pascal 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 );
}
...
}
在某种程度上仍然有用。