一、需求
如題,當建好Model 時,不想自己手工建表,可以采取hibernate進行自動建表。下面將用一個小例子來說明如何將其實現。
二、實現
說明:1)這里用的是4.3.1.Final版本的hibernate,mysql-connector-java用的是5.1.26版本的;
2)這里要手工新那一個數據庫ssh,建庫語句為:
create database ssh;
1.新建maven項目


都填寫好了,點擊finish即可。

2.項目架構圖
下面是maven默認的目錄,如果沒有main/java 和test/java那么自己手工建吧。


3.代碼
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.amos</groupId> <artifactId>spring_mvc_hibernate</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>spring_mvc_hibernate Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>4.3.1.Final</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.26</version> </dependency> </dependencies> <build> <finalName>spring_mvc_hibernate</finalName> </build> </project>
hibernate.cfg.xml
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">root</property> <property name="hibernate.connection.url">jdbc:mysql://127.0.0.1:3306/ssh?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true </property> <property name="hibernate.hbm2ddl.auto">update</property> <property name="hibernate.cache.use_second_level_cache">false</property> <mapping class="com.amos.model.Person" /> </session-factory> </hibernate-configuration>
自動建表的關鍵是在<property name="hibernate.hbm2ddl.auto">update</property>,看hibernate的文檔就發現還有其它幾個選項:
validate 加載hibernate時,驗證創建數據庫表結構
create 每次加載hibernate,重新創建數據庫表結構,這就是導致數據庫表數據丟失的原因。
create-drop 加載hibernate時創建,退出是刪除表結構
update 加載hibernate自動更新數據庫結構,如果沒有,那就新建數據結構。
model中的Person.java
package com.amos.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; import org.hibernate.annotations.GenericGenerator; @Entity @Table(name = "person2") public class Person { @Id @GenericGenerator(name = "generator", strategy = "increment") @GeneratedValue(generator = "generator", strategy = GenerationType.TABLE) @Column(unique = true, nullable = false) private Long id; @Column(name = "name", length = 50) private String name; @Column private Integer age; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
注:這里使用注解的方式,使用自增的方式,注意加粗的地方的配置。
PersonDao.java
package com.amos.dao; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; import com.amos.model.Person; /** * @ClassName: PersonDao * @Description: 用戶dao * @author: amosli * @email:amosli@infomorrow.com * @date 2014年2月28日 下午6:01:19 */ public class PersonDao { private static SessionFactory sessionFactory = null; public static void main(String[] args) { // SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory(); createSessionFactory(); Session session = sessionFactory.openSession(); session.beginTransaction(); Person person = new Person(); person.setAge(18); person.setName("amos"); session.save(person); session.getTransaction().commit(); session.close(); System.exit(0); } public static SessionFactory createSessionFactory() { Configuration cfg = new Configuration().configure(); System.out.println("cfg.getProperties():" + cfg.getProperties()); StandardServiceRegistry build = new StandardServiceRegistryBuilder().applySettings(cfg.getProperties()).build(); sessionFactory = cfg.buildSessionFactory(build); return sessionFactory; } }
注: 加粗的部分是重點,這里建議用未過時的就是新建一個ServiceRegistry。
用 new Configuration().configure().buildSessionFactory()會提示:Deprecated. Use buildSessionFactory(ServiceRegistry) instead
看源碼,就會發現Configuration類中的buildSessionFactory()用的就是
final ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() .applySettings( properties ) .build();
這里模仿其用法,也用StandardServiceRegistryBuilder實現ServiceRegistry,經測試是沒問題的。
另,如果hibernate.cfg.xml自己更改為hibernate_test.xml那么應改怎么辦?
只需要在new Configuration().configure("hibernate_test.xml")即可,這樣可以指定其去加載classpath下的.xml文件。
4.效果

5.遇到的問題
Exception in thread "main" org.hibernate.AnnotationException: No identifier specified for entity: com.amos.model.Person at org.hibernate.cfg.InheritanceState.determineDefaultAccessType(InheritanceState.java:277) at org.hibernate.cfg.InheritanceState.getElementsToProcess(InheritanceState.java:224) at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:775) at org.hibernate.cfg.Configuration$MetadataSourceQueue.processAnnotatedClassesQueue(Configuration.java:3790) at org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(Configuration.java:3744) at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1410) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1844) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1928) at com.amos.dao.PersonDao.main(PersonDao.java:11)
出現個主要是因為在建model 時沒有定義id為其主鍵,所以報錯了,在其前面加上@Id即可。
6.補充
下面是:hibernate.cfg.xml一些可參考的配置,主要將部分配置外包化,這樣考慮主要是項目有可能在測試環境測一段時間然后才部署到生產環境上去。
<?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <!-- Generated by MyEclipse Hibernate Tools. --> <hibernate-configuration> <session-factory> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">${hibernate.credit.url}</property> <property name="connection.username">${hibernate.credit.username}</property> <property name="connection.password">${hibernate.credit.password}</property> <!--數據庫連接池的大小 20 --> <!-- <property name="hibernate.connection.pool.size">1 </property> --> <property name="connection.provider_class">org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider</property> <!-- 最大連接數 --> <property name="hibernate.c3p0.max_size">50</property> <!-- 最小連接數 --> <property name="hibernate.c3p0.min_size">${hibernate.credit.min_size}</property> <!-- 獲得連接的超時時間,如果超過這個時間,會拋出異常,單位毫秒 --> <property name="hibernate.c3p0.timeout">9000</property> <!-- 最多高速緩存 20 個預編譯語句 不為0會報APPARENT DEADLOCK!!!死鎖警告 --> <property name="hibernate.c3p0.max_statements">0</property> <!-- 當連接池里面的連接用完的時候,C3P0一下獲取的新的連接數 --> <property name="hibernate.c3p0.acquire_increment">2</property> <!-- 每隔600秒檢查連接池里的空閑連接 ,單位是秒 --> <property name="hibernate.c3p0.idle_test_period">180</property> <property name="hibernate.c3p0.automaticTestTable">Test</property> <!-- 在checkout一個connection時候,判斷這個connection沒有被使用的時間是否大於maxIdleTime,來決定是關閉它,還是被checkout --> <!-- <property name="maxIdleTime">1800</property> --> <!--定義在從數據庫獲取新連接失敗后重復嘗試的次數。Default: 30 --> <property name="acquireRetryAttempts">30</property> <!--兩次連接中間隔時間,單位毫秒。Default: 1000 --> <property name="acquireRetryDelay">1000</property> <!--連接關閉時默認將所有未提交的操作回滾。Default: false --> <property name="autoCommitOnClose">true</property> <!-- -jdbc.fetch_size是指Hibernate每次從數據庫中取出並放到JDBC的Statement中的記錄條數.Fetch Size設的越大,讀數據庫的次數越少,速度越快, --> <!-- Fetch Size越小,讀數據庫的次數越多,速度越慢 --> <property name="jdbc.fetch_size">30 </property> <!--jdbc.batch_size是指Hibernate批量插入,刪除和更新時每次操作的記錄數。Batch Size越大,批量操作的向數據庫發送Sql的次數越少,速度就越快,同樣耗用內存就越大 --> <property name="jdbc.batch_size">30 </property> <!--jdbc.use_scrollable_resultset是否允許Hibernate用JDBC的可滾動的結果集。對分頁的結果集。對分頁時的設置非常有幫助 --> <property name="jdbc.use_scrollable_resultset">true </property> <!--connection.useUnicode連接數據庫時是否使用Unicode編碼 --> <property name="Connection.useUnicode">true </property> <!--connection.characterEncoding連接數據庫時數據的傳輸字符集編碼方式,最好設置為gbk,utf-8,用gb2312有的字符不全 --> <property name="connection.characterEncoding">utf-8 </property> <!-- 執行事務的方式 --> <property name="current_session_context_class">thread</property> <!-- <property name="current_session_context_class">jta</property> --> <!-- 事物隔離-防止查詢出現緩存 Read Committed(讀取提交內容) 1,2,4,8 --> <property name="hibernate.connection.isolation">2</property> <!-- 是否更新表 TODO 需要關閉! update false --> <property name="hibernate.hbm2ddl.auto">update</property> <property name="show_sql">false</property> <property name="format_sql">false</property> <mapping class="com.amos.model.Person" /> </session-factory> </hibernate-configuration>
test.properties
hibernate.credit.url=jdbc:mysql://127.0.0.1:3306/juxinli_credit?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true hibernate.credit.username=root hibernate.credit.password=root hibernate.credit.min_size=5
在pom.xml 中 </dependencies>之后,</project>加上如下配置:
</dependencies> <build> <finalName>hibernate</finalName> <defaultGoal>compile</defaultGoal> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.1</version> <configuration> <source>1.7</source> <target>1.7</target> <encoding>UTF-8</encoding> <compilerArguments> <extdirs>src/main/webapp/WEB-INF/lib</extdirs> </compilerArguments> </configuration> </plugin> </plugins> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> </build> <profiles> <profile> <id>development</id> <activation> <activeByDefault>true</activeByDefault> </activation> <build> <filters> <filter>src/main/resources/environment/test.properties</filter> </filters> </build> </profile> <profile> <id>production</id> <build> <filters> <filter>src/main/resources/environment/production.properties</filter> </filters> </build> </profile> </profiles></project>
在使用maven打war包時:
1)可以手動運行命令:
mvn package -Ptest
這樣表示的是打id為test的war包。
2)也可以采用:項目名稱,鼠標右鍵Run As--> Maven install 進行打包。
7.本文源碼
https://github.com/amosli/hibernate_auto_create_table
