Hibernate中的Entity类之间的ManyToMany关联

原创 2016年05月31日 15:46:02

Hibernate中的Entity类之间的ManyToMany关联,必须在数据库模式中有一个中间连接表,其中的外键作为两个实体表之间的桥梁;而实体表中没有外键。

1. ManyToMany单向关联

任选一个实体类作为owning side,设置关联如下:

@Entity(name = "Person")
public static class Person {

    @Id
    @GeneratedValue
    private Long id;
    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    private List<Address> addresses = new ArrayList<>();

    public Person() {
    }

    public List<Address> getAddresses() {
        return addresses;
    }
}

在另一个实体类中不设置任何关联,如下:

@Entity(name = "Address")
public static class Address {

    @Id
    @GeneratedValue
    private Long id;

    private String street;

    private String number;

    public Address() {
    }

    public Address(String street, String number) {
        this.street = street;
        this.number = number;
    }

    public Long getId() {
        return id;
    }

    public String getStreet() {
        return street;
    }

    public String getNumber() {
        return number;
    }
}

单向关联中,没有关联实体类的概念。

单向关联中,删除被关联对象时,首先删除所有被关联的对象,然后再重新插入没有被删除的对象,存在性能瓶颈。


2.ManyToMany双向关联

在ManyToMany双向关联中,两个实体类可以互为父子类。任选其中一个作为父实体类(owning side),其中定义集合对象引用子实体类,子实体类(inverse side)方给出(mappedBy="...")指向父实体类。

父实体类(owning side)定义如下:

@Entity(name = "Person")
public static class Person {

    @Id
    @GeneratedValue
    private Long id;

    @NaturalId
    private String registrationNumber;
    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    private List<Address> addresses = new ArrayList<>();

    public Person() {
    }

    public Person(String registrationNumber) {
        this.registrationNumber = registrationNumber;
    }

    public List<Address> getAddresses() {
        return addresses;
    }

    public void addAddress(Address address) {
        addresses.add( address );
        address.getOwners().add( this );
    }

    public void removeAddress(Address address) {
        addresses.remove( address );
        address.getOwners().remove( this );
    }

    @Override
    public boolean equals(Object o) {
        if ( this == o ) {
            return true;
        }
        if ( o == null || getClass() != o.getClass() ) {
            return false;
        }
        Person person = (Person) o;
        return Objects.equals( registrationNumber, person.registrationNumber );
    }

    @Override
    public int hashCode() {
        return Objects.hash( registrationNumber );
    }
}

子实体类(inverse side)定义如下:

@Entity(name = "Address")
public static class Address {

    @Id
    @GeneratedValue
    private Long id;

    private String street;

    private String number;

    private String postalCode;

    @ManyToMany(mappedBy = "addresses")
    private List<Person> owners = new ArrayList<>();

    public Address() {
    }

    public Address(String street, String number, String postalCode) {
        this.street = street;
        this.number = number;
        this.postalCode = postalCode;
    }

    public Long getId() {
        return id;
    }

    public String getStreet() {
        return street;
    }

    public String getNumber() {
        return number;
    }

    public String getPostalCode() {
        return postalCode;
    }

    public List<Person> getOwners() {
        return owners;
    }

    @Override
    public boolean equals(Object o) {
        if ( this == o ) {
            return true;
        }
        if ( o == null || getClass() != o.getClass() ) {
            return false;
        }
        Address address = (Address) o;
        return Objects.equals( street, address.street ) &&
                Objects.equals( number, address.number ) &&
                Objects.equals( postalCode, address.postalCode );
    }

    @Override
    public int hashCode() {
        return Objects.hash( street, number, postalCode );
    }
}

3.ManyToMany双向关联与两个OneToMany双向关联的等价替换

为中间表定义一个关联实体类,定义两个@ManyToOne关联,并作为owning side。
在两个实体类中分别定义一个@OneToMany关联,都作为inverse side。

关联实体类的定义如下:

@Entity(name = "PersonAddress")
public static class PersonAddress implements Serializable {

    @Id
    @ManyToOne
    private Person person;

    @Id
    @ManyToOne
    private Address address;

    public PersonAddress() {
    }

    public PersonAddress(Person person, Address address) {
        this.person = person;
        this.address = address;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    @Override
    public boolean equals(Object o) {
        if ( this == o ) {
            return true;
        }
        if ( o == null || getClass() != o.getClass() ) {
            return false;
        }
        PersonAddress that = (PersonAddress) o;
        return Objects.equals( person, that.person ) &&
                Objects.equals( address, that.address );
    }

    @Override
    public int hashCode() {
        return Objects.hash( person, address );
    }
}
注意:其中定义了两个@ManyToOne关联,并且都是作为owning side。

一个实体类定义如下:

@Entity(name = "Person")
public static class Person implements Serializable {

    @Id
    @GeneratedValue
    private Long id;

    @NaturalId
    private String registrationNumber;

    @OneToMany(mappedBy = "person", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<PersonAddress> addresses = new ArrayList<>();

    public Person() {
    }

    public Person(String registrationNumber) {
        this.registrationNumber = registrationNumber;
    }

    public Long getId() {
        return id;
    }

    public List<PersonAddress> getAddresses() {
        return addresses;
    }

    public void addAddress(Address address) {
        PersonAddress personAddress = new PersonAddress( this, address );
        addresses.add( personAddress );
        address.getOwners().add( personAddress );
    }

    public void removeAddress(Address address) {
        PersonAddress personAddress = new PersonAddress( this, address );
        address.getOwners().remove( personAddress );
        addresses.remove( personAddress );
        personAddress.setPerson( null );
        personAddress.setAddress( null );
    }

    @Override
    public boolean equals(Object o) {
        if ( this == o ) {
            return true;
        }
        if ( o == null || getClass() != o.getClass() ) {
            return false;
        }
        Person person = (Person) o;
        return Objects.equals( registrationNumber, person.registrationNumber );
    }

    @Override
    public int hashCode() {
        return Objects.hash( registrationNumber );
    }
}
注意:其中定义了一个@OneToMany关联,并且作为inverse side。

另一个实体类定义如下:

@Entity(name = "Address")
public static class Address implements Serializable {

    @Id
    @GeneratedValue
    private Long id;

    private String street;

    private String number;

    private String postalCode;

    @OneToMany(mappedBy = "address", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<PersonAddress> owners = new ArrayList<>();

    public Address() {
    }

    public Address(String street, String number, String postalCode) {
        this.street = street;
        this.number = number;
        this.postalCode = postalCode;
    }

    public Long getId() {
        return id;
    }

    public String getStreet() {
        return street;
    }

    public String getNumber() {
        return number;
    }

    public String getPostalCode() {
        return postalCode;
    }

    public List<PersonAddress> getOwners() {
        return owners;
    }

    @Override
    public boolean equals(Object o) {
        if ( this == o ) {
            return true;
        }
        if ( o == null || getClass() != o.getClass() ) {
            return false;
        }
        Address address = (Address) o;
        return Objects.equals( street, address.street ) &&
                Objects.equals( number, address.number ) &&
                Objects.equals( postalCode, address.postalCode );
    }

    @Override
    public int hashCode() {
        return Objects.hash( street, number, postalCode );
    }
}
注意:其中定义了一个@OneToMany关联,并且作为inverse side。


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Hibernate中多对多的annotation的写法(中间表可以有多个字段)

2011-07-04 6:52 一般情况下,多对多的关联关系是需要中间表的; 情况一:如果中间表仅仅是做关联用的,它里面仅有2个外键做联合主键,则使用ManyToMany(不用...

Hibernate学习总结:ManyToMany双向关联

说明: 一、一个老师可以教许多学生,并且一个学生可以有许多老师。 二、本次使用的Hibernate版本是hibernate-release-4.3.11.Final. ...

ManyToMany(基于注解)使用之进阶(中级版)

社团和成员就是多对多的关系,一个成员有多个社团,一个社团也有多个成员,这里的多对多映射采用中间表连接的映射策略,建立中间表的映射策略,建立中间表分别引入俩边的主键作为外键。通过中间表映射俩个表之间的关...

Hibernate中的Entity类之间的OneToMany关联

OneToMany关联将一个父Entity类与若干个子Entity类联系起来。 1. 双向关联 通常,OneToMany关联都有与之反向的ManyToOne关联对应,两者成组出现,这被称为双向关联...

Hibernate ManyToMany 删除两个实体的关联

在我的工程中,有这么两个实体:GrowthDiary.java(成长日记)和DiaryTag.java(日记标签)。 大概就是和csdn发表文章给文章打标签一个意思吧。 现在我想在后台管理平台删除...

Hibernate关系映射(六)多对多单向关联@ManyToMany Annotation方式

本篇介绍多对多的单向关联,多对多的处理方式是,有一张中间表,中间表保存两个多方之间的关系。首先来看实际应用场景:在之前开发的系统中,应用了基于角色的控制访问,也就是RBAC模型,一个用户可能存在多种角...

Hibernate关系映射(七)多对多双向关联@ManyToMany Annotation方式

本篇介绍多对多的双向关联,也是Hibernate关系映射的结尾篇,后续篇章会介绍Hibernate的懒加载机制和级联相关操作。首先还是来模拟一个实际应用的场景,在之前开发过的RBAC模型中,有这样一个...

Hibernate学习总结:ManyToMany单向关联

说明: 一、一个老师可以教许多学生,并且一个学生可以有许多老师。 二、本次使用的Hibernate版本是hibernate-release-4.3.11.Final. 先写Ann...

Hibernate中的Entity类之间的继承关系之一MappedSuperclass

在Hibernate中,Entity类可以继承Entity类或非Entity类。但是,关系数据库表之间不存在继承的关系。那么在Entity类之间的继承关系,在数据库表中如何表示呢? Hibernate...

Hibernate中的Entity类之间的继承关系之四TABLE_PER_CLASS

对于Hibernate提供的4种兼容JPA的映射策略,这里介绍第四种table-per-concrete-class策略。事实上,从数据库表结构看,这种策略下的每个Entity类都对应一个独立的数据库...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Hibernate中的Entity类之间的ManyToMany关联
举报原因:
原因补充:

(最多只允许输入30个字)