这里有新鲜出炉的Java设计模式,程序狗速度看过来!
java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由Sun Microsystems公司于1995年5月推出的Java程序设计语言和Java平台(即JavaEE(j2ee), JavaME(j2me), JavaSE(j2se))的总称。
复合主键映射用起来比普通的增加主键字段要复杂,这里我们就来共同学习Java的Hibernate框架中复合主键映射的创建和使用教程,需要的朋友可以参考下
复合主键映射需要在映射配置文件中使用
Note:想要使用复合映射必须要将复合主键放到一个类中,也就是讲复合主键属性和其它属性分到两个类中,并将复合主键的类实现接口Serializable,该接口隶属于java.io。
复合主键的映射关系的主键是由多个列复合而成的,对应到数据表中相当的简单,如下图:
1、类文件
这里就拿上图的表来作为示例,在表中有两个字段年限和持续时间组合成为表的主键,所以分成的新类分别命名为FiscalYearPeriod和FiscalYearPeriodPK,其中FiscalYearPeriodPK类封装表的主键属性,FiscalYearPeriod类封装其它属性以及FiscalYearPeriodPK类。
1.1 FiscalYearPeriod.java
类中封装有基本的属性,并把FiscalYearPeriodPK类作为属性封装到类中,并在配置文件中配置相应的映射,如下代码:
- package com.src.hibernate;
- import java.sql.Date;
- public class FiscalYearPeriod {
- //时间主键
- private FiscalYearPeriodPK fiscalYearPeriodPK;
- public FiscalYearPeriodPK getFiscalYearPeriodPK() {
- return fiscalYearPeriodPK;
- }
- public void setFiscalYearPeriodPK(FiscalYearPeriodPK fiscalYearPeriodPK) {
- this.fiscalYearPeriodPK = fiscalYearPeriodPK;
- }
- //开始日期
- private Date beginDate;
- public Date getBeginDate() {
- return beginDate;
- }
- public void setBeginDate(Date beginDate) {
- this.beginDate = beginDate;
- }
- //结束日期
- private Date endDate;
- public Date getEndDate() {
- return endDate;
- }
- public void setEndDate(Date endDate) {
- this.endDate = endDate;
- }
- //阶段时间
- private String periodSts;
- public String getPeriodSts() {
- return periodSts;
- }
- public void setPeriodSts(String periodSts) {
- this.periodSts = periodSts;
- }
- }
1.2 FiscalYearPeriodPK.java
封装主键属性,该类是从FiscalYearPeriod类中分离出来的,包含了基本的主键属性,并且需要实现接口Serializable,该类是要映射到配置文件中
- package com.src.hibernate;
- import java.io.Serializable;
- public class FiscalYearPeriodPK implements Serializable {
- //年限
- private int fiscalYear;
- public int getFiscalYear() {
- return fiscalYear;
- }
- public void setFiscalYear(int fiscalYear) {
- this.fiscalYear = fiscalYear;
- }
- //持续时间
- private int fiscalPeriod;
- public int getFiscalPeriod() {
- return fiscalPeriod;
- }
- public void setFiscalPeriod(int fiscalPeriod) {
- this.fiscalPeriod = fiscalPeriod;
- }
- }
2、配置文件
这里有个疑问两个类都是哪个需要添加映射文件?因为会使用
- <?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="fiscalYearPeriodPK">
- <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="periodSts" />
- </class>
- </hibernate-mapping>
将上面的文件生成对应的数据库表,生成的sql语句如下:
- 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))
对应的表结构如下图:
3、数据操作
相应的映射文件配置好后,相应的数据操作就变得很简单了,首先从写入数据开始,向数据库中写入数据时会同时把两个类写入到数据库中,所以此时这两个类都必须转化为Transient状态,所以在保存时需要首先将FiscalYearPeriod对象首先保存到数据库中,然后它会自动关联复合属性,将信息保存到数据库中。
3.1 写入操作
写入的操作方法和以前的写入方法相同,需要定义两个对象,然后保存相应的对象信息到数据库中,代码如下:
- public void testSave1() {
- //声明会话对象
- Session session = null;
- try {
- //获取会话对象
- session = HibernateUtils.getSession();
- //开启会话
- session.beginTransaction();
- //创建复合对象
- FiscalYearPeriodPK fiscalyearperiodpk = new FiscalYearPeriodPK();
- fiscalyearperiodpk.setFiscalPeriod(2014);
- fiscalyearperiodpk.setFiscalYear(2012);
- //创建对象
- FiscalYearPeriod fiscalyearperiod = new FiscalYearPeriod();
- fiscalyearperiod.setFiscalYearPeriodPK(fiscalyearperiodpk);
- session.save(fiscalyearperiod);
- //提交会话
- session.getTransaction().commit();
- } catch(Exception e) {
- e.printStackTrace();
- session.getTransaction().rollback();
- } finally {
- HibernateUtils.closeSession(session);
- }
- }
执行相应的测试方法,生成的SQL语句如下:
相应的数据库视图:
- Hibernate: insert into t_fiscal_year_period_pk (beginDate, endDate, periodSts, fiscalYear, fiscalPeriod) values (?, ?, ?, ?, ?)
3.2 加载操作
相应的加载方法会和以前不同,因为在该表中主键是复合属性,所以需要创建一个类。在加载数据时需要创建主键对象,此时的主键就是一个对象,更需要为对象的属性赋值,这样才能获取对象,代码如下:
- public void testLoad1() {
- //声明会话对象
- Session session = null;
- try {
- //获取会话对象
- session = HibernateUtils.getSession();
- //开启会话
- session.beginTransaction();
- //创建复合对象
- FiscalYearPeriodPK fiscalyearperiodpk = new FiscalYearPeriodPK();
- fiscalyearperiodpk.setFiscalPeriod(2014);
- fiscalyearperiodpk.setFiscalYear(2012);
- FiscalYearPeriod fiscalyearperiod = (FiscalYearPeriod) session.load(FiscalYearPeriod.class, fiscalyearperiodpk);
- System.out.println("开始日期: " + fiscalyearperiod.getBeginDate());
- //提交会话
- session.getTransaction().commit();
- } catch(Exception e) {
- e.printStackTrace();
- session.getTransaction().rollback();
- } finally {
- HibernateUtils.closeSession(session);
- }
- }
生成的结果,如下:
- 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=?
- 开始日期: 2013-10-12
4、综合示例
一个规模较大公司的部门表(hibernate_dept_compositePK),由所在区域(area),部门名(name),本部门人数(empCount),组建时间(birthday)等字段组成,我们使用所在区域和部门名做联合主键:
4.1 目标类:Department.java
- public class Department {
- /** 把主键关联属性抽象出来单独写成一个类 */
- //private String area;
- //private String name;
- /**把主键类对象作为成员变量*/
- 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主键类:DepartmentPK.java
- public class DepartmentPK implements Serializable {
- private static final long serialVersionUID = -288002855915204255L;
- private String area;
- private String name;
- /**
- * 覆盖hashCode方法(根据area和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;
- }
- /**
- * 覆盖equals(根据area和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 映射文件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">
- <!-- 联合主键 -->
- <!-- name指的是主键对象属性 -->
- <composite-id name="departmentPK">
- <!-- 这里是主键关联属性 -->
- <key-property name="area" />
- <key-property name="name" />
- </composite-id>
- <!-- 其它属性 -->
- <property name="empCount" length="4" />
- <property name="birthday" type="date" />
- </class>
- </hibernate-mapping>
4.4 hibernate配置文件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测试类:DepartmentTest.java
- public class DepartmentTest extends TestCase {
- /**
- * 测试插入数据
- */
- public void save() {
- Session session = HibernateUtils.getSession();
- Transaction t = session.beginTransaction();
- try {
- Department dept = new Department();
- /** 生成主键对象 */
- DepartmentPK deptPK = new DepartmentPK();
- deptPK.setArea("北京");
- deptPK.setName("研发部");
- 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);
- }
- }
- /**
- * 测试加载数据
- */
- public void load() {
- Session session = HibernateUtils.getSession();
- Transaction t = session.beginTransaction();
- try {
- /** 生成主键对象 */
- DepartmentPK deptPK = new DepartmentPK();
- deptPK.setArea("北京");
- deptPK.setName("研发部");
- 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);
- }
- }
- /**
- * 测试修改数据
- */
- public void update() {
- Session session = HibernateUtils.getSession();
- Transaction t = session.beginTransaction();
- try {
- /** 生成主键对象 */
- DepartmentPK deptPK = new DepartmentPK();
- deptPK.setArea("北京");
- deptPK.setName("研发部");
- 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);
- /** 生成主键对象 */
- DepartmentPK deptPK2 = new DepartmentPK();
- deptPK2.setArea("北京");
- deptPK2.setName("研发部");
- 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);
- }
- }
- /**
- * 测试删除数据
- */
- public void delete() {
- Session session = HibernateUtils.getSession();
- Transaction t = session.beginTransaction();
- try {
- /** 生成主键对象 */
- DepartmentPK deptPK = new DepartmentPK();
- deptPK.setArea("北京");
- deptPK.setName("研发部");
- Department dept = (Department) session.load(Department.class, deptPK);
- session.delete(dept);
- t.commit();
- } catch(HibernateException e) {
- e.printStackTrace();
- t.rollback();
- } finally {
- HibernateUtils.closeSession(session);
- }
- }
- }
来源: http://www.phperz.com/article/17/1124/360450.html