Spring/JPA/persistence 实体属性字段不能是最终的?

Posted

技术标签:

【中文标题】Spring/JPA/persistence 实体属性字段不能是最终的?【英文标题】:Spring/JPA/persistence entity attribute field cannot be final? 【发布时间】:2017-05-31 10:38:44 【问题描述】:

我有一个使用JPASpring MVC 项目,我在过去已经工作了一段时间,没有这个问题。但是现在由于某种原因(可能是环境问题,因为自从我上次使用新笔记本电脑后我已经换了一台新笔记本电脑)我收到了这个奇怪的错误。

该项目本质上是一个用于创建和执行调查的工具,调查只是一组问题。有多种类型的问题,例如“自动完成问题”、“选择题”、“整数问题”等,它们收集不同类型的数据。每个问题类型都由一个子类建模,该子类扩展了一个名为 DdmQuestion 的抽象类,看起来像这样:

@Entity
@Table(name = "ddm_question")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(discriminatorType = DiscriminatorType.STRING, name = "question_type")

@JsonIgnoreProperties("dataType")
@JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@question_type")
@JsonSubTypes(value =  @Type(DdmTextQuestion.class),@Type(DdmDateQuestion.class),@Type(DdmTimeQuestion.class),@Type(DdmNumberIntegerQuestion.class),@Type(DdmChoiceMultiQuestion.class),@Type(DdmAutoCompleteQuestion.class) )
public abstract class DdmQuestion 

    @Id
    @GeneratedValue
    @Column(name = "question_id")
    private int questionId;

    @Column(name = "name")
    private String name;

    public int getQuestionId() 
        return questionId;
    

    public void setQuestionId(int questionId) 
        this.questionId = questionId;
    

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

    @JsonIgnore
    public abstract String getDataType();

注意getDataType() 方法。

然后,对于每种问题类型,我都有一个扩展它的子类,它看起来像这样:

@Entity
@DiscriminatorValue("ddm_question_date")
public class DdmDateQuestion extends DdmQuestion 

    final private String DATA_TYPE = "Long"; // this is the line with the error

    @Override
    public String getDataType() 
        return DATA_TYPE;
    


现在,我以前从未遇到过这个错误(我记得),但Eclipse 在这里抛出了一个错误,上面写着:

“属性“DATA_TYPE”的 Java 字段是最终的”。就是这样 说。

如果我从类中删除 @Entity 注释,则此错误会消失,很明显 JPA 中的某些内容对此不满意,但我之前从未遇到过此错误,因此我认为在较新的版本中有所更改.我的 POM 对依赖版本不是特别明确,所以这不足为奇。

谁能向我解释为什么会发生这种情况以及正确的解决方案是什么?我可以从字段声明中删除“final”,但这对我来说似乎是错误的,因为它绝对是一个最终值......

提前致谢。

【问题讨论】:

这对我来说似乎是一个常数值,你为什么不给它加上 static 关键字呢? JPA 规范说得很清楚,JPA 不能保留最终/静态字段 @galovics 嗯...好问题,我刚刚尝试过,错误消失了!但我不明白为什么...? @NeilStockton 但这段代码过去一直有效?! 定义“工作”。根据定义,你改变了一些东西 【参考方案1】:

如果它是一个不应在数据库中持久化的字段,您通常应该利用瞬态注释,它会告诉持久性提供者在其处理中省略该字段。:

@Transient
final private String DATA_TYPE = "Long";

如果 Eclipse 足够聪明,它应该完全停止突出显示错误。

【讨论】:

【参考方案2】:

在此链接http://docs.oracle.com/javaee/5/tutorial/doc/bnbqa.html#Entities;

实体类必须遵循以下要求:

该类必须使用 javax.persistence.Entity 注释进行注释。

该类必须具有公共或受保护的无参数构造函数。该类可能有其他构造函数。

类不能被声明为final。没有方法或持久实例变量必须声明为 final。

如果实体实例作为分离对象按值传递,例如通过会话 bean 的远程业务接口,则该类必须实现 Serializable 接口。

实体可以扩展实体类和非实体类,非实体类可以扩展实体类。

持久性实例变量必须声明为私有、受保护或包私有,并且只能通过实体类的方法直接访问。客户端必须通过访问器或业务方法访问实体的状态。

【讨论】:

以上是关于Spring/JPA/persistence 实体属性字段不能是最终的?的主要内容,如果未能解决你的问题,请参考以下文章

1029-实体分析与部分实体构建

01数据库的实体关系

实体框架分离实体和相关实体消失

为啥实体框架没有映射我订单中的客户实体?

分离实体和被管理实体

实体框架代码优先 - 通过主键将子实体添加到父实体