hibernate注解配置关联

hibernate注解配置关联

对于mappedBy复习下:
a) 只有OneToOne,OneToMany,ManyToMany上才有mappedBy属性,ManyToOne不存在该属性;
b) mappedBy标签一定是定义在the owned side(被拥有方的),他指向the owning side(拥有方);
c) 关系的拥有方负责关系的维护,在拥有方建立外键。所以用到@JoinColumn
d)mappedBy跟JoinColumn/JoinTable总是处于互斥的一方

一对多双向

@OneToMany(cascade=CascadeType.ALL,orphanRemoval=true,mappedBy="shop")
private Set<Employee> employees;

@ManyToOne(cascade = { CascadeType.ALL })
@JoinColumn(name="shop")
private Shop shop;

一对一单向

 @OneToOne
 @JoinColumn(name = "details_id")
 private PhoneDetails details;
 Phone表中添加关联字段

一对一双向 (双向关联 mappedBy指向创建外键的那个表)

@OneToOne(mappedBy="phone",cascade=CascadeType.ALL,orphanRomval=true FetchType.LAZY)
private PhoneDetails details; //Phone类
//添加删除
public void addDetails(PhoneDetails details) {
      details.setPhone( this );
      this.details = details;
  }
 public void removeDetails() {
      if ( details != null ) {
          details.setPhone( null );
          this.details = null;
      }
  }


@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "phone_id") //外键在PhoneDetails表中
private Phone phone;//PhoneDetails类


---------

Phone phone = new Phone( "123-456-7890" );
PhoneDetails details = new PhoneDetails( "T-Mobile", "GSM" );

phone.addDetails( details ); //级联保存
entityManager.persist( phone );//通过保存Phone级联保存details

INSERT INTO Phone ( number, id )VALUES ( '123 - 456 - 7890', 1 )

INSERT INTO PhoneDetails ( phone_id, provider, technology, id )VALUES ( 1, 'T - Mobile, GSM', 2 )

---------

多对一(单向)

@ManyToOne
    @JoinColumn(name = "person_id",
            foreignKey = @ForeignKey(name = "PERSON_ID_FK")
    )

多对多单向

@ManyToMany(cascade = {CascadeType.PERSIST,CascadeType.MERGE})//一般不会配置级联删除,因为可以别的Person可能还与address关联着
private List<Address> addresses = new ArrayList<>();

----------------
CREATE TABLE Address (
    id BIGINT NOT NULL ,
    number VARCHAR(255) ,
    street VARCHAR(255) ,
    PRIMARY KEY ( id )
)

CREATE TABLE Person (
    id BIGINT NOT NULL ,
    PRIMARY KEY ( id )
)

CREATE TABLE Person_Address (
    Person_id BIGINT NOT NULL ,
    addresses_id BIGINT NOT NULL
)
ALTER TABLE Person_Address
ADD CONSTRAINT FKm7j0bnabh2yr0pe99il1d066u
FOREIGN KEY (addresses_id) REFERENCES Address

ALTER TABLE Person_Address
ADD CONSTRAINT FKba7rc9qe2vh44u93u0p2auwti
FOREIGN KEY (Person_id) REFERENCES Person
----------------



Person person1 = new Person();
Person person2 = new Person();

Address address1 = new Address( "12th Avenue", "12A" );
Address address2 = new Address( "18th Avenue", "18B" );

person1.getAddresses().add( address1 );
person1.getAddresses().add( address2 );
person2.getAddresses().add( address1 );

entityManager.persist( person1 ); //级联保存address1和address2
entityManager.persist( person2 );
//插入Person1,插入address1,插入address2,插入Person2,向中间表中插入person1关联的address1和address2,向中间插入person2关联的address1
entityManager.flush();
//从中间表删除person_id=person1 id的数据,再向中间表插入person1关联的address2
person1.getAddresses().remove( address1 );

多对多双向


@Id
@GeneratedValue
private Long id;

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

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 ); //自然主键
}

@ManyToMany(mappedBy = "addresses") //指向拥有方,让Address类维护关系
private List<Person> owners = new ArrayList<>();

 @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 );
 }
-----------
同上的person和address,当person1.removeAddress( address1 );只会删除中间表的一条数据,而不会先都删除在添加没有删除的数据

如果双向@OneToMany协会执行更好的去除或改变子元素的顺序时,@ManyToMany关系不能受益于这样的优化,因为外键不控制。为了克服这个限制,必须直接接触和联系表格分成两个双向@OneToMany @ManyToMany协会的关系。
-------------

一对多双向(person->多personAddress,Address是->多PersonAddress )

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

 public void addAddress(Address address) {
    PersonAddress personAddress = new PersonAddress( this, address );
      addresses.add( personAddress );
       this.address.getOwners().add( personAddress );
  }
//只是删除中间表的数据,而不删除address表中的数据
  public void removeAddress(Address address) {
     PersonAddress personAddress = new PersonAddress( this, address );
      address.getOwners().remove( personAddress );
      this.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 );
  }
  //中间表类 PersonAddress
@Id
@ManyToOne
private Person person;

@Id
@ManyToOne
private 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 );
   }

 //表类 Address
 @OneToMany(mappedBy = "address", cascade = CascadeType.ALL, orphanRemoval = true)
private List<PersonAddress> owners = new ArrayList<>();
   @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 );
  }

多对多

@ManyToMany(mappedBy="categories")
    private Set<Brand> brands=new HashSet<>();
    @ManyToMany(/*cascade={ CascadeType.ALL}*/)
    @JoinTable(
                name="tb_brand_category",
                joinColumns=@JoinColumn(name="brand_id"),
                inverseJoinColumns=@JoinColumn(name="category_id")
            )
    private Set<Category> categories=new HashSet<>();

    public void addCategory(Category category){
        category.getBrands().add(this);
        this.categories.add(category);
    }

    public void removeAllCategory(){
        this.categories.clear();

    }

    public void removeCategory(String code){
        Category c=null;
        for (Category category : categories) {
            if(category.getCode().equals(code)){
                c=category;
                break;
            }
        }
        this.categories.remove(c);
    }

    public void addAll(List<Category> category){
        removeAllCategory();
        category.forEach((c)->{
            addCategory(c);
        });
    }

值集合

1集合
@Entity(name = "Person")
public static class Person {
    @Id
    private Long id;
    @ElementCollection
    private List<String> phones = new ArrayList<>();
    public List<String> getPhones() {
        return phones;
    }
}
//@ElementCollection 添加和删除所有元素比较简单,删除某个元素则要重新组件集合
person.getPhones().remove(0);    
DELETE FROM Person_phones WHERE Person_id = 1 //删除所有 
INSERT INTO Person_phones ( Person_id, phones )VALUES ( 1, '456-000-1234' ) //把没有删除的重新插入数据库

2.顺序集合
@ElementCollection
@OrderColumn(name = "order_id")
private List<String> phones = new ArrayList<>();

//**@OrderColumn从集合的尾部删除时,该列最适用**,因为它只需要一个删除语句。从集合的头部或中间移除需要删除额外的元素并更新其余元素以保留元素顺序。

3.可插入类型集合
@Embeddable
public static class Phone {
    private String type;
    @Column(name = "`number`")
    private String number;
}
@Entity(name = "Person")
public static class Person {
    @Id
    private Long id;
    @ElementCollection
    private List<Phone> phones = new ArrayList<>();
}

/*@ElementCollection
@CollectionTable(name = "tb_orders_items", joinColumns = @JoinColumn(name = "orders_id")) 指定值集合表名和外键名
*/
3.一对多单向关联(很想值集合)
@Entity(name = "Person")
public static class Person {
    @Id
    private Long id;
    @OneToMany(cascade = CascadeType.ALL)
    private List<Phone> phones = new ArrayList<>();
}
@Entity(name = "Phone")
public static class Phone {
    @Id
    private Long id;
    private String type;
    @Column(name = "`number`")
    private String number;
}
当设置CascadeType.ALL级联操作时,单向关联生命周期变得非常类似于值类型集合。
在删除或重新排列元素方面,效率不高,父端不能标识每个单独的孩子,因此会删除所有关联的字表行,再重新添加他他们

4.双向关联则提高效率
@Entity(name = "Person")
public static class Person {

    @Id
    private Long id;
    @OneToMany(mappedBy = "person", cascade = CascadeType.ALL)
    private List<Phone> phones = new ArrayList<>();

    public Person() {
    }

    public Person(Long id) {
        this.id = id;
    }

    public List<Phone> getPhones() {
        return phones;
    }

    public void addPhone(Phone phone) {
        phones.add( phone );
        phone.setPerson( this );
    }

    public void removePhone(Phone phone) {
        phones.remove( phone );
        phone.setPerson( null );
    }
}

@Entity(name = "Phone")
public static class Phone {
    @Id
    private Long id;
    private String type;
    @Column(name = "`number`", unique = true)
    @NaturalId
    private String number;
    @ManyToOne
    private Person person;
    public Phone() {
    }
    public Phone(Long id, String type, String number) {
        this.id = id;
        this.type = type;
        this.number = number;
    }
    public Long getId() {
        return id;
    }
    public String getType() {
        return type;
    }
    public String getNumber() {
        return number;
    }
    public Person getPerson() {
        return person;
    }
    public void setPerson(Person person) {
        this.person = person;
    }
    @Override
    public boolean equals(Object o) {
        if ( this == o ) {
            return true;
        }
        if ( o == null || getClass() != o.getClass() ) {
            return false;
        }
        Phone phone = (Phone) o;
        return Objects.equals( number, phone.number );
    }
    @Override
    public int hashCode() {
        return Objects.hash( number );
    }
}

有序List

@OneToMany(cascade = CascadeType.ALL)
@OrderBy("number") //查询sql通过phones表的number字段 order by phones.number
private List<Phone> phones = new ArrayList<>();
//指定多个字段@OrderBy("name ASC, type DESC"))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值