Hibernate框架-1对1关联

7 篇文章 0 订阅
5 篇文章 0 订阅
这篇博客详细介绍了Hibernate框架中的单向和双向1对1关联,包括基于外键和联合主键的情况。通过Annotation和XML两种方式进行配置,涵盖了无连接表和有连接表的场景,并提供了相应的实体类和XML映射文件示例。
摘要由CSDN通过智能技术生成

Hibernate单向1-1关联

对于单向的1-1关联,需要在实体类中增加相对应关联实体的属性(关联实体对象)

基于外键的单向1-1关联

Annotation方式
无连接表的单向1-1关联

首先使用@OneToOne注解代表关联实体的属性,再使用@JoinColumn映射外键即可
例:Husband类中设置了对应的Wife类对象,并为之增加@OneToOne和@JoinColumn注解,其中unique=true保证了wife_id字段的唯一性

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToOne;

/**
 * @author msidolphin
 * @time   2017年6月3日
 */
@Entity
public class Husband {

    private int id;
    private String name;
    private Wife wife;

    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }

    @Column(length = 50)
    public String getName() {
        return name;
    }

    @OneToOne
    @JoinColumn(name="wife_id", unique=true) 
    public Wife getWife() {
        return wife;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setWife(Wife wife) {
        this.wife = wife;
    }
}

由于是单向1-1,所有Wife类中没有设置Husband对象

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

/**
 * @author msidolphin
 * @time   2017年6月3日
 */
@Entity
public class Wife {

    private int id;
    private String name;

    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }

    @Column(length = 50)
    public String getName() {
        return name;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }
}

测试类:

import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.junit.Test;

/**
 * @author msidolphin
 * @time   2017年6月3日
 */
public class DomainJunit {
    @Test
    public void schemaExport_() {
        new SchemaExport(new Configuration().configure()).create(false, true);
    }
}

控制台日志输出的SQL语句
这里写图片描述

有连接表的单向1-1关联

有连接表的单向1-1关联需要使用@JoinTable注解映射连接表,由于是1-1关联,因此需要为@JoinTable注解中的joinColumns属性映射的外键字段设置unique=true属性,以此保证严格的1-1关联
Husband类:

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToOne;

/**
 * @author msidolphin
 * @time   2017年6月3日
 */
@Entity
public class Husband {

    private int id;
    private String name;
    private Wife wife;

    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
    @Column(length = 50)
    public String getName() {
        return name;
    }
    @OneToOne
    @JoinColumn(name="wife_id", unique=true) 
    @JoinTable(
            name="husband_wife", //表名
            joinColumns=@JoinColumn(
                    name="husband_id", 
                    unique=true, 
                    referencedColumnName="id"
            ),
            inverseJoinColumns=@JoinColumn(
                    name="wife_id",
                    unique=true,
                    referencedColumnName="id"
            )
    )
    public Wife getWife() {
        return wife;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setWife(Wife wife) {
        this.wife = wife;
    }
}

Wife类无需改动,同上

控制台输出的sql语句:
这里写图片描述

XML方式

使用<many-to-one>标签设置关联实体属性,由于是1-1,所以unique属性要设置为true
husband.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.one2one">
    <class name="Husband" table="husband">
        <id name="id" column="id">
            <generator class="native"></generator>
        </id>
        <property name="name" column="name" length="50"/>
        <many-to-one name="wife" column="wife_id" unique="true"></many-to-one>
    </class>
</hibernate-mapping>

wife.hbm.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!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.one2one">
    <class name="Wife" table="wife">
        <id name="id" column="id">
            <generator class="native"></generator>
        </id>
        <property name="name" column="name" length="50"></property>
    </class>
</hibernate-mapping>

Hibernate双向1-1关联

双向1-1关联需要在两个实体类中都增加引用关联实体的属性

基于外键的双向1-1关联

Annotation方式
无连接表的双向1-1关联

两端都需要为关联实体属性增加@OneToOne注解,对于基于外键的双向1-1关联,外键可以存放在任意一端,存放外键的一端,需要增加@JoinColumn注解映射外键字段,当选择一方增加外键后,该表即变为从表,而另一张表则为主表,主表对应的实体使用@OneToOne注解时,应增加mappedBy属性,表示该表作为主表使用,不增加对应从表的外键(这么做是为了防止修改从表时需要更新对应的主表字段,导致生成额外的update语句,引起性能下降)
例:
Husband类:husband表作为主表

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;

/**
 * @author msidolphin
 * @time   2017年6月3日
 */
@Entity
public class Husband {

    private int id;
    private String name;
    private Wife wife;

    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }

    @Column(length = 50)
    public String getName() {
        return name;
    }

    @OneToOne(mappedBy="husband")
    public Wife getWife() {
        return wife;
    }
    public void setId(int id) {
        this.id = id;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setWife(Wife wife) {
        this.wife = wife;
    }
}

Wife类:

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;

/**
 * @author msidolphin
 * @time   2017年6月3日
 */
@Entity
public class Wife {

    private int id;
    private String name;
    private Husband husband;

    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }

    @Column(length = 50)
    public String getName() {
        return name;
    }

    @OneToOne
    @JoinColumn(
            name="husband_id", 
            unique=true
    ) 
    public Husband getHusband() {
        return husband;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setHusband(Husband husband) {
        this.husband = husband;
    }
}

结果:
这里写图片描述

有连接表的双向1-1关联

有连接表的双向1-1关联需要在两端都使用@JoinTable映射连接表,在映射连接表时,两端指定的连接表的表名应当相同,字段名当然也要一致
Husband类:

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToOne;

/**
 * @author msidolphin
 * @time   2017年6月3日
 */
@Entity
public class Husband {

    private int id;
    private String name;
    private Wife wife;

    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }

    @Column(length = 50)
    public String getName() {
        return name;
    }

    @OneToOne
    @JoinTable(
            name="husband_wife", //表名
            joinColumns=@JoinColumn(
                    name="husband_id", 
                    unique=true, 
                    referencedColumnName="id"
            ),
            inverseJoinColumns=@JoinColumn(
                    name="wife_id",
                    unique=true,
                    referencedColumnName="id"
            )
    )
    public Wife getWife() {
        return wife;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setWife(Wife wife) {
        this.wife = wife;
    }
}

Wife类:

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToOne;

/**
 * @author msidolphin
 * @time   2017年6月3日
 */
@Entity
public class Wife {

    private int id;
    private String name;
    private Husband husband;

    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }

    @Column(length = 50)
    public String getName() {
        return name;
    }

    @OneToOne
    @JoinTable(
            name="husband_wife", //表名
            joinColumns=@JoinColumn(
                    name="wife_id", 
                    unique=true, 
                    referencedColumnName="id"
            ),
            inverseJoinColumns=@JoinColumn(
                    name="husband_id",
                    unique=true,
                    referencedColumnName="id"
            )
    )
    public Husband getHusband() {
        return husband;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setHusband(Husband husband) {
        this.husband = husband;
    }
}

结果:
这里写图片描述

XML方式

husband.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.one2one">
    <class name="Husband" table="husband">
        <id name="id" column="id">
            <generator class="native"></generator>
        </id>
        <property name="name" column="name" length="50"/>
        <many-to-one name="wife" column="wife_id" unique="true"></many-to-one>
    </class>
</hibernate-mapping>

wife.hbm.xml文件
注:这里使用的是<one-to-one>标签,如果使用<many-to-one>标签,则在两张表中都会生成外键字段

<?xml version="1.0" encoding="UTF-8"?>
<!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.one2one">
    <class name="Wife" table="wife">
        <id name="id" column="id">
            <generator class="native"></generator>
        </id>
        <property name="name" column="name" length="50"></property>
        <one-to-one name="husband"></one-to-one>
    </class>
</hibernate-mapping>

Hibernate联合主键关联

Annotation方式

Wife类:id和name字段作为联合主键

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;


/**
 * @author msidolphin
 * @time   2017年6月3日
 */
@Entity
public class Wife implements Serializable{

    private static final long serialVersionUID = 1L;

    private int id;
    private String name;

    @Id
    public int getId() {
        return id;
    }

    @Id
    @Column(length = 50)
    public String getName() {
        return name;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object obj) {
        if(obj == null) {
            return false;
        }

        if(obj instanceof Wife) {
            Wife pk = (Wife) 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();
    }
}

Husband类:

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.OneToOne;

/**
 * @author msidolphin
 * @time   2017年6月3日
 */
@Entity
public class Husband {

    private int id;
    private String name;
    private Wife wife;

    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }

    @Column(length = 50)
    public String getName() {
        return name;
    }

    @OneToOne
    @JoinColumns({
        @JoinColumn(name="wife_id", referencedColumnName="id", unique=true),
        @JoinColumn(name="wife_name", referencedColumnName="name", unique=true)
    })
    public Wife getWife() {
        return wife;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setWife(Wife wife) {
        this.wife = wife;
    }
}

控制台打印的SQL建表语句:
这里写图片描述

XML方式

主键类: Wife表的id和name字段作为联合主键

import java.io.Serializable;

/**
 * @author msidolphin
 * @time   2017年6月3日
 */

public class WifePk implements Serializable{

    private static final long serialVersionUID = 1L;

    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }   

    @Override
    public boolean equals(Object obj) {
        if(obj == null) {
            return false;
        }

        if(obj instanceof WifePk) {
            WifePk pk = (WifePk) 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();
    }

}

Wife类:

/**
 * @author msidolphin
 * @time   2017年6月3日
 */
public class Wife {

    private WifePk pk;

    public WifePk getPk() {
        return pk;
    }

    public void setPk(WifePk pk) {
        this.pk = pk;
    }
}

Husband类:

/**
 * @author msidolphin
 * @time   2017年6月3日
 */
public class Husband {

    private int id;
    private String name;
    private Wife wife;

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public Wife getWife() {
        return wife;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setWife(Wife wife) {
        this.wife = wife;
    }
}

wife.hbm.xml文件,由于使用了联合主键,所以应该使用<composite-id>标签

<?xml version="1.0" encoding="UTF-8"?>
<!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.one2one">
    <class name="Wife" table="wife">
        <composite-id name="pk" class="pers.msidolphin.hibernate.one2one.WifePk">
            <key-property name="id"></key-property>
            <key-property name="name" length="50"></key-property>
        </composite-id>
    </class>
</hibernate-mapping>

husband.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.one2one">
    <class name="Husband" table="husband">
        <id name="id" column="id">
            <generator class="native"></generator>
        </id>
        <property name="name" column="name" length="50"/>
        <many-to-one name="wife">
            <!-- 要格外注意顺序 -->
            <column name="wife_id" unique="true"></column>  
            <column name="wife_name"  unique="true"></column>   
        </many-to-one>
    </class>
</hibernate-mapping>

控制台打印的SQL建表语句:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值