Hibernate——自動創建數據庫表 & 對象的三種狀態

自動創建數據庫表

如果需要Hibernate根據映射關係自動創建數據庫,則需要配置hibernate.cfg.xml文件

<property name="hbm2ddl.auto">create</property>

這裏有四個配置,分別是:create、update、create-drop和validate

  • create:當我們的應用程序加載hibernate.cfg.xml(比如new Configuration().configure())時,就會根據映射文件,創建出數據庫,每次都會刪掉已經存在的數據庫重新創建;
  • update:如果數據庫中沒有該表,則創建表,如果有表,則看錶有沒有變化,如果有變化,則更新(比如增加一列);
  • create-drop:在顯示關閉sessionFactory時,將drop掉數據庫的schema
  • validate:相當於每次插入數據之前都會驗證數據庫中的表結構和hbm文件的結果是否一致

下面我們對update屬性做簡單的測試,首先我們創建一個數據庫test

這裏寫圖片描述

可以看到,當前數據庫中沒有任何數據表。

接着,我們創建項目HibernateHbmToDDL,手動創建一個domain對象Student,如下:

package com.gavin.domain;

public class Student {
    private Integer id;
    private String name;
    private String sex;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

並且手動配置其對象關係映射文件Student.hbm.xml,如下:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>

    <class name="com.gavin.domain.Student" table="student" schema="test">
        <id name="id" column="id" type="java.lang.Integer"/>
        <property name="name" column="name" type="java.lang.String" length="64"/>
        <property name="sex" column="sex" type="java.lang.String" length="8"/>
    </class>
</hibernate-mapping>

接着,我們對Hibernate進行配置。hibernate.cfg.xml文件如下:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="connection.url">jdbc:mysql://localhost:3306/test</property>
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.username">root</property>
        <property name="connection.password">gavin</property>

        <!-- DB schema will be updated if needed -->
         <property name="hbm2ddl.auto">update</property>
        <mapping resource="com/gavin/domain/Student.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

可以看到,在這裏我們配置了<property name="hbm2ddl.auto">update</property>,所以如果數據庫沒有表的時候,Hibernate會自動幫我們建表。

下面寫一個主方法保存一個Student對象:

import com.gavin.domain.Student;
import org.hibernate.*;
import org.hibernate.cfg.Configuration;

public class Main {

    public static void main(final String[] args) throws Exception {
        Session session = new Configuration().configure().buildSessionFactory().openSession();
        Transaction transaction = session.beginTransaction();

        Student student = new Student();
        student.setId(1);
        student.setName("Gavin");
        student.setSex("M");

        session.save(student);
        transaction.commit();
        session.close();
    }
}

運行之後,我們可以再看數據庫:

這裏寫圖片描述

發現已經數據庫已經創建好了student表,而且存入了剛剛程序中的數據。此時我們可以查看student表的表結構:

這裏寫圖片描述

可以看到name字段是varchar(64)類型,也就是長度爲64,sex長度爲8,這就是之前我們在對象映射文件Student.hbm.xml文件中配置的length屬性起的作用。

對象的狀態

瞬時(transient)

數據庫中沒有數據與之對應,超過作用域會被JVM垃圾回收期回收,一般是new出來且與session沒有關聯的對象。

持久(persistent)

數據庫中有數據與之對應,當前與session有關聯,並且相關聯的session沒有關閉,事務沒有提交;持久對象狀態發生改變,在事務提交時會影響到數據庫(Hibernate能檢測到)

脫管/遊離(detached)

數據庫中有數據與之對應,但當前沒有session與之關聯;託管對象狀態發生改變,Hibernate不能檢測到。

三種狀態的轉換圖如下:

這裏寫圖片描述

示例代碼如下:

// 對象的三種狀態
// 剛剛創建的時候,course就是瞬時態
Course course = new Course();
course.setCcredit(3);
course.setCname("PHP");
SessionFactory sessionFactory = HibernateSessionFactory.getSessionFactory();
Session session = null;
Transaction transaction = null;
try {
    session = sessionFactory.openSession();
    transaction = session.beginTransaction();
    session.save(course);
    // 此時course既處於Session的管理之下(因爲Session還沒有關閉)
    // 同時course被保存在了數據庫中,故其處於持久態
    System.out.println("course.getCname() = " + course.getCname());

    transaction.commit();
    session.close();

    // 這是course被保存到數據庫中,同時沒有處於session的管理之下
    // 故此時course處於遊離態
    System.out.println("course.getCname() = " + course.getCname());
} catch (Exception e) {

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章