java – hibernate更新JPA外键
新新新新旗新新旗新新旗新新旗新新旗新新旗新新旗新新旗新新旗新新旗
public class TESTClass implements Serializable { ... private String name; @EmbeddedId protected IssTESTPK issTESTPK; @ManyToOne(optional=false) @JoinColumns({ @JoinColumn(name="DIVISION_CODE",referencedColumnName="DIVISION_CODE",nullable=false,insertable=false,updatable=false),@JoinColumn(name="SURVEY_NUM",referencedColumnName="SURVEY_NUM",updatable=false)}) private IssDivision issDivision; } 如果我更改为’name’并调用merge,它可以更新到数据库,但是当我更改issDivision并调用merge时,它不会更新数据库. X- 20045 X- 20045 X- 20045 X- 20045 200: 这是否与我使用embededId(复合主键)相关? 更新 如果我设置upadted = true,我得到以下错误 ERROR - ContextLoader.initWebApplicationContext(215) | Context initialization fa iled org.springframework.beans.factory.BeanCreationException: Error creating bean wit h name 'sessionFactory' defined in ServletContext resource [/WEB-INF/application Context.xml]: Invocation of init method failed; nested exception is org.hibernat e.MappingException: Repeated column in mapping for entity: com.compay.test.model .TESTClass column: SURVEY_NUM (should be mapped with insert="false" update="fa lse") at org.springframework.beans.factory.support.AbstractAutowireCapableBean Factory.initializeBean(AbstractAutowireCapableBeanFactory.java:1338) at org.springframework.beans.factory.support.AbstractAutowireCapableBean Factory.doCreateBean(AbstractAutowireCapableBeanFactory.java:473) at org.springframework.beans.factory.support.AbstractAutowireCapableBean Factory$1.run(AbstractAutowireCapableBeanFactory.java:409) at java.security.AccessController.doPrivileged(Native Method) at org.springframework.beans.factory.support.AbstractAutowireCapableBean Factory.createBean(AbstractAutowireCapableBeanFactory.java:380) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getOb ject(AbstractBeanFactory.java:264) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistr y.getSingleton(DefaultSingletonBeanRegistry.java:222) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBe an(AbstractBeanFactory.java:261) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean (AbstractBeanFactory.java:185) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean (AbstractBeanFactory.java:164) at org.springframework.beans.factory.support.DefaultListableBeanFactory. preInstantiateSingletons(DefaultListableBeanFactory.java:423) at org.springframework.context.support.AbstractApplicationContext.finish BeanFactoryInitialization(AbstractApplicationContext.java:728) at org.springframework.context.support.AbstractApplicationContext.refres h(AbstractApplicationContext.java:380) at org.springframework.web.context.ContextLoader.createWebApplicationCon text(ContextLoader.java:255) at org.springframework.web.context.ContextLoader.initWebApplicationConte xt(ContextLoader.java:199) at org.springframework.web.context.ContextLoaderListener.contextInitiali zed(ContextLoaderListener.java:45) at org.apache.catalina.core.StandardContext.listenerStart(StandardContex t.java:3843) at org.apache.catalina.core.StandardContext.start(StandardContext.java:4 342) at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase .java:791) at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:77 1) at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525) at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.ja va:627) at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.j ava:553) at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:488 ) at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1149) at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java :311) at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(Lifecycl eSupport.java:117) at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053) at org.apache.catalina.core.StandardHost.start(StandardHost.java:719) at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045) at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443 ) at org.apache.catalina.core.StandardService.start(StandardService.java:5 16) at org.apache.catalina.core.StandardServer.start(StandardServer.java:710 ) at org.apache.catalina.startup.Catalina.start(Catalina.java:578) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl. 解决方法
好吧,我们来看看
你的例外(和着名的)消息是 repeated column in mapping for entity: column: SURVEY_NUM (should be mapped with insert="false" update="false") SURVEY_NUM列在哪里? 1oissDivision字段存储一个名为SURVEY_NUM的外键列 @ManyToOne @JoinColumns({ @JoinColumn(name="DIVISION_CODE",updatable=false)}) private IssDivision issDivision; 现在,请看下面的映射(请参阅id和accountNumber共享相同的列) @Entity public class Account { private Integer id; private Integer accountNumber; @Id @Column(name="ACCOUNT_NUMBER") public Integer getId() { return this.id; } @Column(name="ACCOUNT_NUMBER") public Integer getAccountNumber() { return this.accountNumber; } } 现在我们来做如下 Account account = new Account(); account.setId(127359); account.setAccountNumber(null); entityManager.persist(account); Hibernate会问你
我应该像这样执行一个查询吗? INSERT INTO ACCOUNT (ACCOUNT_NUMBER,ACCOUNT_NUMBER) VALUES (127359,NULL); 它没有任何意义.因此,这是一个错误的SQL查询; 因为这样,你看到这个好消息
所以我想你的复合主键称为IssTESTPK也存储一个名为SURVEY_NUM的列.而且您将复合主键属性定义为insert =“false”update =“false”并不是个好主意.避免很多头痛. 请记住:当多个属性共享同一列时,将其中的一个定义为insertable = false,updatable = false.没有其他的. 我认为你的复合主键类应该是这样的 @Embeddable public class IssTESTPK implements Serializable { // Ops... Our missing field which causes our Exception (repeated column... blah,blah...) @Column(name="SURVEY_NUM",nullable=false) private Integer property; private Integer otherProperty; private Integer anotherProperty; // required no-arg constructor public IssTESTPK() {} // You must implement equals and hashcode public boolean equals(Object o) { if(o == null) return false; if(!(o instanceof IssTESTPK)) return false; IssTESTPK other = (IssTESTPK) o; if(!(getProperty().equals(other.getProperty()))) return false; if(!(getOtherProperty().equals(other.getOtherProperty()))) return false; if(!(getAnotherProperty().equals(other.getAnotherProperty()))) return false; return true; } // NetBeans or Eclipse will worry about it public int hashcode() { // hashcode code goes here } } UPDATE 在继续之前
保存前必须提供其值.记住它 我们来看看员工复合主键 @Embeddable public class EmployeeId implements Serializable { @Column(name="EMPLOYEE_NUMBER") private String employeeNumber; @Column(name="SURVEY_NUMBER") private BigInteger surveyNumber; // getter's and setter's // equals and hashcode } 1o在保存员工之前,您必须提供其值.如上所述,Hibernate不支持复合主键的自动生成 2oHibernate不允许您更新(复合)主键没有意义. 3o其值不能为空 所以,如上所述,我们的EmployeeId可以写成 @Embeddable public class EmployeeId implements Serializable { @Column(name="EMPLOYEE_NUMBER",updatable=false) private String employeeNumber; @Column(name="SURVEY_NUMBER",updatable=false) private BigInteger surveyNumber; // getter's and setter's // equals and hashcode } 如上所述
但是我们不能将复合主键属性标记为insertable = false,updatable = false,因为Hibernate使用它来保存我们的实体 由于Hibernate将使用名为surveyNumber(及其SURVEY_NUMBER列)的复合主键属性来对数据库执行SQL操作,因此我们需要将@ManyToOne除法属性(及其外键列名为SURVEY_NUMBER)重写为可插入= false,可更新= FALSE // Employee.java @ManyToOne(fetch=FetchType.LAZY) @JoinColumns({ @JoinColumn(name="DIVISION_CODE",referencedColumnName="DIVISION_CODE"),@JoinColumn(name="SURVEY_NUMBER",referencedColumnName="SURVEY_NUMBER",updatable=false)}) private Division division; 4o当您有复合外键时,我们无法混合可插入或不可更新 – 不可更新. 就像是 @ManyToOne(fetch=FetchType.LAZY) @JoinColumns({ // I can be updatable @JoinColumn(name="DIVISION_CODE",insertable=false),// And i can be insertable @JoinColumn(name="SURVEY_NUMBER",updatable=false)}) private Division division; 否则,Hibernate会抱怨
因此,名为DIVISION_CODE的复合外键列也应标记为insertable = false,updatable = false以避免上述异常 // Employee.java @ManyToOne(fetch=FetchType.LAZY) @JoinColumns({ @JoinColumn(name="DIVISION_CODE",updatable=false)}) private Division division; 由于我们无法更新DIVISION_CODE列,我们的division属性的行为就像一个常量.那么,您可以想像创建一个名为divisionCode的新属性来改变DIVISION_CODE列,如下所示 // Employee.java @ManyToOne(fetch=FetchType.LAZY) @JoinColumns({ @JoinColumn(name="DIVISION_CODE",updatable=false)}) private Division division; // Wow,now i expect i can change the value of DIVISION_CODE column @Column(name="DIVISION_CODE") private BigInteger divisionCode; 好吧,我们来看看.假设我们有以下DIVISION TABLE DIVISION TABLE DIVISION_CODE SURVEY_NUMBER 1 10 2 11 3 12 4 13 5 14 记住:Division和Employee之间有一个外键约束 你想到了
您执行以下代码 employee.setDivisionCode(7); 哇,见上面的DIVISION_TABLE. DIVISION_CODE列中的某些值是否等于7? 答案很清楚:否(你会看到约束违规) 所以,这是一个不一致的映射. Hibernate不允许. 问候, (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |