JPA / Hibernate缺少列
我使用JPA和Hibernate作为提供者。我有一个实体类,它有一个id列作为主键。这工作正常,但我现在必须修改它,因此主键是由两列组成的复合键。为了实现复合键,我使用了how to create a composite primary key hibernate JPA?
中显示的示例以下是最后的课程:
主键
@Embeddable
public class DocumentPK implements Serializable {
private static final long serialVersionUID = 1L;
@Basic(optional = false)
@Column(name="P_ID")
private String pId;
@Basic(optional = false)
@Column(name="P_NAME")
private String pName;
public DocumentPK() {
}
public DocumentPK(String pId, int pName) {
this.pId = pId;
this.pName = pName;
}
public String getPId() {
return pId;
}
public void setPId(String pId) {
this.pId = pId;
}
public String getPName() {
return pName;
}
public void setPName(String pName) {
this.pName = pName;
}
@Override
public int hashCode() {
int hash = 0;
hash += (pId != null ? pId.hashCode() : 0);
hash += (int) pName;
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof DocumentPK)) {
return false;
}
DocumentPK other = (DocumentPK) object;
if ((this.pId == null && other.pId != null) || (this.pId != null && !this.pId.equals(other.pId))) {
return false;
}
if (this.pName != other.pName) {
return false;
}
return true;
}
@Override
public String toString() {
return "[ pId=" + pId + ", pName=" + pName + " ]";
}
}
在实现上述主键之后,我更新了实体类以“嵌入”主键,如下所示。
@Entity
@Table(name="DOCUMENTS")
public class CustomerDocument implements Serializable{
private static final long serialVersionUID = 6373600479711119252L;
private DocumentPK id;
private String p_code;
@EmbeddedId
public DocumentPK getId() {
return id;
}
public void setId(DocumentPK id) {
this.id = id;
}
@Column(name="P_CODE")
public String getPCode() {
return p_code;
}
}
现在我检查了'DOCUMENTS'表,所有列都在那里。我甚至使用相同的用户登录到MySQL,我可以看到表格和相关列。如果我执行上述操作,则会抱怨没有找到P_ID列。我忘记了什么吗?
18:30:45,279 ERROR [TestContextManager] Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@1d349e2] to prepare test instance [com.bt.msm.ds.dao.BatchNumberDaoTest@97d3f0]
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:157)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:321)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:211)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:288)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:290)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:46)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:180)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:41)
at org.junit.runners.ParentRunner$1.evaluate(ParentRunner.java:173)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:220)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor#0' defined in class path resource [my-spring-ds.xml]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [my-spring-jpa.xml]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: myPersistenceUnit] Unable to build EntityManagerFactory
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:728)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:449)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:103)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:1)
at org.springframework.test.context.support.DelegatingSmartContextLoader.loadContext(DelegatingSmartContextLoader.java:228)
at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:124)
at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:148)
... 24 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [msm-spring-jpa.xml]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: myPersistenceUnit] Unable to build EntityManagerFactory
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1455)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:400)
at org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors(BeanFactoryUtils.java:275)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.detectPersistenceExceptionTranslators(PersistenceExceptionTranslationInterceptor.java:139)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.<init>(PersistenceExceptionTranslationInterceptor.java:79)
at org.springframework.dao.annotation.PersistenceExceptionTranslationAdvisor.<init>(PersistenceExceptionTranslationAdvisor.java:70)
at org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor.setBeanFactory(PersistenceExceptionTranslationPostProcessor.java:103)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeAwareMethods(AbstractAutowireCapableBeanFactory.java:1475)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1443)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
... 36 more
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: myPersistenceUnit] Unable to build EntityManagerFactory
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:892)
at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:73)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:257)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:310)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1514)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1452)
... 51 more
Caused by: org.hibernate.HibernateException: Missing column: pId in mydb.documents
at org.hibernate.mapping.Table.validateColumns(Table.java:277)
at org.hibernate.cfg.Configuration.validateSchema(Configuration.java:1174)
at org.hibernate.tool.hbm2ddl.SchemaValidator.validate(SchemaValidator.java:139)
at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:387)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1385)
at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:954)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:883)
... 56 more
答案 0 :(得分:2)
我现在没有任何东西可以测试,但尝试将@EmbeddedId
放在id-field而不是方法上。如果它不起作用,请尝试这样做:
DocumentPK:
public class DocumentPK implements Serializable {
private static final long serialVersionUID = 1L;
private String pId;
private String pName;
/* The rest of the class, notice the missing annotations */
CustomerDocument:
@Entity
@Table(name="DOCUMENTS")
@IdClass(DocumentPK.class)
public class CustomerDocument implements Serializable{
private static final long serialVersionUID = 6373600479711119252L;
@Id
@Column(name="P_ID", nullable=false)
private String pId;
@Id
@Column(name="P_NAME", nullable=false)
private String pName;
private String p_code;
/* Getters and setters */
答案 1 :(得分:1)
你的P_ID的getter和setter是错误的
public String getpId() {
return pId;
}
public void setpId(String pId) {
this.pId = pId;
}
应该是
public String getPId() {
return pId;
}
public void setPId(String pId) {
this.pId = pId;
}
希望有所帮助
<强>更新强> 我使用了复合键以及我在代码中的配置方式,我的建议很少。
@Embeddable
public class DocumentPK implements Serializable {
@Column(name="P_ID")
private String pId;
@Column(name="P_NAME")
private String pName;
//get set………
}
@Entity
@Table(name="DOCUMENTS")
public class CustomerDocument implements Serializable{
private static final long serialVersionUID = 6373600479711119252L;
@Id
private DocumentPK id;
private String p_code;//hoping this is not typo better pCode
//get set ……
}
以类似的理由为我设置。
答案 2 :(得分:1)
将@Access(AccessType.FIELD)添加到DocumentPK类(如果您的实现支持JPA 2.0)或将注释从字段移动到方法(也适用于JPA 1.0实现)。
@Column(name="P_ID")
对您的情况没有影响,因为(来自JPA 2.0规范):
可嵌入类的访问类型由访问权限决定 实体类的类型,映射的超类或嵌入类 嵌入它(包括作为元素集合的成员) 独立于包含类的访问类型是否具有 已明确指定或默认。一种不同的访问类型 可以通过手段为该可嵌入类指定embeddable类 如上所述的Access注释。
DocumentPK字段中的注释没有效果,因为它的访问类型是AccessType.PROPERTY。此访问类型派生自CustomerDocument。 CustomerDocument确实使用属性访问,因为找到的第一个映射注释是针对方法的(再次来自JPA 2.0规范):
实体层次结构的默认访问类型由。确定 将映射注释放置在实体的属性上 没有的实体层次结构的类和映射的超类 明确指定访问类型。
要使其工作,您必须使用@Access批注更改嵌入类中的访问类型,或将注释从字段移动到方法。
此外:您的代码无法编译,因为有时您将pName视为String,有时将其视为int。同样在“Java世界”中,通常的做法是使用camelCase名称而不是下划线作为单词分隔符。您还可以合并字段和方法的名称。