大家好,
我正在尝试从旧版数据库中构建所有jpa实体。我有一个经常出现的问题:某些“主要”实体具有“翻译”的集合,其中主键是“主要” +“语言”标识符的键。语言存储在数据库和枚举中,以简化处理。
我使用的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;
}
问题是,当尝试使用描述上的某些翻译以及设置了“语言”和“消息”的翻译来持久保存一个Main(消息)实体时,我不断收到以下异常:
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为空。任何帮助,评论,线索将不胜感激。
谢谢!
最佳答案
这是我们解决此问题的方法:
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;
希望这可以帮助 :)