自动创建数据库表
如果需要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掉数据库的schemavalidate
:相当于每次插入数据之前都会验证数据库中的表结构和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) {
}