Hibernate框架-联合主键映射

7 篇文章 0 订阅
5 篇文章 0 订阅

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;
    }
}

主键类:
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值