Hibernate4学习总结(4)--注解形式的集合映射,关联关系映射

来源:互联网 发布:spss怎么导入excel数据 编辑:程序博客网 时间:2024/05/18 01:44

      本文将接着上文,讲解hibernate4的集合映射的注解和关联关系映射的注解。本文包括两个部分:

  1. 集合映射的注解。
  2. 关联关系映射的注解。

一、集合映射的注解

         当持久化中有一个属性是集合(Set、List、Map),就要用到集合映射。集合属性会单独生成一张表。定义集合属性时面向接口,并且集合属性需要程序员自己初始化(例如:private List<String> list = new ArrayList<String>();)。

集合属性都要用到的注解:

  • @ElementCollection(fetch="该属性的加载策略",targetClass="集合中元素的类型")。
           fetch=FetchType.EAGER: 立即加载
           fetch=FetchType.LAZY: 延迟加载
  • @CollectionTable(name="表名") : 指定集合生成表的相关信息。

1.1 List集合映射(有序集合): @OrderColumn() 指定排序列

注意:List集合生成表的主键列:(外键列 + 排序列)

1.1.1 List<String> : 集合中元素是标量类型 8个基本类型、包装类、String。

例如:Employee类

package edu.scut.e_CollectionMapping_List;import java.io.Serializable;import java.util.ArrayList;import java.util.List;import javax.persistence.*;@Entity@Table(name="EMP_INFO")public class Employee implements Serializable {@Id @GeneratedValue(strategy=GenerationType.AUTO)private int id; private String name; private int age; @ElementCollection(fetch=FetchType.LAZY, //加载策略,延迟加载targetClass=String.class) //指定集合中元素的类型 @CollectionTable(name="ADD_INFO") //指定集合生成的表@OrderColumn(name="O_ID") //指定排序列的名称 private List<String> address = new ArrayList<String>(); public int getId() {return id; } public List<String> getAddress() { return address;}public void setAddress(List<String> address) {this.address = address;}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;}}

生成两张表:

emp_info表


add_info表


1.1.2 List<Address> : 集合中元素是复合类型。复合属性类上需要加注解:@Embeddable。

例如:Person类

package edu.scut.e_CollectionMapping_List;import java.util.ArrayList;import java.util.List;import javax.persistence.*;@Entity@Table(name="PER_INFO")public class Person {@Id @GeneratedValue(strategy=GenerationType.AUTO)private int id;  private String name;@ElementCollection(fetch=FetchType.LAZY, //加载策略  targetClass=Address.class) //指定元素中集合的类型@CollectionTable(name="PER_ADD_INFO") //指定集合生成的表 @OrderColumn(name="O_A_ID") //指定排序列的名称 private List<Address> address = new ArrayList<Address>();  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 List<Address> getAddress() {   return address;  } public void setAddress(List<Address> address) {   this.address = address; }}

Address类

package edu.scut.e_CollectionMapping_List;import javax.persistence.Embeddable;@Embeddablepublic class Address {private String zip;private String info;public String getZip() {return zip;}public void setZip(String zip) {this.zip = zip;}public String getInfo() {return info;}public void setInfo(String info) {this.info = info;}}

生成的两张表:

per_info表


per_add_info表


1.2 Set集合映射(无序集合)

注意: Set集合生成表的主键列:(外键列 + Set集合的元素列 .. )

1.2.1· Set<String> : 集合中元素是标量类型 8个基本类型、包装类、String。

           Set集合生成表默认是没有主键列的。如果想要生成主键列,需要为Set集合添加非空约束!

例如:Employee类

package edu.scut.e_CollectionMapping_Set;import java.io.Serializable;import java.util.ArrayList;import java.util.HashSet;import java.util.List;import java.util.Set;import javax.persistence.*;@Entity@Table(name="EMP_INFO")public class Employee implements Serializable { @Id @GeneratedValue(strategy=GenerationType.AUTO)private int id; private String name; private int age;@ElementCollection(fetch=FetchType.LAZY, //加载策略,延迟加载 targetClass=String.class) //指定集合中元素的类型@CollectionTable(name="ADD_INFO") //指定集合生成的表@Column(nullable=false) //添加非空约束 private Set<String> address = new HashSet<String>();public int getId() { return id;} public Set<String> getAddress() { return address; }public void setAddress(Set<String> address) {  this.address = address;  } 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;   }}


1.2.2  Set<Address> : 集合中元素是复合类型。
          复合属性类上需要加注解:@Embeddable
         Set集合生成表默认是没有主键列的。如果想要生成主键列,需要为Set集合的元素类的属性上添加非空约束!

例如:Person类

package edu.scut.e_CollectionMapping_Set;import java.util.ArrayList;import java.util.HashSet;import java.util.List;import java.util.Set;import javax.persistence.*;@Entity@Table(name="PER_INFO")public class Person {@Id @GeneratedValue(strategy=GenerationType.AUTO)private int id;  private String name;  @ElementCollection(fetch=FetchType.LAZY, //加载策略  targetClass=Address.class) //指定元素中集合的类型  @CollectionTable(name="PER_ADD_INFO") //指定集合生成的表  private Set<Address> address = new HashSet<Address>(); 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 Set<Address> getAddress() { return address; }public void setAddress(Set<Address> address) {  this.address = address; }}

Address类

package edu.scut.e_CollectionMapping_Set;import javax.persistence.Column;import javax.persistence.Embeddable;@Embeddablepublic class Address {//@Column(nullable=false)private String zip;@Column(nullable=false)private String info;public String getZip() {return zip;}public void setZip(String zip) {this.zip = zip;}public String getInfo() {return info;}public void setInfo(String info) {this.info = info;}}

1.3 Map集合映射(有Map的key): @MapKeyColumn() 指定Map的key生成的列

注意: Map集合生成表的主键列:(外键列 + Map的Key)

1.3.1 Map<String, String> : 集合中元素是标量类型 8个基本类型、包装类、String。

例如:Employee类

package edu.scut.e_CollectionMapping_Map;import java.io.Serializable;import java.util.ArrayList;import java.util.HashMap;import java.util.HashSet;import java.util.List;import java.util.Map;import java.util.Set;import javax.persistence.*;@Entity@Table(name="EMP_INFO")public class Employee implements Serializable {@Id@GeneratedValue(strategy=GenerationType.AUTO)private int id; private String name;private int age; @ElementCollection(fetch=FetchType.LAZY, //加载策略,延迟加载targetClass=String.class) //指定集合中元素的类型 @CollectionTable(name="ADD_INFO") //指定集合生成的表@MapKeyColumn(name="M_KEY") //指定map的key生成的列 private Map<String, String> address = new HashMap<String, String>(); public int getId() { return id;}public Map<String, String> getAddress() { return address; }public void setAddress(Map<String, String> address) { this.address = address; }  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;}}

1.3.2 Map<String, Address> : 集合中元素是复合类型。
         复合属性类上需要加注解:@Embeddable

例如:Person类

package edu.scut.e_CollectionMapping_Map;import java.util.HashMap;import java.util.HashSet;import java.util.Map;import java.util.Set;import javax.persistence.*;@Entity@Table(name="PER_INFO")public class Person { @Id@GeneratedValue(strategy=GenerationType.AUTO) private int id; private String name;   @ElementCollection(fetch=FetchType.LAZY, //加载策略 targetClass=Address.class) //指定元素中集合的类型  @CollectionTable(name="PER_ADD_INFO") //指定集合生成的表 @MapKeyColumn(name="ADD_KEY") //指定key生成的列private Map<String,Address> address = new HashMap<String,Address>();  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 Map<String,Address> getAddress() {  return address; } public void Address(Map<String,Address> address) {  this.address = address;  }}

Address类

package edu.scut.e_CollectionMapping_Map;import javax.persistence.Column;import javax.persistence.Embeddable;@Embeddablepublic class Address {//@Column(nullable=false)private String zip;@Column(nullable=false)private String info;public String getZip() {return zip;}public void setZip(String zip) {this.zip = zip;}public String getInfo() {return info;}public void setInfo(String info) {this.info = info;}}

二、关联关系映射的注解(重点)

单向关联映射和双向关联映射的最大区别就是在查询数据时,单向关联只能通过一边进行查询,而双向关联两边都可以互相查询。

2.1 单向关联映射(一边配置)

2.1.1 一对一

/** 一方*/@OneToOne(fetch=FetchType.LAZY,cascade=CascadeType.ALL,targetEntity=Persons.class)  //维护关联关系(从表)/** 生成外键列*/@JoinColumn(name="P_ID",unique=true,referencedColumnName="id")

通过公民(Person)和身份证(IdCards)的例子来说明:

Person.java

package edu.scut.f_AssoMap_single_one2one;import javax.persistence.*;//公民(一方)@Entity@Table(name="PER_INFO")public class Persons { @Id @GeneratedValue(strategy=GenerationType.AUTO) 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; }}

IdCards.java

package edu.scut.f_AssoMap_single_one2one;import javax.persistence.*;//身份证(一方)@Entity@Table(name="IDCD_INFO")public class IdCards {@Id@GeneratedValue(strategy=GenerationType.AUTO)@Column(name="IDCD_ID")private int id;private String cardno;/** 一方*/@OneToOne(fetch=FetchType.LAZY,cascade=CascadeType.ALL,targetEntity=Persons.class)  //维护关联关系(从表)/** 生成外键列*/@JoinColumn(name="P_ID",unique=true,referencedColumnName="id")private Persons persons;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getCardno() {return cardno;}public void setCardno(String cardno) {this.cardno = cardno;}public Persons getPersons() {return persons;}public void setPersons(Persons persons) {this.persons = persons;}}

2.1.2 一对多

/** 一方*/ @OneToMany(fetch=FetchType.LAZY, //延迟加载targetEntity=Orders.class, //目标对象 cascade=CascadeType.ALL,//级联操作 orphanRemoval=true)  //孤儿删除 @JoinColumn(name="C_ID",referencedColumnName="CUS_ID")

通过客户(Customers)和订单(Orders)的例子说明:

Customers.java

package edu.scut.f_AssoMap_single_one2n;import java.util.HashSet;import java.util.Set;import javax.persistence.*;//客户(一方)@Entity@Table(name="CUS_INFO")public class Customers {@Id        @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="CUS_ID")private int id; private String name;/** 一方*/ @OneToMany(fetch=FetchType.LAZY, //延迟加载targetEntity=Orders.class, //目标对象 cascade=CascadeType.ALL,//级联操作 orphanRemoval=true)  //孤儿删除 @JoinColumn(name="C_ID",referencedColumnName="CUS_ID")private Set<Orders> orders = new HashSet<Orders>(); 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 Set<Orders> getOrders() { return orders;   }  public void setOrders(Set<Orders> orders) { this.orders = orders;    }}

Orders.java

package edu.scut.f_AssoMap_single_one2n;import javax.persistence.*;;import javax.persistence.Table;//订单(多方)@Entity@Table(name="ORD_INFO")public class Orders { @Id@GeneratedValue(strategy=GenerationType.AUTO)  private int id; private String orderno;  public int getId() { return id;  }  public void setId(int id) { this.id = id;  }   public String getOrderno() {return orderno;   } public void setOrderno(String orderno) {  this.orderno = orderno; }}

2.1.3 多对一

/** 多方*/ @ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL, targetEntity=Customers.class)/** 生成外键列*/@JoinColumn(name="C_ID",referencedColumnName="CUS_ID")

通过客户(Customers)和订单(Orders)的例子说明:

Customers.java

package edu.scut.f_AssoMap_single_n2one;import java.util.HashSet;import java.util.Set;import javax.persistence.*;//客户(一方)@Entity@Table(name="CUS_INFO")public class Customers {@Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="CUS_ID")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;   }}

Orders.java

package edu.scut.f_AssoMap_single_n2one;import javax.persistence.*;//订单(多方)@Entity@Table(name="ORD_INFO")public class Orders {@Id @GeneratedValue(strategy=GenerationType.AUTO)  private int id;  private String orderno;  /** 多方*/ @ManyToOne(fetch=FetchType.LAZY,  cascade=CascadeType.ALL,  targetEntity=Customers.class) /** 生成外键列*/   @JoinColumn(name="C_ID",referencedColumnName="CUS_ID")  private Customers customers; public int getId() {  return id; }  public void setId(int id) {   this.id = id; }   public String getOrderno() {  return orderno;  }  public void setOrderno(String orderno) {this.orderno = orderno;  }public Customers getCustomers() { return customers;  } public void setCustomers(Customers customers) {this.customers = customers;  }}

2.1.4 多对多

/** 多方*/@ManyToMany(fetch=FetchType.LAZY, //延迟加载cascade=CascadeType.ALL,targetEntity=Teacher.class) //目标对象/** 中间表*/@JoinTable(name="TEA_STU", //指定中间表名称joinColumns=@JoinColumn(name="S_ID",referencedColumnName="STU_ID"), //@ManyToMany中没有加mappedby的主键列inverseJoinColumns=@JoinColumn(name="T_ID",referencedColumnName="TEA_ID")) //@ManyToMany中加mappedby的主键列

通过老师(Teachers)和学生(Students)的例子说明:

Teachers.java

package edu.scut.f_AssoMap_single_n2n;import java.util.HashSet;import java.util.Set;import javax.persistence.*;//多方@Entity@Table(name="TEA_INFO")public class Teacher {@Id@GeneratedValue(strategy=GenerationType.AUTO)@Column(name="TEA_ID") private int id; private String name;private String dept; 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 String getDept() { return dept; } public void setDept(String dept) { this.dept = dept; }}

Students.java

package edu.scut.f_AssoMap_single_n2n;import java.util.HashSet;import java.util.Set;import javax.persistence.*;//多方@Entity@Table(name="STU_INFO")public class Student {@Id@GeneratedValue(strategy=GenerationType.AUTO)@Column(name="STU_ID")private int id;private String name;private float score;/** 多方*/@ManyToMany(fetch=FetchType.LAZY, //延迟加载cascade=CascadeType.ALL,targetEntity=Teacher.class) //目标对象/** 中间表*/@JoinTable(name="TEA_STU", //指定中间表名称joinColumns=@JoinColumn(name="S_ID",referencedColumnName="STU_ID"), //@ManyToMany中没有加mappedby的主键列inverseJoinColumns=@JoinColumn(name="T_ID",referencedColumnName="TEA_ID")) //@ManyToMany中加mappedby的主键列private Set<Teacher> teachers = new HashSet<Teacher>();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 float getScore() {return score;}public void setScore(float score) {this.score = score;}public Set<Teacher> getTeachers() {return teachers;}public void setTeachers(Set<Teacher> teachers) {this.teachers = teachers;}}

2.2 双向关联映射(两边同时配置)

2.2.1 一对一

一方:

/** 一方 */@OneToOne(fetch=FetchType.LAZY,targetEntity=IdCards.class,mappedBy="persons",   //不维护关联关系(主表)cascade=CascadeType.ALL) 
另一方:

/** 一方*/@OneToOne(fetch=FetchType.LAZY,targetEntity=Persons.class)  //维护关联关系(从表)/** 生成外键列*/@JoinColumn(name="P_ID",unique=true,referencedColumnName="id")

还是通过公民(Persons)和身份证(IdCards)的例子来说明:

Persons.java

package edu.scut.f_AssoMap_double_one2one;import javax.persistence.*;//公民(一方)@Entity@Table(name="PER_INFO")public class Persons {@Id@GeneratedValue(strategy=GenerationType.AUTO)private int id;private String name;/** 一方 */@OneToOne(fetch=FetchType.LAZY,targetEntity=IdCards.class,mappedBy="persons",   //不维护关联关系(主表)cascade=CascadeType.ALL) private IdCards idcards;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 IdCards getIdcards() {return idcards;}public void setIdcards(IdCards idcards) {this.idcards = idcards;}}
IdCards.java

package edu.scut.f_AssoMap_double_one2one;import javax.persistence.*;//身份证(一方)@Entity@Table(name="IDCD_INFO")public class IdCards {@Id@GeneratedValue(strategy=GenerationType.AUTO)@Column(name="IDCD_ID")private int id;private String cardno;/** 一方*/@OneToOne(fetch=FetchType.LAZY,targetEntity=Persons.class)  //维护关联关系(从表)/** 生成外键列*/@JoinColumn(name="P_ID",unique=true,referencedColumnName="id")private Persons persons;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getCardno() {return cardno;}public void setCardno(String cardno) {this.cardno = cardno;}public Persons getPersons() {return persons;}public void setPersons(Persons persons) {this.persons = persons;}}

2.2.2 一对多

一方:

/** 一方*/@OneToMany(fetch=FetchType.LAZY, //延迟加载targetEntity=Orders.class, //目标对象cascade=CascadeType.ALL,  //级联操作orphanRemoval=true,  //孤儿删除mappedBy="customers") //指定由哪边维护关系(从表维护)

多方:

/** 多方*/@ManyToOne(fetch=FetchType.LAZY,//cascade=CascadeType.ALL,targetEntity=Customers.class)/** 生成外键列*/@JoinColumn(name="C_ID",referencedColumnName="CUS_ID")

还是通过客户(Customers)和订单(Orders)的例子说明:

Customers.java

package edu.scut.f_AssoMap_double_one2n;import java.util.HashSet;import java.util.Set;import javax.persistence.*;//客户(一方)@Entity@Table(name="CUS_INFO")public class Customers {@Id @GeneratedValue(strategy=GenerationType.AUTO)@Column(name="CUS_ID")private int id; private String name; /** 一方*/@OneToMany(fetch=FetchType.LAZY, //延迟加载 targetEntity=Orders.class, //目标对象cascade=CascadeType.ALL,  //级联操作 orphanRemoval=true,  //孤儿删除mappedBy="customers") //指定由哪边维护关系(从表维护)private Set<Orders> orders = new HashSet<Orders>();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 Set<Orders> getOrders() { return orders; }public void setOrders(Set<Orders> orders) {  this.orders = orders; }}

Orders.java

package edu.scut.f_AssoMap_double_one2n;import javax.persistence.*;//订单(多方)@Entity@Table(name="ORD_INFO")public class Orders { @Id@GeneratedValue(strategy=GenerationType.AUTO) private int id; private String orderno; /** 多方*/ @ManyToOne(fetch=FetchType.LAZY,//cascade=CascadeType.ALL, targetEntity=Customers.class)/** 生成外键列*/ @JoinColumn(name="C_ID",referencedColumnName="CUS_ID") private Customers customers;public int getId() { return id; } public void setId(int id) {this.id = id;  } public String getOrderno() {return orderno;  }public void setOrderno(String orderno) { this.orderno = orderno; } public Customers getCustomers() { return customers; } public void setCustomers(Customers customers) {this.customers = customers; }}

2.2.3 多对多

多方:

/** 多方*/@ManyToMany(fetch=FetchType.LAZY, //延迟加载targetEntity=Student.class, //指定目标对象cascade=CascadeType.ALL,mappedBy="teachers") //老师不维护关联关系

另一个多方:

/** 多方*/@ManyToMany(fetch=FetchType.LAZY, //延迟加载targetEntity=Teacher.class) //目标对象/** 中间表*/@JoinTable(name="TEA_STU", //指定中间表名称joinColumns=@JoinColumn(name="S_ID",referencedColumnName="STU_ID"), //@ManyToMany中没有加mappedby的主键列inverseJoinColumns=@JoinColumn(name="T_ID",referencedColumnName="TEA_ID")) //@ManyToMany中加mappedby的主键列

还是通过老师(Teachers)和学生(Students)的例子说明:

Teachers.java

package edu.scut.f_AssoMap_double_n2n;import java.util.HashSet;import java.util.Set;import javax.persistence.*;//多方@Entity@Table(name="TEA_INFO")public class Teacher {@Id@GeneratedValue(strategy=GenerationType.AUTO)@Column(name="TEA_ID")private int id;private String name;private String dept;/** 多方*/@ManyToMany(fetch=FetchType.LAZY, //延迟加载targetEntity=Student.class, //目标对象cascade=CascadeType.ALL,mappedBy="teachers") //老师不维护关联关系private Set<Student> students = new HashSet<Student>();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 String getDept() {return dept;}  public void setDept(String dept) {this.dept = dept; }public Set<Student> getStudents() { return students;} public void setStudents(Set<Student> students) {this.students = students; }}

Students.java

package edu.scut.f_AssoMap_double_n2n;import java.util.HashSet;import java.util.Set;import javax.persistence.*;//多方@Entity@Table(name="STU_INFO")public class Student {@Id@GeneratedValue(strategy=GenerationType.AUTO)@Column(name="STU_ID")private int id;private String name;private float score;/** 多方*/@ManyToMany(fetch=FetchType.LAZY, //延迟加载targetEntity=Teacher.class) //目标对象 /** 中间表*/@JoinTable(name="TEA_STU", //指定中间表名称 joinColumns=@JoinColumn(name="S_ID",referencedColumnName="STU_ID"), //@ManyToMany中没有加mappedby的主键列inverseJoinColumns=@JoinColumn(name="T_ID",referencedColumnName="TEA_ID")) //@ManyToMany中加mappedby的主键列private Set<Teacher> teachers = new HashSet<Teacher>(); 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 float getScore() { return score;} public void setScore(float score) {this.score = score;} public Set<Teacher> getTeachers() {return teachers; }public void setTeachers(Set<Teacher> teachers) { this.teachers = teachers; }}














1 0