具有外键和枚举的JPA复合键

时间:2014-11-25 10:24:53

标签: java hibernate jpa enums compound-key

大家好,

我试图从遗留数据库中构建所有jpa实体。我有一个经常出现的问题:一些" main"实体有一组"翻译",其中主键是" main"的关键字。 +"语言"标识符。语言存储在数据库和Enum上,以便于他们的处理。

我正在使用的JPA实现是Hibernate 4。

在下文中,当前的实现:

主要:(留言)

@Entity
@Table(name="MESSAGES")
@NamedQueries({
public class Message implements Serializable {

  @Id
  @SequenceGenerator(name="MESSAGES_MESSAGEID_GENERATOR", sequenceName="SEQ_MSG_messageID")
  @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="MESSAGES_MESSAGEID_GENERATOR")
  @Column(name="messageId")
  private long id;

  @OneToMany(mappedBy="message", fetch=FetchType.EAGER)
  private Set<MessageDesc> descriptions;
}

翻译:(MessageDesc)

@Entity
@Table(name="MESSAGEDESCS")
public class MessageDesc implements Serializable, Translatable {

  @EmbeddedId
  private MessageDescPK id;

  @NotNull  
  @Enumerated(EnumType.ORDINAL)
  @Column(name = "LANGUAGEID")
  private LanguageEnum language;

  @NotNull  
  @ManyToOne
  @JoinColumn(name="MESSAGEID")
  private Message message;
}

翻译复合键:(MessageDescPK)

@Embeddable
public class MessageDescPK implements Serializable {

  @Column(name="messageid", nullable = false, insertable = false)
  private long message;

  @Column(name="languageid", nullable = false, insertable = false)
  private int language;
}

语言:(LanguageEnum)

public enum LanguageEnum {
  FRENCH(0, "FR"),
  DUTCH(1, "NL");

  private int id;
  private String desc;
}

问题在于,当尝试在描述中保留一个主要(消息)实体并且在设置了语言和消息的翻译时,我会继续收到以下异常:

org.springframework.orm.jpa.JpaSystemException: org.hibernate.id.IdentifierGenerationException: null id generated for:class something.persistence.entity.message.MessageDesc; nested exception is javax.persistence.PersistenceException: org.hibernate.id.IdentifierGenerationException: null id generated for:class something.persistence.entity.message.MessageDesc
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:321)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:403)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:58)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:163)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodIntercceptor.invoke(CrudMethodMetadataPostProcessor.java:111)

我不明白为什么在设置messageDesc实例上的语言和消息(已经持久化)之后PK为null。任何帮助,评论,线索将不胜感激。

谢谢!

1 个答案:

答案 0 :(得分:1)

这就是我们解决这个问题的方法:

<强> MessageDesc

@NotNull    
@Enumerated(EnumType.ORDINAL)
@Column(name = "LANGUAGEID", insertable=false, nullable = false)
private LanguageEnum language;

@NotNull    
@ManyToOne
@JoinColumn(name="MESSAGEID", insertable=false, nullable = false)
private Message message;

@PrePersist
private void prePersist(){
    if (getId() == null){
        MessageDescPK id = new MessageDescPK();
        //the way this enum is persisted is EnumType.ORDINAL
        id.setLanguage(getLanguage().ordinal());
        id.setMessage(getMessage().getId());
        this.setId(id);
    }
}

<强> MessageDescPk

@Embeddable
public class MessageDescPK implements Serializable {
    //default serial version id, required for serializable classes.
    private static final long serialVersionUID = 1L;

    @Column(name="messageid", nullable = false, insertable = false, updatable=false)
    private long message;

    @Column(name="languageid", nullable = false, insertable = false, updatable=false)
    private int language;

希望这会有所帮助:)