Composite primary key mapping requires the use of the <composite-id> tag in the mapping configuration file. This tag refers to specifying a class as the corresponding compound primary key. Its name attribute needs to specify the property value defined in the class file and add the <key-property> sub-label to the tag.
Note: If you want to use composite mapping, you must place the composite primary key in one class, that is, the composite primary key attributes and other attributes are divided into two classes, and the composite primary key class implements the interface Serializable, which belongs to java.io.
The primary key of the mapping relationship of the composite primary key is composed of multiple columns, which corresponds to the data table quite simple, as shown in the figure below:
1. Class files
Here we take the table in the figure above as an example. In the table, two fields and durations combine to form the primary key of the table. Therefore, the new classes divided are named FiscalYearPeriod and FiscalYearPeriodPK respectively. Among them, the FiscalYearPeriod class encapsulates the primary key attributes of the table, the FiscalYearPeriod class encapsulates other attributes, and the FiscalYearPeriod class.
1.1 FiscalYearPeriod.java
The class encapsulates basic properties, and encapsulates the FiscalYearPeriodPK class as attributes into the class, and configures the corresponding mapping in the configuration file, as follows:
package com.src.hibernate; import java.sql.Date; public class FiscalYearPeriod { //Time primary key private FiscalYearPeriodPK fiscalYearPeriodPK; public FiscalYearPeriodPK getFiscalYearPeriodPK() { return fiscalYearPeriodPK; } public void setFiscalYearPeriodPK(FiscalYearPeriodPK fiscalYearPeriodPK) { this.fiscalYearPeriodPK = fiscalYearPeriodPK; } //Start date private Date beginDate; public Date getBeginDate() { return beginDate; } public void setBeginDate(Date beginDate) { this.beginDate = beginDate; } //end date private Date endDate; public Date getEndDate() { return endDate; } public void setEndDate(Date endDate) { this.endDate = endDate; } //Stage time private String periodSts; public String getPeriodSts() { return periodSts; } public void setPeriodSts(String periodSts) { this.periodSts = periodSts; } } 1.2 FiscalYearPeriodPK.java
Encapsulate the primary key attribute. This class is separated from the FiscalYearPeriod class. It contains the basic primary key attributes and needs to implement the interface Serializable. This class is to be mapped to the <composite-id> tag in the configuration file to specify the class. The code is as follows:
package com.src.hibernate; import java.io.Serializable; public class FiscalYearPeriodPK implements Serializable { //year private int fiscalYear; public int getFiscalYear() { return fiscalYear; } public void setFiscalYear(int fiscalYear) { this.fiscalYear = fiscalYear; } //duration private int fiscalPeriod; public int getFiscalPeriod() { return fiscalPeriod; } public void setFiscalPeriod(int fiscalPeriod) { this.fiscalPeriod = fiscalPeriod; } } 2. Configuration file
Here is a question which of the two classes need to add mapping files? Because the <composite-id> tag is used, you only need to add a mapping for the FiscalYearPeriod class, add the corresponding composite primary key tag to the mapping file, and add the corresponding primary key attributes to the tag, as follows:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.src.hibernate.FiscalYearPeriod" table="t_fiscal_year_period_pk"> <composite-id name="fiscalYearPK"> <key-property name="fiscalYear"></key-property> <key-property name="fiscalPeriod"></key-property> </composite-id> <property name="beginDate" type="date"/> <property name="endDate" type="date"/> <property name="endDate" type="date"/> <property name="periodSts"/> </class> </hibernate-mapping>
The above file is generated to generate the corresponding database table, and the generated SQL statement is as follows:
drop table if exists t_fiscal_year_period_pk create table t_fiscal_year_period_pk (fiscalYear integer not null, fiscalPeriod integer not null, beginDate date, endDate date, periodSts varchar(255), primary key (fiscalYear, fiscalPeriod))
The corresponding table structure is as follows:
3. Data operation
After the corresponding mapping file is configured, the corresponding data operation becomes very simple. First, start with writing data. When writing data to the database, two classes will be written to the database at the same time. Therefore, both classes must be converted into Transient state. Therefore, when saving, you need to first save the FiscalYearPeriod object to the database first, and then it will automatically associate the composite attributes and save the information to the database.
3.1 Write operation
The write operation method is the same as the previous write method. You need to define two objects and then save the corresponding object information into the database. The code is as follows:
public void testSave1(){ //Declare the session object Session session=null; try{ //Get the session object session=HibernateUtils.getSession(); //Open the session session.beginTransaction(); //Create the composite object FiscalYearPeriodPK fiscalyearperiodpk=new FiscalYearPeriodPK(); fiscalyearperiodpk.setFiscalPeriod(2014); fiscalyearperiodpk.setFiscalYearYear(2012); //Create the object FiscalYearPeriod fiscalyearperiod=new FiscalYearPeriod(); fiscalyearperiod.setFiscalYearPeriodPK(fiscalyearperiodpk); session.save(fiscalyearperiod); //Submit session session session.getTransaction().commit(); }catch(Exception e){ e.printStackTrace(); session.getTransaction().rollback(); } finally{ HibernateUtils.closeSession(session); } }Execute the corresponding test method, and the generated SQL statement is as follows:
Hibernate: insert into t_fiscal_year_period_pk (beginDate, endDate, periodSts, fiscalYear, fiscalPeriod) values (?, ?, ?, ?, ?) The corresponding database view:
3.2 Loading operation
The corresponding loading method will be different from before, because the primary key in the table is a compound property, so a class needs to be created. When loading data, you need to create a primary key object. At this time, the primary key is an object, and you need to assign values to the object's properties to obtain the object. The code is as follows:
public void testLoad1(){ //Declare the session object Session session=null; try{ //Get the session object session=HibernateUtils.getSession(); //Open the session session.beginTransaction(); //Create the composite object FiscalYearPeriodPK fiscalyearperiodpk=new FiscalYearPeriodPK(); fiscalyearperiodpk.setFiscalPeriod(2014); fiscalyearperiodpk.setFiscalYear(2012); FiscalYearPeriod fiscalyearperiod=(FiscalYearPeriod)session.load(FiscalYearPeriod.class,fiscalyearperiodpk); System.out.println("Start Date: "+fiscalyearperiod.getBeginDate()); //Submit session session.getTransaction().commit(); }catch(Exception e){ e.printStackTrace(); session.getTransaction().rollback(); } finally{ HibernateUtils.closeSession(session); } }The result is as follows:
Hibernate: select fiscalyear0_.fiscalYear as fiscalYear0_0_, fiscalyear0_.fiscalPeriod as fiscalPe2_0_0_, fiscalyear0_.beginDate as beginDate0_0_, fiscalyear0_.endDate as endDate0_0_, fiscalyear0_.periodSts as periodSts0_0_ from t_fiscal_year_period_pk fiscalyear0_ where fiscalyear0_.fiscalYear=? and fiscalyear0_.fiscalPeriod=? Start Date: 2013-10-12
4. Comprehensive examples
A department table of a larger company (hibernate_dept_compositePK) consists of fields such as the area (area), department name (name), number of people in the department (empCount), and establishment time (birthday). We use the area and department name as the joint primary key:
4.1 Target class: Department.java
public class Department { /** Abstract the primary key association attribute and write it into a class separately*/ //private String area; //private String name; /**Preparing the primary key class object as a member variable*/ private DepartmentPK departmentPK; private int empCount; private Date birthday; // public String getArea() { // return area; // } // // public void setArea(String area) { // this.area = area; // } // // public String getName() { // return name; // } // // public void setName(String name) { // this.name = name; // } public int getEmpCount() { return empCount; } public void setEmpCount(int empCount) { this.empCount = empCount; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public DepartmentPK getDepartmentPK() { return departmentPK; } public void setDepartmentPK(DepartmentPK departmentPK) { this.departmentPK = departmentPK; } } 4.2 Primary Key Class: DepartmentPK.java
public class DepartmentPK implements Serializable { private static final long serialVersionUID = -288002855915204255L; private String area; private String name; /** * Overwrite hashCode method (judged based on area and name) */ //@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((area == null) ? 0 : area.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } /** * Overwrite equals(judged based on area and name) */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final DepartmentPK other = (DepartmentPK) obj; if (area == null) { if (other.area != null) return false; } else if (!area.equals(other.area)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } public String getArea() { return area; } public void setArea(String area) { this.area = area; } public String getName() { return name; } public void setName(String name) { this.name = name; } } 4.3 Mapping file Department.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.yangfei.hibernate.compositePk.entity.Department" table="hibernate_dept_compositePK"> <!-- Union primary key--> <!-- name refers to primary key object attributes--> <composite-id name="departmentPK"> <!-- Here is the primary key association property --> <key-property name="area" /> <key-property name="name" /> </composite-id> <!-- Other properties --> <property name="empCount" length="4" /> <property name="birthday" type="date" /> </class> </hibernate-mapping>
4.4 hibernate configuration file hibernate.cfg.xml
<?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <!-- Generated by MyEclipse Hibernate Tools. --> <hibernate-configuration> <session-factory> <property name="dialect">org.hibernate.dialect.Oracle9Dialect</property> <property name="connection.url">jdbc:oracle:thin:@127.0.0.1:1521:orcl10</property> <property name="connection.username">scott</property> <property name="connection.password">yf123</property> <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property> <property name="hibernate.show_sql">true</property> <mapping resource="com/yangfei/hibernate/compositePk/entity/Department.hbm.xml"/> </session-factory> </hibernate-configuration>
4.5 Test class: DepartmentTest.java
public class DepartmentTest extends TestCase { /** * Test insert data*/ public void save() { Session session = HibernateUtils.getSession(); Transaction t = session.beginTransaction(); try { Department dept = new Department(); /** Generate primary key object*/ DepartmentPK deptPK = new DepartmentPK(); deptPK.setArea("Beijing"); deptPK.setName("R&D Department"); dept.setDepartmentPK(deptPK); dept.setEmpCount(100); dept.setBirthday(new Date()); session.save(dept); t.commit(); } catch (HibernateException e) { e.printStackTrace(); t.rollback(); } finally { HibernateUtils.closeSession(session); } } /** * Test load data*/ public void load() { Session session = HibernateUtils.getSession(); Transaction t = session.beginTransaction(); try { /** Generate primary key object*/ DepartmentPK deptPK = new DepartmentPK(); deptPK.setArea("Beijing"); deptPK.setName("R&D Department"); Department dept=(Department)session.load(Department.class, deptPK); System.out.println(dept.getDepartmentPK().getArea()+","+dept.getDepartmentPK().getName()+","+dept.getEmpCount()+","+dept.getBirthday()); } catch (HibernateException e) { e.printStackTrace(); t.rollback(); } finally { HibernateUtils.closeSession(session); } } /** * Test modification data*/ public void update() { Session session = HibernateUtils.getSession(); Transaction t = session.beginTransaction(); try { /** Generate primary key object*/ DepartmentPK deptPK = new DepartmentPK(); deptPK.setArea("Beijing"); deptPK.setName("R&D Department"); Department emp=(Department)session.load(Department.class, deptPK); System.out.println(emp.getDepartmentPK().getArea()+","+emp.getDepartmentPK().getName()+","+emp.getEmpCount()+","+emp.getBirthday()); emp.setEmpCount(100); session.saveOrUpdate(emp); /** Generate primary key object*/ DepartmentPK deptPK2 = new DepartmentPK(); deptPK2.setArea("Beijing"); deptPK2.setName("R&D Department"); Department dept=(Department)session.load(Department.class, deptPK2); System.out.println(dept.getDepartmentPK().getArea()+","+dept.getDepartmentPK().getName()+","+dept.getEmpCount()+","+dept.getBirthday()); t.commit(); } catch (HibernateException e) { e.printStackTrace(); t.rollback(); } finally { HibernateUtils.closeSession(session); } } /** * Test delete data*/ public void delete() { Session session = HibernateUtils.getSession(); Transaction t = session.beginTransaction(); try { /** Generate primary key object*/ DepartmentPK deptPK = new DepartmentPK(); deptPK.setArea("Beijing"); deptPK.setName("R&D Department"); Department dept=(Department)session.load(Department.class, deptPK); session.delete(dept); t.commit(); } catch (HibernateException e) { e.printStackTrace(); t.rollback(); } finally { HibernateUtils.closeSession(session); } } }