Many a times there is a need for composite key as primary key, JPA, Hibernate provides composite-key for implementing this use case.
Let’s run through this example quickly.
Step 1:
Create a “Java Project” in Eclipse and add required jars. Since Maven is nice but not a panacea, please see the image below so as to see which all jars are required.
Step 2:
Let’s say our model is to update Student Record, our table Student has three fields namely:
- Id
- Name
- Address
As per domain, both id and name are part of primary key.
Third we need an JPA Entity class for holding Student.
Student.java
package com.mumz.test.jpa.embedded; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "STUDENT") public class Student { private StudentPK studentPK = null; private String address = null; public Student(StudentPK studentPK, String address) { super(); this.studentPK = studentPK; this.address = address; } /** * @param studentPK * the studentPK to set */ public void setStudentPK(StudentPK studentPK) { this.studentPK = studentPK; } /** * @return the studentPK */ @Id public StudentPK getStudentPK() { return studentPK; } /** * @return the address */ @Column(name = "STUDENT_ADDRESS") public String getAddress() { return address; } /** * @param address * the address to set */ public void setAddress(String address) { this.address = address; } /** * (non-Javadoc) * * @see java.lang.Object#hashCode() */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((studentPK == null) ? 0 : studentPK.hashCode()); result = prime * result + ((address == null) ? 0 : address.hashCode()); return result; } /** * (non-Javadoc) * * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof Student)) { return false; } Student other = (Student) obj; if (studentPK == null) { if (other.studentPK != null) { return false; } } else if (!studentPK.equals(other.studentPK)) { return false; } if (address == null) { if (other.address != null) { return false; } } else if (!address.equals(other.address)) { return false; } return true; } }
You would have noticed instead of marking both id
and name
with @Id
annotation there is another object called as studentPK
of type StudentPK
which has been marked with @Id
annotation.
Fourth now we will see the primary key class in this case StudentPK
.
StudentPK.java
package com.mumz.test.jpa.embedded; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Embeddable; @Embeddable public class StudentPK implements Serializable{ /** * */ private static final long serialVersionUID = 3686950547855931594L; private Integer id = null; private String name = null; public StudentPK(Integer id, String name) { this.id = id; this.name = name; } /** * @return the id */ @Column(name="STUDENT_ID") public Integer getId() { return id; } /** * @param id the id to set */ public void setId(Integer id) { this.id = id; } /** * @return the name */ @Column(name="STUDENT_NAME") public String getName() { return name; } /** * @param name the name to set */ public void setName(String name) { this.name = name; } /** (non-Javadoc) * @see java.lang.Object#hashCode() */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } /** (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof StudentPK)) { return false; } StudentPK other = (StudentPK) obj; if (id == null) { if (other.id != null) { return false; } } else if (!id.equals(other.id)) { return false; } if (name == null) { if (other.name != null) { return false; } } else if (!name.equals(other.name)) { return false; } return true; } }
@Embeddable
means that StudentPK
is not an independent entity and it depends on another entity for it’s existence.
As per our business model, our entity class Student
now has two columns namely id
and name
as part of primary key.
In order to run this we need to create an EntityManager
which needs some configuration, generally it is called as persistence.xml
.
Fifth inside META-INF folder create an xml file called as persistence.xml
and fill in the value as below.
persistence.xml
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="myJPAService" transaction-type="RESOURCE_LOCAL"> <class>com.mumz.test.jpa.embedded.Student</class> <class>com.mumz.test.jpa.embedded.StudentPK</class> <properties> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/test"/> <property name="javax.persistence.jdbc.user" value="root"/> <property name="javax.persistence.jdbc.password" value="root"/> <property name="show_sql" value="true"/> </properties> </persistence-unit> </persistence>
You would have noticed we have specified our classes and also the database details, for this example we are using MySQL.
Sixth step is to save some data in database, let’s write a test class.
EmbeddableTestMainApp.java
package com.mumz.test.jpa.embedded; import javax.persistence.EntityManager; import javax.persistence.Persistence; public class EmbeddableTestMainApp { public static void main(String[] args) { EntityManager em = Persistence.createEntityManagerFactory("myJPAService").createEntityManager(); StudentPK studentPK = new StudentPK(1, "Test Student"); Student student = new Student(studentPK, "Test Address"); boolean isError = false; try { em.getTransaction().begin(); em.persist(student); } catch (Exception exp) { exp.printStackTrace(); isError = true; } finally { if (isError) { em.getTransaction().rollback(); } else { em.getTransaction().commit(); } } } }
Final step is to create a database for our application.
CREATE DATABASE `JPA_Project_DB`; CREATE TABLE `JPA_Project_DB`.`STUDENT` ( `STUDENT_ID` int(11) NOT NULL, `STUDENT_NAME` varchar(45) NOT NULL, `STUDENT_ADDRESS` varchar(45) DEFAULT NULL, PRIMARY KEY (`STUDENT_ID`,`STUDENT_NAME`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8
That’s all, we have just learnt how to use composite key using JPA with Hibernate as the JPA implementation provider and database as MySQL.
i have the following error; ERROR: Column
‘Agregacion_M_idAgregacion’ specified twice. if u have why, teell
me pls 🙂
Hi.
In a mvc project, how to you get the values from a form???.
Using @ModelAttribute justo get student_address.
Any idea???.
Thanks.