注解(Annotation),也叫元數據。一種代碼級別的說明。它是JDK1.5及以后版本引入的一個特性,與類、接口、枚舉是在同一個層次。它可以聲明在包、類、字段、方法、局部變量、方法參數等的前面,用來對這些元素進行說明,注釋。
接下來我們講解一下多對一雙向注解:
我以部門表和員工表作為示例講解。
第一步:創建實體類
Dept(部門表)
package cn.onetomanydouble.entity; import org.hibernate.annotations.*; import org.hibernate.annotations.Cache; import javax.persistence.*; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.Table; import java.io.Serializable; import java.util.HashSet; import java.util.Set; /** * Created by accp on 2017/2/8. */ @Entity @Table(name = "DEPT1") public class Dept implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO,generator="PROMOTION_SEQ") @SequenceGenerator(name="PROMOTION_SEQ",sequenceName="PROMOTION_SEQ",initialValue = 1,allocationSize = 10) /* 對於oracle想使用各自的Sequence,設置如下: @GeneratedValue(strategy = GenerationType.AUTO,generator="PROMOTION_SEQ") @SequenceGenerator(name="PROMOTION_SEQ",sequenceName="PROMOTION_SEQ") 另外: 對於自動增長后,在數據表中的相應字段,要設置字段為auto_increment. */ private Integer deptno; @Column private String deptname; @OneToMany(mappedBy ="dept",cascade = {CascadeType.ALL},fetch = FetchType.LAZY) //mappedBy 屬性主要針對外鍵而言,與之對應的是.xml中的inverse屬性 //mappedBy="dept" 是把維護權交給多的一方 @LazyCollection(LazyCollectionOption.FALSE) private Set<Emp> emps=new HashSet<Emp>(); @Column private String location; public String getLocation() { return location; } public void setLocation(String location) { this.location = location; } public Integer getDeptno() { return deptno; } public void setDeptno(Integer deptno) { this.deptno = deptno; } public String getDeptname() { return deptname; } public void setDeptname(String deptname) { this.deptname = deptname; } public Set<Emp> getEmps() { return emps; } public void setEmps(Set<Emp> emps) { this.emps = emps; } }
Emp(員工表)
package cn.onetomanydouble.entity; import org.hibernate.annotations.*; import org.hibernate.annotations.Cache; import javax.persistence.*; import javax.persistence.Entity; import javax.persistence.Table; import java.io.Serializable; /** * Created by accp on 2017/2/8. */ @Entity @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) @Table(name = "EMP1") public class Emp implements Serializable { @Id @GeneratedValue private Integer empno; @Column private String ename; @ManyToOne @JoinColumn(name = "deptno") private Dept dept; /* @Column private Double salary; @Column private String job;*/ /*public Double getSalary() { return salary; } public void setSalary(Double salary) { this.salary = salary; } public String getJob() { return job; } public void setJob(String job) { this.job = job; }*/ public Integer getEmpno() { return empno; } public void setEmpno(Integer empno) { this.empno = empno; } public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } public Dept getDept() { return dept; } public void setDept(Dept dept) { this.dept = dept; } }
在配置一對多雙向的時候一定要搞清楚主外鍵關系。
第二步:在hibernate.cfg.xml文件中配置<mapping>節點
<mapping class="cn.onetomanydouble.entity.Dept"/> <mapping class="cn.onetomanydouble.entity.Emp"/>
第三步:書寫測試類
package cn.onetomanydouble.test; import cn.onetomanydouble.entity.Dept; import cn.onetomanydouble.entity.Emp; import org.hibernate.Hibernate; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.junit.After; import org.junit.Before; import org.junit.Test; /** * Created by accp on 2017/2/8. */ public class ManyToOneTest { Configuration cfg; Session session; Transaction tx; SessionFactory factory; @Before public void mybefore(){ cfg=new Configuration().configure(); factory=cfg.buildSessionFactory(); session=factory.openSession(); tx=session.beginTransaction(); } @After public void myafter(){ tx.commit(); session.close(); } @Test public void demo(){ System.out.println(123); } @Test public void select(){ /** * load()方法 * fetch = FetchType.EAGER(立即加載) fetch = FetchType.LAZY(懶加載) * 情況一:當在一的一方設置是否加載時 * fetch = FetchType.EAGER (立即加載) * 不查詢不發送sql語句 * 左外連接 兩表查詢 * 查詢關聯表的屬性時 不在重新發送sql * * * fetch = FetchType.LAZY(懶加載) * 不查詢不發送sql語句 * 查詢單一屬性時 只查詢當前表的 當查詢關聯屬性時 * 重新向數據庫發送sql * * get()方法 * fetch = FetchType.EAGER (立即加載) fetch = FetchType.LAZY(懶加載) * (1) 情況一:當在多的一方設置 * fetch = FetchType.EAGER (立即加載) * 先向數據庫查詢一次 * 左外連接 兩表查詢 * 當用到屬性時 直接打印對應的屬性值 * * fetch = FetchType.LAZY(懶加載) * 只加載當前類的語句 * 當查詢當前表的屬性時 只向數據庫發送查詢當前表的sql * * 當查詢關聯表的屬性時 發送關聯表的sql語句 * */ /*Transaction tx = factory.getCurrentSession().beginTransaction(); Dept dept = factory.getCurrentSession().get(Dept.class, 1); for (Emp emp:dept.getEmps()) { System.out.println(emp.getEname()); } tx.commit(); factory.getCurrentSession().close(); System.out.println("====================="); Transaction tx2 = factory.getCurrentSession().beginTransaction(); Dept dept2 = factory.getCurrentSession().get(Dept.class, 1); for (Emp emp:dept2.getEmps()) { System.out.println(emp.getEname()); } tx2.commit(); */ Dept dept = session.get(Dept.class, 1); System.out.println("============="); System.out.println(dept.getClass()); System.out.println(dept.getDeptname()); System.out.println(dept.getEmps().iterator().next().getEname()); /* Emp emp = session.get(Emp.class, 2); System.out.println("===========");*/ /* System.out.println(emp.getEname()); System.out.println(emp.getDept().getDeptname());*/ } @Test public void add(){ /*//創建部門 Dept dept=new Dept(); dept.setDeptname("產品部"); //創建員工 Emp emp=new Emp(); emp.setEname("劉二雄"); emp.setDept(dept); dept.getEmps().add(emp); //因為cascade級聯只需保存部門即可保存員工 session.save(dept);*/ Dept dept=new Dept(); dept.setDeptname("清潔部"); //創建員工 Emp emp=new Emp(); emp.setEname("飄哥"); emp.setDept(dept); dept.getEmps().add(emp); session.save(dept); } }
執行完代碼后一定要看看生成的sql語句,加深印象。