Java – hibernate update JPA foreign key
New flag new flag new flag new flag new flag new flag new flag new flag new flag new flag new flag new flag new flag new flag new flag
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; }
If I change to 'name' and call merge, it can update to the database, but when I change issdivision and call merge, it will not update the database X- 20045 X- 20045 X- 20045 X- 20045 200:
Is this related to my use of embeddedid (composite primary key)?
to update
If I set upadted = true, I get the following error
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.
Solution
Well, let's see
Your exceptional (and famous) news is
repeated column in mapping for entity: column: SURVEY_NUM (should be mapped with insert="false" update="false")
SURVEY_ Where is the num column?
The 1 º issdivision field stores a file named survey_ Foreign key column of num
@ManyToOne @JoinColumns({ @JoinColumn(name="DIVISION_CODE",updatable=false)}) private IssDivision issDivision;
Now look at the mapping below (see ID and accountnumber share the same column)
@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; } }
Now let's do the following
Account account = new Account(); account.setId(127359); account.setAccountNumber(null); entityManager.persist(account);
Hibernate will ask you
Should I execute a query like this?
INSERT INTO ACCOUNT (ACCOUNT_NUMBER,ACCOUNT_NUMBER) VALUES (127359,NULL);
It makes no sense Therefore, this is an incorrect SQL query;
Because of this, you see the good news
So I think your composite primary key is called istestpk, and it also stores a key called query_ Num column Moreover, it is not a good idea for you to define the composite primary key attribute as insert = "false" and update = "false" Avoid a lot of headaches
Remember: when multiple attributes share the same column, define one of them as insertable = false and updatable = false Nothing else
I think your composite primary key class should be like this
@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
Before continuing
Its value must be provided before saving Remember it
Let's take a look at employee composite keys
@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 }
1 º before saving an employee, you must provide its value As mentioned above, hibernate does not support automatic generation of composite primary keys
2 º hibernate does not allow you to update (compound) the primary key, which is meaningless
The value of 3 º cannot be empty
Therefore, as mentioned above, our employeeID can be written as
@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 }
As mentioned above
However, we cannot mark the composite primary key attribute as insertable = false and updatable = false, because hibernate uses it to save our entities
Since hibernate will use the compound primary key attribute named surveynumber (and its query_number column) to perform SQL operations on the database, we need to rewrite the @ manytoone division attribute (and its foreign key column named query_number) to be pluggable = false and updatable = 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;
4 º when you have composite foreign keys, we cannot mix pluggable or non updatable – non updatable
It's like
@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;
Otherwise, hibernate will complain
Therefore, it is called division_ The composite foreign key column of code should also be marked with insertable = false and updatable = false to avoid the above exceptions
// Employee.java @ManyToOne(fetch=FetchType.LAZY) @JoinColumns({ @JoinColumn(name="DIVISION_CODE",updatable=false)}) private Division division;
Because we can't update Division_ Code column, our division property behaves like a constant Then, you can imagine creating a new attribute called divisioncode to change the division_ The code column, as shown below
// 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;
Well, let's have a look Suppose we have the following division table
DIVISION TABLE DIVISION_CODE SURVEY_NUMBER 1 10 2 11 3 12 4 13 5 14
Remember: there is a foreign key constraint between division and employee
Did you think of it
You execute the following code
employee. setDivisionCode(7);
Wow, see division above_ TABLE. DIVISION_ Are some values in the code column equal to 7?
The answer is clear: no (you will see constraint violations)
So, this is an inconsistent mapping Hibernate does not allow
to greet,