5. 對象的狀態(tài)及生命周期及CRUD操作
5.1 對象的狀態(tài)及生命周期

hibernate對象狀態(tài)轉(zhuǎn)換圖
Transient:瞬時態(tài),session中有,數(shù)據(jù)庫中沒有
Persistent:持久態(tài),session中有,數(shù)據(jù)庫中有。
Detached:游離態(tài),session中沒有,數(shù)據(jù)庫中有。
5.2 new->save->close->update
@Test
public void testSave() {
Session session = null;
Transaction tx = null;
User user = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
// 構(gòu)造對象--瞬時狀態(tài)
user = new User();
user.setName("李四");
user.setPwd("222");
// 持久狀態(tài),user被session管理
session.save(user);
/*
* 在持久狀態(tài)下,臟數(shù)據(jù)檢查:當(dāng)提交事務(wù)時或者清理緩存時,發(fā)現(xiàn)session中的數(shù)據(jù)和數(shù)據(jù)庫中的數(shù)據(jù)不一致時,
* 將session中的數(shù)據(jù)更新到數(shù)據(jù)庫中
*/
user.setName("劉德華");
// 在保存以后再修改對象將會產(chǎn)生多條sql語句,效率較低,建議在save前修改
session.flush();
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
// 游離狀態(tài)
user.setName("梁朝偉");
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
// 持久狀態(tài)
session.update(user);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
5.3 get/load->clear/evict
get/load的區(qū)別:get會立即查詢對象,load在使用才去查詢,get找不到對象返回null,load找不到對象拋異常。
@Test
public void testGet() {
Session session = null;
Transaction tx = null;
User user = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
// get后會變?yōu)槌志脿顟B(tài)
// get方法會立即查詢對象:范圍從Session,SessionFactory,數(shù)據(jù)庫
// get查詢不到對象返回null
user = (User) session.get(User.class, 11);
// System.out.println(user);
// 游離狀態(tài)下不被session管理 數(shù)據(jù)庫中不會被更改
// session.evict(user);
// session.clear();
// user.setName("郭富城");
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
@Test
public void testLoad() {
Session session = null;
Transaction tx = null;
User user = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
// load后會變?yōu)槌志脿顟B(tài)
// load方法不會立即查詢對象,到使用的時候才會查詢
// loadl當(dāng)對象不存在會拋異常
user = (User) session.load(User.class, 11);
System.out.println(user);
// 游離狀態(tài)下不被session管理 數(shù)據(jù)庫中不會被更改
// session.evict(user);
// session.clear();
// user.setName("郭富城");
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
5.4 update:先獲取再修改->可以避免異常
@Test
public void testUpdate() {
Session session = null;
Transaction tx = null;
User user = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
// 手動構(gòu)造的瞬時狀態(tài)的對象也可以修改,但是需要指定所有屬性,不建議使用。
// user = new User();
// user.setId(5);
// user.setName("王五");
// 通過從數(shù)據(jù)庫中加載該對象然后再修改 可以進行判斷從而避免異常,提高程序的健壯性
user = (User) session.get(User.class, 5);
if(user != null) {
user.setName("老王");
session.update(user);
}
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
5.5 delete:先獲取再刪除->可以避免異常
@Test
public void testDelete() {
Session session = null;
Transaction tx = null;
User user = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
// 手動構(gòu)造的瞬時狀態(tài)的對象也可以刪除,不建議使用。
// user = new User();
// user.setId(5);
// 通過從數(shù)據(jù)庫中加載該對象然后再修改 可以進行判斷從而避免異常,提高程序的健壯性
user = (User) session.get(User.class, 1);
if(user != null) {
session.delete(user);
}
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
6. SchemaExport&組合主鍵映射
6.1 SchemaExport的使用
@Test
public void testCreateDB() {
Configuration cfg = new Configuration().configure();
SchemaExport se = new SchemaExport(cfg);
// 第一個參數(shù)是否生成ddl腳本,第二個參數(shù)是否執(zhí)行到數(shù)據(jù)庫
se.create(true, true);
}
6.2 通過組件來實現(xiàn)組合主鍵的步驟
- 編寫組合主鍵的類,該類必須實現(xiàn)Serializable接口
public class ScoreId implements Serializable {
private Integer stuId;
private Integer subjectId;
public Integer getStuId() {
return stuId;
}
public void setStuId(Integer stuId) {
this.stuId = stuId;
}
public Integer getSubjectId() {
return subjectId;
}
public void setSubjectId(Integer subjectId) {
this.subjectId = subjectId;
}
}
- 在主類中引用對應(yīng)的組件
public class Score implements Serializable {
private ScoreId scoreId;
private Integer result;
public ScoreId getScoreId() {
return scoreId;
}
public void setScoreId(ScoreId scoreId) {
this.scoreId = scoreId;
}
public Integer getResult() {
return result;
}
public void setResult(Integer result) {
this.result = result;
}
}
- 編寫配置文件
<hibernate-mapping package="com.yxxy.pojo">
<class name="Score">
<!-- 組合主鍵 -->
<composite-id name="scoreId" class="ScoreId">
<key-property name="stuId"></key-property>
<key-property name="subjectId"></key-property>
</composite-id>
<!-- 實體類的屬性 -->
<property name="result"></property>
</class>
</hibernate-mapping>
- 測試
@Test
public void testSave() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
Score score = new Score();
ScoreId sId = new ScoreId();
sId.setStuId(1);
sId.setSubjectId(2);
score.setResult(90);
score.setScoreId(sId);
session.save(score);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
7. 大對象映射
- 在pojo類中,用Blob類型和Clob類型
public class Student {
private Integer id;
private String name;
private Integer age;
// 存放大數(shù)據(jù) 最大可存放4G
private Blob image;
private Clob introduce;
}
- 在*.hbm.xml文件中需要指定類型
<hibernate-mapping package="com.yxxy.pojo">
<class name="Student">
<id name="id">
<generator class="native"></generator>
</id>
<!-- 實體類的屬性 -->
<property name="name"></property>
<property name="age"></property>
<property name="image" type="java.sql.Blob"></property>
<property name="introduce" type="java.sql.Clob"></property>
</class>
</hibernate-mapping>
- 測試
@Test
public void testSave() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
Student stu = new Student();
stu.setName("張三");
stu.setAge(20);
Blob blob = new SerialBlob("blob".getBytes());
Clob clob = new SerialClob("clob".toCharArray());
stu.setImage(blob);
stu.setIntroduce(clob);
session.save(stu);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
8. 組件映射
- 編寫Teacher類
public class Teacher {
private Integer id;
private String name;
private String sex;
private Address address;
}
- 編寫Teacher類的組件Address類
public class Address {
private String add1;
private String add2;
private String add3;
}
- Teacher.hbm.xml映射文件
<hibernate-mapping package="com.yxxy.pojo">
<class name="Teacher">
<id name="id">
<generator class="native"></generator>
</id>
<!-- 實體類的屬性 -->
<property name="name"></property>
<property name="sex"></property>
<!-- 組件映射 -->
<component name="address" class="Address">
<property name="add1"></property>
<property name="add2"></property>
<property name="add3"></property>
</component>
</class>
</hibernate-mapping>
- 測試
@Test
public void testSave() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
Teacher teacher = new Teacher();
teacher.setName("高淇");
teacher.setSex("男");
Address address = new Address();
address.setAdd1("西三旗");
address.setAdd2("西直門");
address.setAdd3("北五環(huán)");
teacher.setAddress(address);
session.save(teacher);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
9. 單向多對一的關(guān)聯(lián)映射
- 學(xué)生表和年級表
學(xué)生表
| ID | Name | Age | Grade_ID |
|---|---|---|---|
| 1 | 張三 | 20 | 1 |
| 2 | 李四 | 30 | 2 |
| 3 | 王五 | 40 | 1 |
年級表
| ID | Name |
|---|---|
| 1 | 初級 |
| 2 | 中級 |
- Student類和Grade類
public class Student {
private Integer id;
private String name;
private Integer age;
private Grade grade;
}
public class Grade {
private Integer id;
private String name;
}
- 映射文件
Grade.hbm.xml
<hibernate-mapping package="com.yxxy.pojo">
<class name="Grade">
<id name="id">
<generator class="native"></generator>
</id>
<!-- 實體類的屬性 -->
<property name="name"></property>
</class>
</hibernate-mapping>
Student.hbm.xml
<hibernate-mapping package="com.yxxy.pojo">
<class name="Student">
<id name="id">
<generator class="native"></generator>
</id>
<!-- 實體類的屬性 -->
<property name="name"></property>
<property name="age"></property>
<!--
多對一
name:表示屬性名
class:指明屬性對應(yīng)的類
colume:指數(shù)據(jù)庫表中的列名
-->
<many-to-one name="grade" class="Grade" column="grade_id" foreign-key="fk_grade" not-null="true"></many-to-one>
</class>
</hibernate-mapping>
- 測試
@Test
public void testSave() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
Grade grade = new Grade();
grade.setName("基礎(chǔ)");
Student stu = new Student();
stu.setName("張三");
stu.setAge(20);
stu.setGrade(grade);
session.save(grade);
session.save(stu);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
10. 單向一對多的關(guān)聯(lián)映射
- 類Student和Grade類
public class Grade {
private Integer id;
private String name;
private Set<Student> students = new HashSet<>();
}
public class Student {
private Integer id;
private String name;
private Integer age;
}
- 映射文件
Grade.hbm.xml
<hibernate-mapping package="com.yxxy.pojo">
<class name="Grade">
<id name="id">
<generator class="native"></generator>
</id>
<!-- 實體類的屬性 -->
<property name="name"></property>
<!-- set是Grade中的集合屬性 name屬性名稱 -->
<set name="students">
<!-- key表示外鍵 colume外鍵列名 -->
<key column="grade_id" not-null="true" foreign-key="fk_grade"></key>
<!-- 一對多 類Grade中 students所表示的類型 -->
<one-to-many class="Student"/>
</set>
</class>
</hibernate-mapping>
Student.hbm.xml
<hibernate-mapping package="com.yxxy.pojo">
<class name="Student">
<id name="id">
<generator class="native"></generator>
</id>
<!-- 實體類的屬性 -->
<property name="name"></property>
<property name="age"></property>
</class>
</hibernate-mapping>
- 測試
@Test
public void testSave() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
Grade grade = new Grade();
grade.setName("基礎(chǔ)");
Student stu = new Student();
stu.setName("張三");
stu.setAge(20);
stu.setGrade(grade);
session.save(grade);
session.save(stu);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
11. 雙向一對多的關(guān)聯(lián)映射
- 類Student和Grade類
public class Grade {
private Integer id;
private String name;
private Set<Student> students = new HashSet<>();
}
public class Student {
private Integer id;
private String name;
private Integer age;
private Grade grade;
}
-
映射文件
Grade.hbm.xml
<hibernate-mapping package="com.yxxy.pojo">
<class name="Grade">
<id name="id">
<generator class="native"></generator>
</id>
<!-- 實體類的屬性 -->
<property name="name"></property>
<!-- set是Grade中的集合屬性 name屬性名稱 -->
<set name="students">
<!-- key表示外鍵 colume外鍵列名 -->
<key column="grade_id" not-null="true" foreign-key="fk_grade"></key>
<!-- 一對多 類Grade中 students所表示的類型 -->
<one-to-many class="Student"/>
</set>
</class>
</hibernate-mapping>
Student.hbm.xml
<hibernate-mapping package="com.yxxy.pojo">
<class name="Student">
<id name="id">
<generator class="native"></generator>
</id>
<!-- 實體類的屬性 -->
<property name="name"></property>
<property name="age"></property>
<!--
多對一
name:表示屬性名
class:指明屬性對應(yīng)的類
colume:指數(shù)據(jù)庫表中的列名
-->
<many-to-one name="grade" class="Grade" column="grade_id" foreign-key="fk_grade"></many-to-one>
</class>
</hibernate-mapping>
- 測試
@Test
public void testSaveByOneToMany() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
Student stu = new Student();
stu.setName("張三");
stu.setAge(20);
Grade grade = new Grade();
grade.getStudents().add(stu);
grade.setName("基礎(chǔ)");
/**
* 保存數(shù)據(jù)的順序是根據(jù)外鍵的配置來決定的
* 如果外鍵不能為null 先保存一的一端
* 如果外鍵可以為null 則隨意保存,但是會多執(zhí)行update語句
*/
session.save(grade);
session.save(stu);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
@Test
public void testSaveByManyToOne() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
Grade grade = new Grade();
grade.setName("基礎(chǔ)");
Student stu = new Student();
stu.setName("張三");
stu.setAge(20);
stu.setGrade(grade);
session.save(grade);
session.save(stu);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
@Test
public void testGet() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
//取數(shù)據(jù)
Grade grade = (Grade) session.get(Grade.class, 1);
System.out.println("gradeName:" + grade.getName());
System.out.println("grade所對應(yīng)的多的一端的數(shù)據(jù)");
Iterator<Student> iter = grade.getStudents().iterator();
for(; iter.hasNext();) {
Student stu = iter.next();
System.out.println("name=" + stu.getName() + " age=" + stu.getAge());
}
System.out.println("=================================");
Student stu = (Student) session.get(Student.class, 1);
System.out.println("name=" + stu.getName() + " age=" + stu.getAge());
System.out.println("student所對應(yīng)的一端的數(shù)據(jù)");
System.out.println("gradeName:" + stu.getGrade().getName());
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}