按习惯来说,一般系统开发都是从数据库开始设计的。但从面向对象开发的角度,系统的设计应该基于对象模型的设计之上,主要考虑对象的设计和逻辑,然后按照对象模型生成数据库结构,利用hibernate的SchemaExport对象可以方便的实现这一点。另外,使用注解也省却了很多繁杂的配置工作,下面对hibernate注解自动生成数据表的过程做一个详细描述。
一、环境搭载
下载了最新的hibernate-release-4.0.0.CR7.zip,导入required包,这个例子是基于MySql数据库,因此还需要mysql-connector-java-5.1.5.jar
二、配置
hibernate的配置文件可以使用xml或者properties,这里使用的xml:
关于current_session_context_class配置项:
通过hibernate操作数据库时,主要是通过session实现的,session可以简单的视为对数据库的一个链接,有它的生命周期。获取session在SessionFactory里有两个方法,getCurrentSession()和openSession(),后者每次都会新建一个session,它们的区别:
1 、getCurrentSession创建的session会绑定到当前线程,而openSession不会。
2 、getCurrentSession创建的线程会在事务回滚或事物提交后自动关闭,而openSession必须手动关闭
因此,通常使用getCurrentSession()会方便高效一些,但需要在配置文件中配置current_session_context_class,可以有两个取值jta或者thread。
引用: 使用Hibernate的大多数应用程序需要某种形式的“上下文相关的” session,特定的session在整个特定的上下文范围内始终有效。然而,对不同类型的应用程序而言,要为什么是组成这种“上下文”下一个定义通常是困难的;不同的上下文对“当前”这个概念定义了不同的范围。在3.0版本之前,使用Hibernate的程序要么采用自行编写的基于 ThreadLocal的上下文session,要么采用HibernateUtil这样的辅助类,要么采用第三方框架(比如Spring或Pico),它们提供了基于代理(proxy)或者基于拦截器(interception)的上下文相关session。
从3.0.1版本开始,Hibernate增加了SessionFactory.getCurrentSession()方法。一开始,它假定了采用JTA事务,JTA事务定义了当前session的范围和上下文(scope and context)。Hibernate开发团队坚信,因为有好几个独立的JTA TransactionManager实现稳定可用,不论是否被部署到一个J2EE容器中,大多数(假若不是所有的)应用程序都应该采用JTA事务管理。基于这一点,采用JTA的上下文相关session可以满足你一切需要。
更好的是,从3.1开始,SessionFactory.getCurrentSession()的后台实现是可拔插的。因此,我们引入了新的扩展接口 (org.hibernate.context.CurrentSessionContext)和新的配置参数 (hibernate.current_session_context_class),以便对什么是“当前session”的范围和上下文(scope and context)的定义进行拔插。
请参阅 org.hibernate.context.CurrentSessionContext接口的Javadoc,那里有关于它的契约的详细讨论。它定义了单一的方法,currentSession(),特定的实现用它来负责跟踪当前的上下文session。Hibernate内置了此接口的两种实现。
org.hibernate.context.JTASessionContext - 当前session根据JTA来跟踪和界定。这和以前的仅支持JTA的方法是完全一样的。详情请参阅Javadoc。 org.hibernate.context.ThreadLocalSessionContext - 当前session通过当前执行的线程来跟踪和界定。详情也请参阅Javadoc。
这两种实现都提供了“每数据库事务对应一个session”的编程模型,也称作每次请求一个session。Hibernate session的起始和终结由数据库事务的生存来控制。假若你采用自行编写代码来管理事务(比如,在纯粹的J2SE,或者 JTA/UserTransaction/BMT),建议你使用Hibernate Transaction API来把底层事务实现从你的代码中隐藏掉。如果你在支持CMT的EJB容器中执行,事务边界是声明式定义的,你不需要在代码中进行任何事务或 session管理操作。请参阅第 11 章 事务和并发一节来阅读更多的内容和示例代码。 hibernate.current_session_context_class 配置参数定义了应该采用哪个org.hibernate.context.CurrentSessionContext实现。注意,为了向下兼容,如果未配置此参数,但是存在org.hibernate.transaction.TransactionManagerLookup的配置,Hibernate会采用org.hibernate.context.JTASessionContext。一般而言,此参数的值指明了要使用的实现类的全名,但那两个内置的实现可以使用简写,即"jta"和"thread"。
在 SessionFactory 启动的时候, Hibernate 会根据配置创建相应的 CurrentSessionContext ,在 getCurrentSession() 被调用的时候,实际被执行的方法是 CurrentSessionContext.currentSession() 。在 currentSession() 执行时,如果当前 Session 为空, currentSession 会调用 SessionFactory 的 openSession 。所以 getCurrentSession() 对于 Java EE 来说是更好的获取 Session 的方法。
三、编写持久化对象
所有对象编写完后,需要在配置文件中配置,这里为:<mapping class="cn.com.model.User" />
四、测试
Configuration configuration = new AnnotationConfiguration();
configuration.configure();
SchemaExport export = new SchemaExport(configuration);
export.execute(true, true, false, true);
SessionFactory factory = configuration.buildSessionFactory();
// Session session = factory.openSession();
Session session = factory.getCurrentSession();
session.beginTransaction();
User user = new User();
user.setName("成都");
session.save(user);
session.getTransaction().commit();
// session.close();
关于SchemaExport对象有几个方法生成数据库结构。
1、create(boolean script,boolean export)
script:是否在控制台打印DDL语句,export为true时,会先执行drop再根据持久化对象create数据表,可能造成数据丢失,为false时,数据库需要先建立对应的数据表,否则会找不到表而报错,不会造成数据丢失。
2、drop(boolean script,boolean export)
script:是否在控制台打印DDL语句,export为true时,会执行drop操作,为false时不执行
3、execute(boolean script, boolean export,boolean justDrop, boolean justCreate)
当export为true时,justDrop为false,justCreate为true,如果对应的数据表不存在,则create,如果存在则不执行create操作
当export为true时,justDrop为true,justCreate为false,执行drop操作
因此,要新建数据表,最好使用create(true,true);
一、环境搭载
下载了最新的hibernate-release-4.0.0.CR7.zip,导入required包,这个例子是基于MySql数据库,因此还需要mysql-connector-java-5.1.5.jar
二、配置
hibernate的配置文件可以使用xml或者properties,这里使用的xml:
01.<?xml version="1.0" encoding="UTF-8"?>
02.<!DOCTYPE hibernate-configuration PUBLIC
03."-//Hibernate/Hibernate Configuration DTD 3.0//EN"
04."http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
05.
06.<hibernate-configuration>
07.<session-factory>
08. <!-- 各属性的配置-->
09. <!--为true表示将Hibernate发送给数据库的sql显示出来-->
10. <property name="show_sql">true</property>
11. <!-- SQL方言,这边设定的是MySQL -->
12. <property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
13. <!-- 一次读的数据库记录数 -->
14. <property name="jdbc.fetch_size">50</property>
15. <!-- 设定对数据库进行批量删除 -->
16. <property name="jdbc.batch_size">30</property>
17. <!--驱动程序-->
18. <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
19. <!-- JDBC URL -->
20. <property name="connection.url">jdbc:mysql://localhost/fight_game?characterEncoding=utf-8</property>
21. <!-- 数据库用户名-->
22. <property name="connection.username">root</property>
23. <!-- 数据库密码-->
24. <property name="connection.password">root</property>
25.
26. <!-- 使用本地事务jdbc事务,如果是使用全局jta事务,则需要配置为jta-->
27.
28. <property name="current_session_context_class">thread</property>
29.<mapping class="cn.com.model.User" />
30.</session-factory>
31.</hibernate-configuration>
关于current_session_context_class配置项:
通过hibernate操作数据库时,主要是通过session实现的,session可以简单的视为对数据库的一个链接,有它的生命周期。获取session在SessionFactory里有两个方法,getCurrentSession()和openSession(),后者每次都会新建一个session,它们的区别:
1 、getCurrentSession创建的session会绑定到当前线程,而openSession不会。
2 、getCurrentSession创建的线程会在事务回滚或事物提交后自动关闭,而openSession必须手动关闭
因此,通常使用getCurrentSession()会方便高效一些,但需要在配置文件中配置current_session_context_class,可以有两个取值jta或者thread。
引用: 使用Hibernate的大多数应用程序需要某种形式的“上下文相关的” session,特定的session在整个特定的上下文范围内始终有效。然而,对不同类型的应用程序而言,要为什么是组成这种“上下文”下一个定义通常是困难的;不同的上下文对“当前”这个概念定义了不同的范围。在3.0版本之前,使用Hibernate的程序要么采用自行编写的基于 ThreadLocal的上下文session,要么采用HibernateUtil这样的辅助类,要么采用第三方框架(比如Spring或Pico),它们提供了基于代理(proxy)或者基于拦截器(interception)的上下文相关session。
从3.0.1版本开始,Hibernate增加了SessionFactory.getCurrentSession()方法。一开始,它假定了采用JTA事务,JTA事务定义了当前session的范围和上下文(scope and context)。Hibernate开发团队坚信,因为有好几个独立的JTA TransactionManager实现稳定可用,不论是否被部署到一个J2EE容器中,大多数(假若不是所有的)应用程序都应该采用JTA事务管理。基于这一点,采用JTA的上下文相关session可以满足你一切需要。
更好的是,从3.1开始,SessionFactory.getCurrentSession()的后台实现是可拔插的。因此,我们引入了新的扩展接口 (org.hibernate.context.CurrentSessionContext)和新的配置参数 (hibernate.current_session_context_class),以便对什么是“当前session”的范围和上下文(scope and context)的定义进行拔插。
请参阅 org.hibernate.context.CurrentSessionContext接口的Javadoc,那里有关于它的契约的详细讨论。它定义了单一的方法,currentSession(),特定的实现用它来负责跟踪当前的上下文session。Hibernate内置了此接口的两种实现。
org.hibernate.context.JTASessionContext - 当前session根据JTA来跟踪和界定。这和以前的仅支持JTA的方法是完全一样的。详情请参阅Javadoc。 org.hibernate.context.ThreadLocalSessionContext - 当前session通过当前执行的线程来跟踪和界定。详情也请参阅Javadoc。
这两种实现都提供了“每数据库事务对应一个session”的编程模型,也称作每次请求一个session。Hibernate session的起始和终结由数据库事务的生存来控制。假若你采用自行编写代码来管理事务(比如,在纯粹的J2SE,或者 JTA/UserTransaction/BMT),建议你使用Hibernate Transaction API来把底层事务实现从你的代码中隐藏掉。如果你在支持CMT的EJB容器中执行,事务边界是声明式定义的,你不需要在代码中进行任何事务或 session管理操作。请参阅第 11 章 事务和并发一节来阅读更多的内容和示例代码。 hibernate.current_session_context_class 配置参数定义了应该采用哪个org.hibernate.context.CurrentSessionContext实现。注意,为了向下兼容,如果未配置此参数,但是存在org.hibernate.transaction.TransactionManagerLookup的配置,Hibernate会采用org.hibernate.context.JTASessionContext。一般而言,此参数的值指明了要使用的实现类的全名,但那两个内置的实现可以使用简写,即"jta"和"thread"。
在 SessionFactory 启动的时候, Hibernate 会根据配置创建相应的 CurrentSessionContext ,在 getCurrentSession() 被调用的时候,实际被执行的方法是 CurrentSessionContext.currentSession() 。在 currentSession() 执行时,如果当前 Session 为空, currentSession 会调用 SessionFactory 的 openSession 。所以 getCurrentSession() 对于 Java EE 来说是更好的获取 Session 的方法。
三、编写持久化对象
import java.io.Serializable;
04.
05.import javax.persistence.Column;
06.import javax.persistence.Entity;
07.import javax.persistence.GeneratedValue;
08.import javax.persistence.GenerationType;
09.import javax.persistence.Id;
10.import javax.persistence.Table;
11.
12.@Entity
13.@Table(name="t_user")
14.public class User implements Serializable{
15. /**
16. *
17. */
18. private static final long serialVersionUID = 1L;
19.
20. private long id;
21.
22. private String name;
23.
24. @Id
25. @GeneratedValue(strategy=GenerationType.IDENTITY)
26. public long getId() {
27. return id;
28. }
29.
30. public void setId(long id) {
31. this.id = id;
32. }
33.
34. @Column(name="name",length=50)
35. public String getName() {
36. return name;
37. }
38.
39. public void setName(String name) {
40. this.name = name;
41. }
42.
43.}
所有对象编写完后,需要在配置文件中配置,这里为:<mapping class="cn.com.model.User" />
四、测试
Configuration configuration = new AnnotationConfiguration();
configuration.configure();
SchemaExport export = new SchemaExport(configuration);
export.execute(true, true, false, true);
SessionFactory factory = configuration.buildSessionFactory();
// Session session = factory.openSession();
Session session = factory.getCurrentSession();
session.beginTransaction();
User user = new User();
user.setName("成都");
session.save(user);
session.getTransaction().commit();
// session.close();
关于SchemaExport对象有几个方法生成数据库结构。
1、create(boolean script,boolean export)
script:是否在控制台打印DDL语句,export为true时,会先执行drop再根据持久化对象create数据表,可能造成数据丢失,为false时,数据库需要先建立对应的数据表,否则会找不到表而报错,不会造成数据丢失。
2、drop(boolean script,boolean export)
script:是否在控制台打印DDL语句,export为true时,会执行drop操作,为false时不执行
3、execute(boolean script, boolean export,boolean justDrop, boolean justCreate)
当export为true时,justDrop为false,justCreate为true,如果对应的数据表不存在,则create,如果存在则不执行create操作
当export为true时,justDrop为true,justCreate为false,执行drop操作
因此,要新建数据表,最好使用create(true,true);