Hibernate框架-联合主键映射

来源:互联网 发布:电脑主题壁纸软件 编辑:程序博客网 时间:2024/05/22 04:36

Hibernate联合主键映射

Hibernate允许直接将实体类的多个属性映射成联合主键,如果需要直接将实体类的多列映射成联合主键,则该实体类必须满足如下条件:

i. 有无参的构造方法
ii. 实现Java.io.Serializable接口
iii. 建议根据联合主键列所映射的属性来重写equals()hashCode()方法

例:

import java.io.Serializable;import java.util.Date;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.EnumType;import javax.persistence.Enumerated;import javax.persistence.Id;import javax.persistence.Table;import javax.persistence.Temporal;import javax.persistence.TemporalType;@Entity@Table(name="teacher")public class Teacher implements Serializable{    private static final long serialVersionUID = 4938691487727505015L;    private int id;    private String name;    private Title title;    private Date date;    @Id //!!    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    @Id //!!    @Column(length=50)    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    @Enumerated(EnumType.STRING)    public Title getTitle() {        return title;    }    public void setTitle(Title title) {        this.title = title;    }    @Temporal(TemporalType.DATE)    public Date getDate() {        return date;    }    public void setDate(Date date) {        this.date = date;    }    @Override    //重写equals()方法,根据id, name进行判断    public boolean equals(Object obj) {        if(obj == null) {            return false;        }        if(obj instanceof TeacherPk) {            TeacherPk pk = (TeacherPk) obj;            if(this.id == pk.getId() && this.name.equals(pk.getName())) {                return true;            }            return false;        }        return false;    }    @Override    public int hashCode() {        return this.getName().hashCode();    }}

测试方法:

    @Test    public void Teacher() {        Teacher teacher = new Teacher();        teacher.setId(1);        teacher.setName("teacher");        teacher.setTitle(Title.A);        teacher.setDate(new Date());        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();        Session session = sessionFactory.openSession();        Transaction transaction = session.beginTransaction();        session.save(teacher);        transaction.commit();        session.close();        HibernateUtil.close();    }

控制台日志
这里写图片描述

这里写图片描述

尝试插入相同的记录
这里写图片描述

传统方式

如果使用传统方式来开发Hibernate实体类,则实体类的设计不同于单一主键时:要将属于联合主键的字段从实体类中分离,单独建立一个主键类,这个主键类要求拥有无参的构造方法、实现**Java.io.Serializable**接口和重写**equals()**和**hashCode()**方法,因为数据库是要根据不同的字段的值判断是否为唯一主键的,那么判断机制肯定不能够和以往基于单一主键的判断机制相同。

实体类

public class Student {    private int id;    private String name;    private int age;    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }}

XML方式:

现在要改造为联合主键(id和name字段)

首先将id和name分离出去,建立主键类

//主键类import java.io.Serializable;public class StudentPk implements Serializable{    private static final long serialVersionUID = 8538253779495022662L;    private int id;    private String name;    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    @Override    public boolean equals(Object obj) {        if(obj == null) {            return false;        }        if(obj instanceof StudentPk) {            StudentPk pk = (StudentPk) obj;            if(this.id == pk.getId() && this.name.equals(pk.getName())) {                return true;            }            return false;        }        return false;    }    @Override    public int hashCode() {        return this.name.hashCode();    }}

新的实体类

public class Student {    private StudentPk pk = null;    private int age;    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    public StudentPk getPk() {        return pk;    }    public void setPk(StudentPk pk) {        this.pk = pk;    }}

student.hbm.xml文件

<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"><hibernate-mapping package="pers.msidolphin.hibernate.domain">    <class name="Student" table="_STUDENT">        <!--这个name属性指定的是主键对象在实体类中的属性名 class当然是主键类对应的完整类名-->        <composite-id name="pk" class="pers.msidolphin.hibernate.domain.StudentPk">            <!--映射联合主键里的各个属性-->            <key-property name="id" column="ID"></key-property>            <key-property name="name" column="NAME" length="50"></key-property>        </composite-id>        <property name="age" column="AGE"/>    </class></hibernate-mapping>

测试方法:

    @Test    public void Student() {        Student stu = new Student();        StudentPk pk = new StudentPk();        pk.setId(1);        pk.setName("admin");        stu.setAge(21);        stu.setPk(pk);        Configuration cfg = new Configuration();        cfg = cfg.configure();        SessionFactory  sf = HibernateUtil.getSessionFactory();        Session session = sf.openSession();        Transaction transaction = session.beginTransaction();        session.save(stu);        transaction.commit();        session.close();        sf.close();    }

控制台日志打印出的建表语句,primary key(id, name)说明以id和name字段建立了联合主键
这里写图片描述

查看插入结果:
这里写图片描述

尝试插入相同的记录
这里写图片描述



注解(Annotation)方式:

有三种:

i. **@Embeddable**:将主键类注解为@Embeddable,并将实体类的主键类对象属性加上@Id注解

ii. **@EmbeddedId**:直接把实体类的主键类对象属性加上此注解

iii. **@IdClass**:在实体类加上@IdClass注解,并且将该实体类中所有属于主键的属性都注解为@Id(这种方式在实体类中保留了主键字段,但是还是要依赖主键类)

@Embeddable方式:

实体类:

import java.util.Date;import javax.persistence.Entity;import javax.persistence.EnumType;import javax.persistence.Enumerated;import javax.persistence.Id;import javax.persistence.Temporal;import javax.persistence.TemporalType;@Entity@Table(name="teacher1")public class Teacher {    private TeacherPk pk = null;    private Title title;    private Date date;    @Id //!!    public TeacherPk getPk() {        return pk;    }    public void setPk(TeacherPk pk) {        this.pk = pk;    }    @Enumerated(EnumType.STRING)    public Title getTitle() {        return title;    }    public void setTitle(Title title) {        this.title = title;    }    @Temporal(TemporalType.DATE)    public Date getDate() {        return date;    }    public void setDate(Date date) {        this.date = date;    }}

主键类:

import java.io.Serializable;import javax.persistence.Column;import javax.persistence.Embeddable;@Embeddable //!!public class TeacherPk implements Serializable{    private static final long serialVersionUID = 1084438907442149399L;    private int id;    private String name;    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    @Column(length=50)    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    @Override    public boolean equals(Object obj) {        if(obj == null) {            return false;        }        if(obj instanceof TeacherPk) {            TeacherPk pk = (TeacherPk) obj;            if(this.id == pk.getId() && this.name.equals(pk.getName())) {                return true;            }            return false;        }        return false;    }    @Override    public int hashCode() {        return this.name.hashCode();    }}

测试结果:
这里写图片描述

@EmbeddedId方式:
实体类:

import java.util.Date;import javax.persistence.EmbeddedId;import javax.persistence.Entity;import javax.persistence.EnumType;import javax.persistence.Enumerated;import javax.persistence.Temporal;import javax.persistence.TemporalType;@Table(name="teacher2")public class Teacher2 {    private TeacherPk2 pk = null;    private Title title;    private Date date;    @EmbeddedId //!!    public TeacherPk2 getPk() {        return pk;    }    public void setPk(TeacherPk2 pk) {        this.pk = pk;    }    @Enumerated(EnumType.STRING)    public Title getTitle() {        return title;    }    public void setTitle(Title title) {        this.title = title;    }    @Temporal(TemporalType.DATE)    public Date getDate() {        return date;    }    public void setDate(Date date) {        this.date = date;    }}

主键类:

import java.io.Serializable;import javax.persistence.Column;public class TeacherPk2 implements Serializable{    private static final long serialVersionUID = 1084438907442149399L;    private int id;    private String name;    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    @Column(length=50)    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    @Override    public boolean equals(Object obj) {        if(obj == null) {            return false;        }        if(obj instanceof TeacherPk2) {            TeacherPk2 pk = (TeacherPk2) obj;            if(this.id == pk.getId() && this.name.equals(pk.getName())) {                return true;            }            return false;        }        return false;    }    @Override    public int hashCode() {        return this.name.hashCode();    }}

测试结果:
这里写图片描述

@IdClass方式:
实体类:

import java.util.Date;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.EnumType;import javax.persistence.Enumerated;import javax.persistence.Id;import javax.persistence.IdClass;import javax.persistence.Temporal;import javax.persistence.TemporalType;@Entity()@Table(name="teacher3")@IdClass(TeacherPk3.class) //!!public class Teacher3 {    private int id;    private String name;    private Title title;    private Date date;    @Id //!!    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    @Id //!!    @Column(length=50)    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    @Enumerated(EnumType.STRING)    public Title getTitle() {        return title;    }    public void setTitle(Title title) {        this.title = title;    }    @Temporal(TemporalType.DATE)    public Date getDate() {        return date;    }    public void setDate(Date date) {        this.date = date;    }}

主键类:
这里写图片描述

原创粉丝点击