1. 程式人生 > >劍指架構師系列-Hibernate需要掌握的Annotation

劍指架構師系列-Hibernate需要掌握的Annotation

www. 管理表 con _id 冗余 並且 mina name app

1、一對多的關系配置

@Entity
@Table(name = "t_order")
public class Order {
	@Id
	@GeneratedValue 
	private int id;

	private String name;
	
    /*
     * 該屬性定義類和類之間的級聯關系。定義的級聯關系將被容器視為對當前類對象及其關聯類對象采取相同的操作,
     * 而且這種關系是遞歸調用的。舉個例子:Order 和OrderItem有級聯關系,那麽刪除Order時將同時刪除它所對
     * 應的OrderItem對象。而如果OrderItem還和其他的對象之間有級聯關系,那麽這樣的操作會一直遞歸執行下去。
     * 
     * CascadeType.PERSIST(級聯新建)  貌似只能在關聯對象單獨保存後才可以
     * CascadeType.REMOVE(級聯刪除) 有級聯的效果
     * CascadeType.REFRESH(級聯刷新)
     * CascadeType.MERGE(級聯更新)
     * CascadeType.ALL(選擇全部四項)
     * 
     * 級聯的意思是允許你進行某個級聯操作,例如是級聯刪除時,進行級聯新建是不允許的
     * 
     * mappedBy 屬性值是多方中定義的一方的變量名,形成雙向關系時需要定義
     */
	@OneToMany(
			cascade ={ CascadeType.ALL},   
			fetch = FetchType.EAGER,        
			mappedBy = "order",             
			targetEntity = OrderItem.class  
	)
	private Set<OrderItem> orderItems = new HashSet<OrderItem>();

	// 省略
}

// 通過@Entity註解將一個類聲明為一個實體bean
// 通過 @Table註解可以為實體bean映射指定表,name屬性表示實體所對應表的名稱,如果沒有
// 定義 @Table,那麽系統自動使用默認值:實體的類名(不帶包名)
@Entity
@Table(name = "t_orderitem")
public class OrderItem implements java.io.Serializable {
	private static final long serialVersionUID = 1L;

	// 用於標記屬性的主鍵
    // @Id
    // 表示持久化屬性所映射表中的字段,如果屬性名與表中的字段名相同,則可以省略@Column註解,
    // 另外有兩種方式標記,一是放在屬性前,另一種是放在getter方法前
    // @Column(name = "EMPLOYEE_ID")
    
    /*
     * 表生成器。將當前主鍵的值單獨保存到一個數據庫表中,主鍵的值每次都是從指定的表中查詢來獲得,
     * 這種生成主鍵的方式是很常用的。這種方法生成主鍵的策略可以適用於任何數據庫,不必擔心不同數
     * 據庫不兼容造成的問題。推薦這種方式管理主鍵,很方便,集中式管理表的主鍵,而且更換數據
     * 庫不會造成很大的問題。
     */
	/*
     @TableGenerator(
         name="tab-store",        // 該表主鍵生成策略的名稱,可以自定義,它被引用在@GeneratedValue中設置的"generator"值中
         table="GENERATOR_TABLE", // 表生成策略所持久化的表名,就是管理其它表主鍵的表
         pkColumnName = "G_KEY",  // 表生成器中的列名,用來存放其它表的主鍵鍵名,這個列名是與表中的字段對應的
         pkColumnValue="EMPLOYEE_PK",  // 實體表所對應到生成器表中的主鍵名,可以自定義
         // 表生成器中的列名,實體表主鍵的下一個值,假設EMPLOYEE表中的EMPLOYEE_ID最大為2,那麽此時,生成器表中與實體表主鍵對應的鍵名值則為3
         valueColumnName = "G_VALUE",
         allocationSize=1         // 表示每次主鍵值增加的大小,例如設置成1,則表示每次創建新記錄後自動加1,默認為50
     )
    */
    /*
     * 定義主鍵生成策略,這裏因為使用的是TableGenerator,所以,主鍵的生成策略為GenerationType.TABLE,
     * 生成主鍵策略的名稱則為前面定義的”tab-store”。
     * 
     * strategy = GenerationType.AUTO或是strategy = GenerationType.SEQUENCE,采用SEQUENCE序列是因為Oracle數據中不支持identity自動增長,
     * 要想使用它,還得在數據庫中創建一個序列。
     * 
     * 采用的是SQL Server作為數據庫時,如果想使用AUTO或是IDENTITY生成策略,則一定要對主鍵加上identity標識,如identity(1,1)。
     * 不過對於AUTO來說,是根據不同的數據庫選擇最合適的自增主鍵生成策略。如果使用MySQL,則主鍵要定義AUTO_INCREMENT。
     * 如果是Oracle,則要創建Sequence來實現自增。
     * 
     * */
    
	@Id
//	@Column(name = "id")
//	@TableGenerator(name = "tab-store", table = "GENERATOR_TABLE", pkColumnName = "G_KEY", pkColumnValue = "ORDERITEM_PK", valueColumnName = "G_VALUE", allocationSize = 1)
//	@GeneratedValue(strategy = GenerationType.TABLE, generator = "tab-store")
	@GeneratedValue
	private Integer id; 

	private String name; 

	/*
	   optional屬性是定義該關聯類是否必須存在,值為false時,關聯類雙方都必須存在,如果關系被維護端不存在,
	        查詢的結果為null。值為true時,關系被維護端可以不存在,查詢的結果仍然會返回關系維護端,在關系維護端
	         中指向關系被維護端的屬性為null。optional屬性的默認值是true。
	   optional屬性實際上指定關聯類與被關聯 類的join查詢關系,如optional=false時join查詢關系為inner join, 
	   optional=true 時join 查詢關系為left join。
	 */
	
	@ManyToOne(
			cascade ={ CascadeType.ALL},
			optional = false,     
			fetch=FetchType.LAZY,  
			targetEntity=Order.class
	)
	@JoinColumn(name = "order_id")// 在關系被維護端需要建立外鍵列指向關系維護端的主鍵列
	private Order order;          // ManyToOne表示多個Employee對應與一個Department,dept_id字段加入Employee表中

	
	// 省略
	
}

  

2、多對多的關系配置

@Entity
@Table(name = "Teacher")
public class Teacher implements java.io.Serializable {
	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue
	private Integer id;

	@Column(name = "name", length = 100) // 對應數據庫中表的列,最大長度是100
	private String name;
	
	// @ManyToMany註釋表示Teacher是多對多關系的一端。
	/*
	 * @JoinTable描述了多對多關系的數據表關系。
	 * name屬性指定中間表名稱, joinColumns定義中間表與Teacher表的外鍵關系。
	 * inverseJoinColumns屬性定義了中間表與另外一端(Student)的外鍵關系。
	 */
    @JoinTable(
    		name="teacher_student",
    		joinColumns = {@JoinColumn(name="teacher_id")},
    		inverseJoinColumns={@JoinColumn(name="student_id")}
    )
	@ManyToMany(
			cascade = CascadeType.ALL, 
			fetch = FetchType.LAZY
	)
	private Set<Student> students = new HashSet<Student>();
        // 省略
}

  

@Entity
@Table(name = "Student")
public class Student implements Serializable {
	private static final long serialVersionUID = 1L;
	@Id
	@GeneratedValue	
	private Integer id;
	
	@Column(name = "name")
	private String name;
	
	@Column(name = "age")
	private Integer age;
	
	// @ManyToMany註釋表示Student是多對多關系的一邊,mappedBy屬性定義了Student為雙向關系的維護端
	// 有且僅有一個實體指定mappedBy屬性
	// 這個teachers屬性會在數據庫中生成對應的teachers_id字段
	@ManyToMany(
			cascade = CascadeType.ALL, 
			mappedBy = "students"
	) 
	private Set<Teacher> teachers = new HashSet<Teacher>();
	
	// 省略
}

  

3、Hibernate中繼承關系的使用

Hibernate的繼承映射包含了三種不同的策略:

  1. 每簇類使用一個表
  2. 每個子類一個表
  3. 每個具體內一個表(有限制)

JPA同樣支持3種類型的繼承形式:


1.Single Table Strategy ,單表策略,一張表包含基類與子類的所有數據,很多情況下都是采用這樣的冗余設計,通過一個discriminator來區分
2.Table Per Class Strategy ,每個子類對應一張表,每張表都擁有基類的屬性
3.Join Strategy ,仍然是每個子類對應一張表,但此表中不包含基類的屬性,僅僅是此子類的擴展屬性,共享基類的屬性

(1)單表策略

// 采用單表策略,通過@DiscriminatorColumn確定了標誌值的字段和類型
// @DiscriminatorValue註釋,當Animal類型的Entity存入數據庫時,JPA將自動把animal的值賦給animalType字段
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="animalType")
@DiscriminatorValue("animal")
public class Animal {
	private int id;
	private String name;
	
	@Id
	@GeneratedValue
	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;
	}
}

@Entity
@DiscriminatorValue("cat")
public class Cat extends Animal {

	private String catName;
        // 省略
}

@Entity
@DiscriminatorValue(value="dog")
public class Dog extends Animal{
	private String dogName;

	 // 省略
}

 

技術分享

(2)Table per Class

采用Table Per Class策略的話,每個子類都將單獨建表,並且都獨立擁有基類中的所有屬性,互相之間不共享

 

@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class Animal {
	private int id;
	private String name;
	
	@Id
	@GeneratedValue(strategy=GenerationType.TABLE)
	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;
	}
}

@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class Cat extends Animal {

	private String catName;

	public String getCatName() {
		return catName;
	}
	public void setCatName(String catName) {
		this.catName = catName;
	}
}

@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class Dog extends Animal{
	private String dogName;

	public String getDogName() {
		return dogName;
	}
	public void setDogName(String dogName) {
		this.dogName = dogName;
	}
}

技術分享  

(3)Join策略

每個子類同樣獨立建表,基類也獨立建表,只不過所有的子類的表中只有擴展屬性,他們共享基類的表

@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public class Animal {
	private int id;
	private String name;
	
	@Id
	@GeneratedValue
	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;
	}
}

@Entity
@PrimaryKeyJoinColumn(name="catId")
public class Cat extends Animal {

	private String catName;

	public String getCatName() {
		return catName;
	}
	public void setCatName(String catName) {
		this.catName = catName;
	}
}

@Entity
@PrimaryKeyJoinColumn(name="dogId")
public class Dog extends Animal{
	private String dogName;

	public String getDogName() {
		return dogName;
	}
	public void setDogName(String dogName) {
		this.dogName = dogName;
	}
}

  

技術分享

參考文章:

 1、http://www.360doc.com/content/11/0906/22/1542811_146326974.shtml 

劍指架構師系列-Hibernate需要掌握的Annotation