*****************關於註解的簡單介紹html
詳細介紹請點擊這裏註解詳細教程java
package com.tomowork.pojo; import org.hibernate.annotations.GenericGenerator; import javax.annotation.Generated; import javax.persistence.*; import java.io.Serializable; @Entity() //代表這個類是一個實體類,在數據庫中存在對應的字段 @Table(name="emp",schema = "test") //在數據庫中對應的表 public class Emp implements Serializable { private Integer empno ; private String ename ; @Id /** * 可選的主鍵的生成策略 * 可選的值: TABLE, SEQUENCE, //主要用於Oracle數據庫 IDENTITY, AUTO; //根據數據庫定義主鍵生成策略,myql底層是自動增加主列 @GeneratedValue(strategy = GenerationType.AUTO) */ /** * 若是主鍵是指派的,就不能用jpa註解 */ @GeneratedValue(generator = "deptno") //定義一個主鍵生成策略 @GenericGenerator(name = "deptno",strategy = "assigned") public Integer getEmpno() { return empno; } public void setEmpno(Integer empno) { this.empno = empno; } @Column(name = "ename") public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } }
****************註解開發單向一對一mysql
編寫數據庫腳本:linux
假如一個學生只有一部手機,一個手機只屬於一個學生;sql
CREATE TABLE `phone` ( `tel` varchar(255) NOT NULL DEFAULT '' COMMENT '手機號碼', `pname` varchar(255) NOT NULL COMMENT '手機名字', `price` double NOT NULL COMMENT '手機價格', `sid` int(11) NOT NULL COMMENT '手機的主人', PRIMARY KEY (`tel`), KEY `fk_sid` (`sid`), CONSTRAINT `fk_sid` FOREIGN KEY (`sid`) REFERENCES `students` (`sid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `students` ( `sid` int(11) NOT NULL DEFAULT '0', `sname` varchar(255) DEFAULT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`sid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
編寫實體類:數據庫
Students.java後端
package com.itcloud.pojo; import org.hibernate.annotations.GenericGenerator; import javax.persistence.*; @Entity //代表這是一個數據庫實體 @Table(name="Students") public class Students { //統一代碼規範將註解設置在get方法上面而不是設置在屬性上面 private Integer sid ; private String sname ; private Integer age ; //無參構造 public Students(){} //全參構造 public Students(Integer sid, String sname, Integer age) { this.sid = sid; this.sname = sname; this.age = age; } @Id //表示這是一個主鍵列 //定義主鍵的生成策略,assigned表示是本身指派的 @GeneratedValue(generator = "sid") @GenericGenerator(name="sid",strategy = "assigned") public Integer getSid() { return sid; } public void setSid(Integer sid) { this.sid = sid; } /** *Basic,定義屬性的存取獲取策略 *Basic(FetchType.EAGER):默認,表示即時存取 *Basic(FetchType.LAZY):延遲加載 */ @Basic //這裏設置默認就能夠了 @Column(length =13,name="sname" ) public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } @Basic @Column(name = "age") public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
Phone.javasession
package com.itcloud.pojo; import org.hibernate.annotations.GenericGenerator; import javax.persistence.*; @Entity @Table(name="phone",schema = "test") public class Phone { private String tel ; private String pname ; private Double price ; private Students students ; public Phone() { } public Phone(String tel, String pname, Double price, Students students) { this.tel = tel; this.pname = pname; this.price = price; this.students = students; } @Id @GeneratedValue(generator = "tel") @GenericGenerator(name = "tel",strategy="assigned") //本身指派主鍵生成策略 public String getTel() { return tel; } public void setTel(String tel) { this.tel = tel; } @Basic @Column(name="pname") public String getPname() { return pname; } public void setPname(String pname) { this.pname = pname; } @Basic @Column(name="price") public Double getPrice() { return price; } public void setPrice(Double price) { this.price = price; } /** *進行單項一對一的關聯映射 */ @OneToOne(cascade = CascadeType.ALL) //所有級聯CRUD操做 @JoinColumn(name="sid",unique = true) //name指的是主表的外鍵,unique表示是不是惟一的 public Students getStudents() { return students; } public void setStudents(Students students) { this.students = students; } }
測試用例:mybatis
package com.itcloud.test; import com.itcloud.pojo.Phone; import com.itcloud.pojo.Students; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.junit.After; import org.junit.Test; public class TestHibernate { public static SessionFactory sessionFactory =null ; public static Session session = null ; public static Transaction transaction ; static { Configuration configuration = new Configuration().configure() ; sessionFactory = configuration.buildSessionFactory() ; session = sessionFactory.openSession() ; transaction = session.beginTransaction() ; } @Test public void post(){ //建立學生實體 Students stus = new Students(201401,"張三",10) ; Phone phone = new Phone("13588578866","iphone",888.36,stus) ; session.save(stus) ; session.save(phone) ; } @After public void destroy(){ transaction.commit(); session.close(); sessionFactory.close(); } }
測試結果:app
Hibernate: insert into Students (age, sname, sid) values (?, ?, ?) Hibernate: 十二月 02, 2017 12:19:41 上午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop insert into phoneINFO: HHH10001008: Cleaning up connection pool [jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8] (pname, price, sid, tel) values (?, ?, ?, ?)
***********註解開發一對一雙向
數據庫表結構
CREATE TABLE `students` (
`sid` int(11) NOT NULL,
`sname` varchar(15) NOT NULL DEFAULT '',
`age` int(11) NOT NULL DEFAULT '0',
`tel` varchar(18) NOT NULL DEFAULT '' COMMENT '一個學生有一部手機',
PRIMARY KEY (`sid`),
KEY `fk_tel` (`tel`),
CONSTRAINT `fk_tel` FOREIGN KEY (`tel`) REFERENCES `phone` (`tel`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `phone` (
`tel` varchar(18) NOT NULL,
`pname` varchar(20) NOT NULL DEFAULT '' COMMENT '手機名字',
`price` double NOT NULL DEFAULT '0' COMMENT '手機價格',
PRIMARY KEY (`tel`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
假如一個學生擁有一個手機,一個手機屬於一個學生,學生爲主控方
實體類的編寫
Students
package com.itcloud.pojo; import org.hibernate.annotations.GenericGenerator; import javax.persistence.*; import java.io.Serializable; @Entity //代表這是一個數據庫實體 @Table(name="students") public class Students implements Serializable { //統一代碼規範將註解設置在get方法上面而不是設置在屬性上面 private Integer sid ; private String sname ; private Integer age ; private Phone phone ;//一個學生擁有一個手機 //無參構造 public Students(){} //全參構造 public Students(Integer sid, String sname, Integer age) { this.sid = sid; this.sname = sname; this.age = age; } @Id //表示這是一個主鍵列 //定義主鍵的生成策略,assigned表示是本身指派的 @GeneratedValue(generator = "sid") @GenericGenerator(name="sid",strategy = "assigned") public Integer getSid() { return sid; } public void setSid(Integer sid) { this.sid = sid; } /** *Basic,定義屬性的存取獲取策略 *Basic(FetchType.EAGER):默認,表示即時存取 *Basic(FetchType.LAZY):延遲加載 */ @Basic //這裏設置默認就能夠了 @Column(name="sname" ) public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } @Basic @Column(name = "age") public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @OneToOne(cascade = CascadeType.ALL,fetch = FetchType.LAZY) @JoinColumn(name="tel",unique = true) //name指的是主表的外鍵,數據庫中的外鍵,unique表示是不是惟一的 public Phone getPhone() { return phone; } public void setPhone(Phone phone) { this.phone = phone; } }
Phones.java
1 package com.itcloud.pojo; 2 3 import org.hibernate.annotations.GenericGenerator; 4 5 import javax.persistence.*; 6 import java.io.Serializable; 7 8 @Entity 9 @Table(name="phone",schema = "test") 10 public class Phone implements Serializable { 11 private String tel ; 12 private String pname ; 13 private Double price ; 14 15 private Students students ; //一個手機屬於一個學生 16 17 public Phone() { 18 } 19 20 public Phone(String tel, String pname, Double price) { 21 this.tel = tel; 22 this.pname = pname; 23 this.price = price; 24 } 25 26 @Id 27 @GeneratedValue(generator = "tel") 28 @GenericGenerator(name = "tel",strategy="assigned") //本身指派主鍵生成策略 29 public String getTel() { 30 return tel; 31 } 32 33 public void setTel(String tel) { 34 this.tel = tel; 35 } 36 @Basic 37 @Column(name="pname") 38 public String getPname() { 39 return pname; 40 } 41 42 public void setPname(String pname) { 43 this.pname = pname; 44 } 45 @Basic 46 @Column(name="price") 47 public Double getPrice() { 48 return price; 49 } 50 51 public void setPrice(Double price) { 52 this.price = price; 53 } 54 55 @OneToOne(mappedBy = "phone",fetch = FetchType.LAZY) //主表類中的從表實例 56 public Students getStudents() { 57 return students; 58 } 59 60 public void setStudents(Students students) { 61 this.students = students; 62 } 63 }
測試用例:
@Test public void post(){ //建立學生實體 Phone phone = new Phone("13588578867","iphone",888.36) ; Students stus = new Students(201402,"李四",10) ; stus.setPhone(phone); phone.setStudents(stus); session.save(phone) ; //必定要保存手機,再保存學生 session.save(stus) ; }
雙向一對一總結:
首先表設計:主表:students,存在有phone的外鍵
從表:沒有外鍵,數據交給students管理;
實體類的設計:主表:
@OneToOne(cascade = CascadeType.ALL,fetch = FetchType.LAZY) @JoinColumn(name="tel",unique = true) //name指的是主表的外鍵,數據庫中的外鍵,unique表示是不是惟一的
從表:
@OneToOne(mappedBy = "phone",fetch = FetchType.LAZY) //phone爲主表類中的從表實例即:private Phone phone ;中的phone
***********單方多對一關聯關係:
假設一個部門擁有多個僱員,一個僱員屬於一個部門,典型的多對一關聯
首先表設計:
CREATE TABLE `dept` ( `deptno` int(11) NOT NULL DEFAULT '0', `dname` varchar(255) DEFAULT '', `loc` varchar(255) DEFAULT '', PRIMARY KEY (`deptno`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `emp` ( `empno` int(11) NOT NULL, `ename` varchar(15) NOT NULL DEFAULT '' COMMENT '僱員姓名', `job` varchar(25) NOT NULL DEFAULT '' COMMENT '僱員職位', `deptno` int(11) NOT NULL DEFAULT '-1' COMMENT '所屬部門,-1表示沒有部門', PRIMARY KEY (`empno`), KEY `fk_deptno` (`deptno`), CONSTRAINT `fk_deptno` FOREIGN KEY (`deptno`) REFERENCES `dept` (`deptno`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
實體類的編寫
Dept.java(多方)
package com.itcloud.pojo; import javax.persistence.Basic; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; @Entity /** * @author:itcloud * */ public class Dept { private Integer deptno; private String dname; private String loc; public Dept() { } public Dept(Integer deptno, String dname, String loc) { this.deptno = deptno; this.dname = dname; this.loc = loc; } @Id @Column(name = "deptno") public int getDeptno() { return deptno; } public void setDeptno(int deptno) { this.deptno = deptno; } @Basic @Column(name = "dname") public String getDname() { return dname; } public void setDname(String dname) { this.dname = dname; } @Basic @Column(name = "loc") public String getLoc() { return loc; } public void setLoc(String loc) { this.loc = loc; } @Override public boolean equals(Object o) { if (this == o) {return true;} if (o == null || getClass() != o.getClass()){ return false;} Dept dept = (Dept) o; if (deptno != dept.deptno) {return false;} if (dname != null ? !dname.equals(dept.dname) : dept.dname != null) {return false;} if (loc != null ? !loc.equals(dept.loc) : dept.loc != null) {return false;} return true; } @Override public int hashCode() { int result = deptno; result = 31 * result + (dname != null ? dname.hashCode() : 0); result = 31 * result + (loc != null ? loc.hashCode() : 0); return result; } @Override public String toString() { return "Dept{" + "deptno=" + deptno + ", dname='" + dname + '\'' + ", loc='" + loc + '\'' + '}'; } }
Emp.java(一方)
package com.itcloud.pojo; import org.hibernate.annotations.GenericGenerator; import javax.persistence.*; @Entity @Table(name = "emp",schema = "test") public class Emp { private Integer empno ; private String ename ; private String job ; private Dept dept ; public Emp() { } public Emp(Integer empno, String ename, String job, Dept dept) { this.empno = empno; this.ename = ename; this.job = job; this.dept = dept; } /** * emp是多方,dept是一方 * */ @ManyToOne(cascade = CascadeType.ALL,fetch = FetchType.EAGER) //抓取策略是積極的 @JoinColumn(name = "deptno")//deptno是外鍵 public Dept getDept() { return dept; } public void setDept(Dept dept) { this.dept = dept; } @Id @GeneratedValue(generator = "empno") @GenericGenerator(name="empno",strategy = "assigned") public Integer getEmpno() { return empno; } public void setEmpno(Integer empno) { this.empno = empno; } @Column(name="ename") public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } @Column(name="job") public String getJob() { return job; } public void setJob(String job) { this.job = job; } }
測試用例:
@Test public void post(){ //多對一測試 Dept dept = new Dept(11,"運維部門","402"); Emp emp = new Emp(7371,"clom","linux運維",dept) ; session.save(dept) ; session.save(emp) ; }
測試結果:
Hibernate: insert into Dept (dname, loc, deptno) values (?, ?, ?) Hibernate: insert into emp (deptno, ename, job, empno) values (?, ?, ?, ?)
多對一在多方(即Emp.java)上面添加以下註解
...
/** * emp是多方,dept是一方 * */ @ManyToOne(cascade = CascadeType.ALL,fetch = FetchType.EAGER) //抓取策略是積極的 @JoinColumn(name = "deptno")//deptno是外鍵 public Dept getDept() { return dept; }
...
***********一對多單向外鍵關聯
一方持有多方的集合 :一個部門存在多個僱員,可是僱員不是重複的,在Dept.java中添加:private Set<Emp> allEmps = new HashSet<>() ;
數據表:仍是dept,emp這兩個表
編寫實體類
Dept.java
package com.itcloud.pojo; import org.hibernate.annotations.GenericGenerator; import javax.persistence.*; import java.util.HashSet; import java.util.Set; @Entity @Table(name = "dept") public class Dept { private Integer deptno ; private String dname ; private String loc ; private Set<Emp> emps = new HashSet<>() ; @Id @GeneratedValue(generator = "dno") @GenericGenerator(name="dno",strategy = "assigned") public Integer getDeptno() { return deptno; } public void setDeptno(Integer deptno) { this.deptno = deptno; } public String getDname() { return dname; } public void setDname(String dname) { this.dname = dname; } public String getLoc() { return loc; } public void setLoc(String loc) { this.loc = loc; } @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY) @JoinColumn(name = "deptno",updatable = false) public Set<Emp> getEmps() { return emps; } public void setEmps(Set<Emp> emps) { this.emps = emps; } }
Emp.java
package com.itcloud.pojo; import org.hibernate.annotations.GenericGenerator; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="emp") public class Emp { private Integer empno ; private String ename ; private String job ; public Emp() { } public Emp(Integer empno, String ename, String job) { this.empno = empno; this.ename = ename; this.job = job; } @Id @GeneratedValue(generator = "eno") @GenericGenerator(name = "eno",strategy = "assigned") 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 String getJob() { return job; } public void setJob(String job) { this.job = job; } }
測試用例:
@Test public void post(){ Dept dept = new Dept() ; dept.setDeptno(11); dept.setDname("開發部門"); dept.setLoc("403"); Emp emp1 = new Emp(7777,"smith","java開發") ; Emp emp2 = new Emp(7778,"jack","後端開發") ; dept.getEmps().add(emp1) ; dept.getEmps().add(emp2) ; session.save(emp1) ; session.save(emp2) ; session.save(dept) ; }
***********1-N(N-1)雙向外鍵關聯
package com.itcloud.pojo; import javax.persistence.*; import java.util.HashSet; import java.util.Set; @Entity public class Dept { private int deptno; private String dname; private String loc; private Set<Emp> emps = new HashSet<>(); @Id @Column(name = "deptno", nullable = false) public int getDeptno() { return deptno; } public void setDeptno(int deptno) { this.deptno = deptno; } @Basic @Column(name = "dname", nullable = true, length = 255) public String getDname() { return dname; } public void setDname(String dname) { this.dname = dname; } @Basic @Column(name = "loc", nullable = true, length = 255) public String getLoc() { return loc; } public void setLoc(String loc) { this.loc = loc; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Dept dept = (Dept) o; if (deptno != dept.deptno) return false; if (dname != null ? !dname.equals(dept.dname) : dept.dname != null) return false; if (loc != null ? !loc.equals(dept.loc) : dept.loc != null) return false; return true; } @Override public int hashCode() { int result = deptno; result = 31 * result + (dname != null ? dname.hashCode() : 0); result = 31 * result + (loc != null ? loc.hashCode() : 0); return result; } @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY) @JoinColumn(name="deptno") public Set<Emp> getEmps() { return emps; } public void setEmps(Set<Emp> emps) { this.emps = emps; } }
package com.itcloud.pojo; import javax.persistence.*; @Entity public class Emp { private int empno; private String ename; private String job; private Dept dept; public Emp(int empno, String ename, String job) { this.empno = empno; this.ename = ename; this.job = job; } @Id @Column(name = "empno", nullable = false) public int getEmpno() { return empno; } public void setEmpno(int empno) { this.empno = empno; } @Basic @Column(name = "ename", nullable = true, length = 255) public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } @Basic @Column(name = "job", nullable = true, length = 255) public String getJob() { return job; } public void setJob(String job) { this.job = job; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Emp emp = (Emp) o; if (empno != emp.empno) return false; if (ename != null ? !ename.equals(emp.ename) : emp.ename != null) return false; if (job != null ? !job.equals(emp.job) : emp.job != null) return false; return true; } @Override public int hashCode() { int result = empno; result = 31 * result + (ename != null ? ename.hashCode() : 0); result = 31 * result + (job != null ? job.hashCode() : 0); return result; } @ManyToOne(cascade = CascadeType.ALL,fetch = FetchType.EAGER) @JoinColumn(name = "deptno", referencedColumnName = "deptno") public Dept getDept() { return dept; } public void setDept(Dept dept) { this.dept = dept; } }
注意點:
1.不管是在多方仍是在一方,都要加上:@JoinColumn(name="deptno")這一語句,若是不加則沒法級聯,deptno爲多方的外鍵,
2.不要加mappedBy這一屬性,由於加上這一屬性只能夠從多方進行級聯,而一方沒法進行級聯,就須要設置①,②兩個字段
測試:
@Test
public void post(){
Dept dept = new Dept() ;
dept.setDeptno(11);
dept.setDname("開發部門");
dept.setLoc("313");
Emp emp1 = new Emp(7777,"smith","java開發") ;
Emp emp2 = new Emp(7778,"jack","後端開發") ;
dept.getEmps().add(emp1) ;
dept.getEmps().add(emp2) ;
// emp1.setDept(dept);//②
// emp2.setDept(dept);//①
session.save(emp1) ;
session.save(emp2) ;
session.save(dept) ;
}
結果
Hibernate: insert into Emp (deptno, ename, job, empno) values (?, ?, ?, ?) Hibernate: insert into Emp (deptno, ename, job, empno) values (?, ?, ?, ?) Hibernate: insert into Dept (dname, loc, deptno) values (?, ?, ?) Hibernate: update Emp set deptno=? where empno=? Hibernate: update Emp set deptno=? where empno=?
************多對多外鍵關聯
表結構:
CREATE TABLE `teachers` ( `tid` int(11) NOT NULL, `tname` varchar(255) NOT NULL DEFAULT '', PRIMARY KEY (`tid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `students` ( `sid` int(11) NOT NULL, `sname` varchar(15) NOT NULL DEFAULT '', PRIMARY KEY (`sid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- 中間關係維護表 CREATE TABLE `stu_teach` ( `tid` int(11) NOT NULL, `sid` int(11) NOT NULL, KEY `FKt56181amkhrdpmd2ici8ngp35` (`sid`), KEY `FKe9ifjo0m9y756vlrgmb8oygsa` (`tid`), CONSTRAINT `FKe9ifjo0m9y756vlrgmb8oygsa` FOREIGN KEY (`tid`) REFERENCES `teachers` (`tid`), CONSTRAINT `FKt56181amkhrdpmd2ici8ngp35` FOREIGN KEY (`sid`) REFERENCES `students` (`sid`),-- 這裏面的外鍵是開發工具加的,不知道爲啥mmp CONSTRAINT `fk_sid` FOREIGN KEY (`sid`) REFERENCES `students` (`sid`) ON DELETE NO ACTION ON UPDATE CASCADE, CONSTRAINT `fk_tid` FOREIGN KEY (`tid`) REFERENCES `teachers` (`tid`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
@ManyToMany @JoinTable( name = "stu_teach", joinColumns = {@JoinColumn(name = "tid",updatable = false)}, inverseJoinColumns = {@JoinColumn(name="sid",updatable = false)} ) public Set<Students> getStus() { return stus; }
在Teachers.java類中上面的註解便可知足單向多對多開發;
***********雙向多對多
Students.java
private Set<Teachers> teachers = new HashSet<>() ; @ManyToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY) @JoinTable( name = "stu_teach", joinColumns = {@JoinColumn(name = "sid",updatable = false)},//該實體對應表的主鍵 inverseJoinColumns = {@JoinColumn(name="tid",updatable = false)} ) public Set<Teachers> getTeachers() { return teachers; }
Teacher.java
private Set<Students> stus = new HashSet<>(); @ManyToMany(cascade = CascadeType.MERGE,fetch = FetchType.LAZY) @JoinTable( name = "stu_teach", joinColumns = {@JoinColumn(name = "tid",updatable = false)},//該實體對應表的主鍵 inverseJoinColumns = {@JoinColumn(name="sid",updatable = false)} ) public Set<Students> getStus() { return stus; }
總結:
真的很操蛋啊,比mybatis要難學多了,各類bug,哎