当前位置:  开发笔记 > 编程语言 > 正文

如何在JPA中使用枚举

如何解决《如何在JPA中使用枚举》经验,为你挑选了4个好方法。

我有一个电影租赁系统的现有数据库.每部电影都有一个评级属性.在SQL中,他们使用约束来限制此属性的允许值.

CONSTRAINT film_rating_check CHECK 
    ((((((((rating)::text = ''::text) OR 
          ((rating)::text = 'G'::text)) OR 
          ((rating)::text = 'PG'::text)) OR 
          ((rating)::text = 'PG-13'::text)) OR 
          ((rating)::text = 'R'::text)) OR 
          ((rating)::text = 'NC-17'::text)))

我认为使用Java枚举将约束映射到对象世界会很好.但由于"PG-13"和"NC-17"中的特殊字符,因此不可能简单地采用允许的值.所以我实现了以下枚举:

public enum Rating {

    UNRATED ( "" ),
    G ( "G" ), 
    PG ( "PG" ),
    PG13 ( "PG-13" ),
    R ( "R" ),
    NC17 ( "NC-17" );

    private String rating;

    private Rating(String rating) {
        this.rating = rating;
    }

    @Override
    public String toString() {
        return rating;
    }
}

@Entity
public class Film {
    ..
    @Enumerated(EnumType.STRING)
    private Rating rating;
    ..

使用toString()方法,方向枚举 - > String工作正常,但String - > enum不起作用.我得到以下异常:

[TopLink警告]:2008.12.09 01:30:57.434 - ServerSession(4729123) - 例外[TOPLINK-116](Oracle TopLink Essentials - 2.0.1(Build b09d-fcs(12/06/2007))): oracle.toplink.essentials.exceptions.DescriptorException异常说明:没有为字段[FILM.RATING]中的值[NC-17]提供转换值.映射:oracle.toplink.essentials.mappings.DirectToFieldMapping [rating - > FILM.RATING]描述符:RelationalDescriptor(de.fhw.nsdb.entities.Film - > [DatabaseTable(FILM)])

干杯

蒂莫



1> aledbf..:

你试图存储序数值吗?如果没有与值关联的String,则存储字符串值可以正常工作:

@Enumerated(EnumType.ORDINAL)


@electrotype是的,从技术上讲它是有效的,但它远非最佳实践.通过数字存储枚举是一个可怕的想法.不改变代码功能的非常基本的更改可以轻松地使所有持久数据无效.例如,重新排列枚举值的顺序或在列表的开头添加新值.
考虑到@Enumerated是[JPA1的一部分](http://docs.oracle.com/javaee/5/api/javax/persistence/Enumerated.html),我无法相信这没有更多的赞成.就个人而言,我认为`EnumType.STRING`会因为cletus所说的原因而更好.

2> cletus..:

你有一个问题,那就是处理枚举时JPA的有限功能.使用枚举,您有两种选择:

    将它们存储为等于的数字Enum.ordinal(),这是一个可怕的想法(imho); 要么

    将它们存储为等于的字符串Enum.name(). 注意:不是toString()您所期望的,特别是因为默认行为Enum.toString()是返回name().

我个人认为最好的选择是(2).

现在您遇到的问题是,您定义的值不代表Java中的vailid实例名称(即使用连字符).所以你的选择是:

改变你的数据;

保持字符串字段并隐式地将它们转换为对象中的枚举; 要么

使用TypeConverters等非标准扩展.

我会按顺序(从头到尾)按顺序排列.

有人建议使用Oracle TopLink的转换器,但您可能正在使用Toplink Essentials,作为参考JPA 1.0实现,它是商业Oracle Toplink产品的一个子集.

作为另一个建议,我强烈建议切换到EclipseLink.这是一个比Toplink Essentials更完整的实现,Eclipselink将成为JPA 2.0的参考实现(由JavaOne明年年中推出).



3> Dan Vinton..:

听起来您需要添加对自定义类型的支持:

扩展OracleAS TopLink以支持自定义类型转换



4> JeeBee..:
public enum Rating {

    UNRATED ( "" ),
    G ( "G" ), 
    PG ( "PG" ),
    PG13 ( "PG-13" ),
    R ( "R" ),
    NC17 ( "NC-17" );

    private String rating;

    private static Map ratings = new HashMap();
    static {
        for (Rating r : EnumSet.allOf(Rating.class)) {
            ratings.put(r.toString(), r);
        }
    }

    private static Rating getRating(String rating) {
        return ratings.get(rating);
    }

    private Rating(String rating) {
        this.rating = rating;
    }

    @Override
    public String toString() {
        return rating;
    }
}

我不知道如何在注释的TopLink方面做映射.

推荐阅读
吻过彩虹的脸_378
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有