Hibernate 学习经验之谈-(四)关联映射

摘要:

(待编写)

        Hibernate 是一个ORM 框架,它的重点就是对象之间的关系模型,维护对象之间的关系是hibernate 的核心内容,也是这个框架中相对比较难的一点。如果能够灵活地运用好这个框架,必须熟悉对象之间的联系。Hibernate 中的主要有三种对象的关系:One to One(一对一关联映射);One to Many (一对多关联映射);Many to Many (关联映射)。 每一种映射又分单向和双向。在数据库中关系表之间的关系只有一种,就是外键关联,hibernatre的对象映射就是建立在数据库外键关联之上。

要掌握hibernate的关联映射,必须要分析hibernate 在使用对象关联时生成的DDL语句,理解每一种映射在数据库中的对应处理方式。

单向关联与双向关联的区别

    对象通过组合的方式来表达的类之间的关系,并在hbm文件或者注解上做出明确的说明。 

           单向可以理解为在两个有关联的对象实体中,只在一方中说明关联关系,对象只能在一方导向到另一方。

           双向可以理解为在两个有关联的对象实体中,双方都有说明关联关系的配置,对象之间可以互相访问到对方。

          导向的意思是说在对象的关联字段访问到关联的对象的信息,双向和单向在数据库层级的实现基本一样。

           对于设置了双向关联的实体,最好的做法就是在其中一方使用mappedBy 指定主导关系,不然会出现冗余的数据字段。原则是在1-1 可以任意设一方,1-N 在N方设置mappedBy,N-N 的在任意一方设置。mappedBy 是关联注解的一个属性,mappedBy="xxx",xxx 为主导关系的getXXX对应的值。例如mappedBy=“person”  person 对应的不是下文中的person 属性,而是对应getter 中getXXX,的“XXX”位置的值,person 对应getPerson();


一.One to One(一对一关联映射)

1.解析:

例如,一个人只能有一张身份证,一张身份证只能对应一个人;这两个对象之间就是属于一对一;一对一是三种关系中最简单的一种。


2.种类:主键关联,唯一外键关联;

2.1 主键关联:两个对象采用一样的主键值来表明他们之间是属于一对一的关系,这种方法是基本不用的。

2.2 外键关联:两个对象采用外键来表示两个之间的联系。

3.配置方式(只讲外键关联)

3.1单向配置

Person

package com.hwj.model;

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

import org.hibernate.annotations.DynamicUpdate;

@Table(name="t_person")
@Entity
@DynamicUpdate
public class Person {

	private int id;
	private String nickName;
	
	
	//关联字段
	private IDCard idCard;
	
	@Id
	@GeneratedValue
	public int getId() {
		return id;
	}
	
	@OneToOne
	public IDCard getIdCard() {
		return idCard;
	}
	public String getNickName() {
		return nickName;
	}	
	public void setId(int id) {
		this.id = id;
	}
	public void setIdCard(IDCard idCard) {
		this.idCard = idCard;
	}
	public void setNickName(String nickName) {
		this.nickName = nickName;
	}

	
}

IDCard

<pre name="code" class="java">package com.hwj.model;

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

import org.hibernate.annotations.DynamicUpdate;

@Entity
@Table(name="t_idcard")
@DynamicUpdate
public class IDCard {

	private int id;
	private String name;
	private String idNo;

	
	
	
	@Id
	@GeneratedValue
	public int getId() {
		return id;
	}
	public String getIdNo() {
		return idNo;
	}
	public String getName() {
		return name;
	}

	public void setId(int id) {
		this.id = id;
	}
	public void setIdNo(String idNo) {
		this.idNo = idNo;
	}
	public void setName(String name) {
		this.name = name;
	}


	
}


 

hibernate 生成的sql语句

Hibernate: 
    create table t_idcard (
        id integer not null auto_increment,
        idNo varchar(255),
        name varchar(255),
        primary key (id)
    )
Hibernate: 
    create table t_person (
        id integer not null auto_increment,
        nickName varchar(255),
        idCard_id integer,
        primary key (id)
    )
Hibernate: 
    alter table t_person 
        add constraint FK_iwf0ex84epvoh2ndq1axpceg9 
        foreign key (idCard_id) 
        references t_idcard (id)


3.2 双向配置


Person

package com.hwj.model;

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

import org.hibernate.annotations.DynamicUpdate;

@Table(name="t_person")
@Entity
@DynamicUpdate
public class Person {

	private int id;
	private String nickName;
	
	
	//关联字段
	private IDCard idCard;
	
	@Id
	@GeneratedValue
	public int getId() {
		return id;
	}
	
	@OneToOne(mappedBy="pserson")
	public IDCard getIdCard() {
		return idCard;
	}
	public String getNickName() {
		return nickName;
	}	
	public void setId(int id) {
		this.id = id;
	}
	public void setIdCard(IDCard idCard) {
		this.idCard = idCard;
	}
	public void setNickName(String nickName) {
		this.nickName = nickName;
	}

	
}


IDCard

package com.hwj.model;

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

import org.hibernate.annotations.DynamicUpdate;

@Entity
@Table(name="t_idcard")
@DynamicUpdate
public class IDCard {

	private int id;
	private String name;
	private String idNo;
	private Person pserson;

	
	
	
	@Id
	@GeneratedValue
	public int getId() {
		return id;
	}
	public String getIdNo() {
		return idNo;
	}
	public String getName() {
		return name;
	}

	@OneToOne
	public Person getPserson() {
		return pserson;
	}
	public void setId(int id) {
		this.id = id;
	}
	public void setIdNo(String idNo) {
		this.idNo = idNo;
	}
	public void setName(String name) {
		this.name = name;
	}
	public void setPserson(Person pserson) {
		this.pserson = pserson;
	}


	
}



hibernate 生成的sql语句

Hibernate: 
    create table t_idcard (
        id integer not null auto_increment,
        idNo varchar(255),
        name varchar(255),
        pserson_id integer,
        primary key (id)
    )
Hibernate: 
    create table t_person (
        id integer not null auto_increment,
        nickName varchar(255),
        primary key (id)
    )
Hibernate: 
    alter table t_idcard 
        add constraint FK_pdvviqxfv7qwech66rqm08830 
        foreign key (pserson_id) 
        references t_person (id)


总结,使用主要使用外键关联,在双方设置了双向关联的时候,进行mappedBy 设置。 

二.One to Many  与 Many to One

      其实一对多,还有多对一,都只是在不同的角度来看,但是映射产生的结果可能会不一样。这里使用Group 组与 User 成员来做举例。

      1.单向映射

        1.1 One to Many (一对多 )

Group 映射

package com.hwj.model;

import java.util.List;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.annotations.UpdateTimestamp;

@Entity
@Table(name="t_group")
@DynamicUpdate
public class Group {

	private int id;
	private String name;
	private List<User> users;
	
	
	@Id
	@GeneratedValue
	public int getId() {
		return id;
	}
	public String getName() {
		return name;
	}
	
	
	
	@OneToMany
	@JoinColumn(name="group_id")
	public List<User> getUsers() {
		return users;
	}
	public void setId(int id) {
		this.id = id;
	}
	public void setName(String name) {
		this.name = name;
	}
	public void setUsers(List<User> users) {
		this.users = users;
	}
	
	
}


       User 的映射

package com.hwj.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

import org.hibernate.annotations.DynamicUpdate;

@Entity
@Table(name="t_user")
@DynamicUpdate
public class User {

	private int id;
	private String name;	


	@Id
	@GeneratedValue
	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;
	}
	
	
	
	
}


产生的sql语句

Hibernate: 
    create table t_group (
        id integer not null auto_increment,
        name varchar(255),
        primary key (id)
    )
Hibernate: 
    create table t_user (
        id integer not null auto_increment,
        name varchar(255),
        group_id integer,
        primary key (id)
    )
Hibernate: 
    alter table t_user 
        add constraint FK_e5f24mh6aryt9hsy99oydps6g 
        foreign key (group_id) 
        references t_group (id)



注意,假如在一对多关联映射中只使用了 One to Many 的话,hibernate 就会发生把One to Many 当成 many to many 方式生成sql 语句,生成的语句中会存在中间表。但是在关联字段添加@joinColumn(name="外键名称") ,j就可以避免这种情况生成正确的sql语句。


     1.2.many to one

          注:many to one 配置方式十分方便,只要在多的一方在关联字段加上 @ManyToOne 就可以正确在多一方生成外键约束。


2.双向关联

注;双向关联中需要在one 的一方设置mappedBy ,在many to one 的一方没有这个属性。设置完后就是实现了对数据的双向导航。


三.Many to Many (关联映射)

1.单向映射

只要在关联字段上添加@ManyToMany 就可以实现多对多单向映射。

2.双向映射

双向映射的时候一定要设置在任意一方设置mappedBy 这样才能不会执行重复的sql语句。

3.表生成

     多对多表映射是采用中间表的方式来实现映射的,中间表字段的修改可以使用@JoinTable来实现。这个注解可以修改中间表的表名,表中的外键字段。

            @JoinTable(

          joinColumns={@JoinColumn(name="本对象的外键引用字段名")},  //为数组的原因是考虑到联合主键的情况

         inverseJoinColumns={@JoinColumn(name="另外的一方的对象外键引用的字段名")}     //为数组的原因是考虑到联合主键的情况

         )




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值