Hibernate的第一个代码

首先来看看hibernate开发的一个简单流程:html

(1)准备开发环境,建立Hibernate项目。
java

(2)在数据库中建立数据表。mysql

(3)建立持久化类。sql

(4)设计映射文件,使用Hibernate映射文件将POJO对象映射到数据库。数据库

(5)建立Hibernate的配置文件Hibernate.cfg.xml。缓存

(6)编写辅助工具类HibernateUtil类,用来实现对HIbernate的初始化并提供得到Session的方法,此步可根据状况取舍。安全

(7)编写DAO层类。session

(8)编写Service层类。并发

(9)编写测试类。app


下面来一步一步地作。

1.建立Eclipse项目

在Eclipse中建立一个Dynamic Web Project项目,命名为HibernateDemo。
HibernateDemo项目名称上右击,在快捷菜单中选择New->Other选项,在弹出的对话框中找到Hibernate节点,选择Hibernate Configuration File(cfg.xml)选项,以下图所示:


点击Next按钮,在弹出的对话框中选择配置文件保存的目录,通常默认在src目录,同时须要输入配置文件的名称,通常默认为hibernate.cfg.xml便可。继续Next,在弹出的对话框中填写数据库方言(Database dialect)、数据库驱动(Driver class)、数据库URL、用户名、密码等。MySQL数据库的配置以下:


单击Finish,配置文件就建立成功了,后面有须要能够继续编辑该文件。

2.建立数据表USER

在MySQL中建立一个名为mysqldb的数据库,在该数据库中建立一张名为USER的表。建立USER表的语句以下:

[sql]  view plain  copy
  1. create table user(  
  2. user_id int(11),  
  3. name varchar(20),  
  4. password varchar(12),  
  5. type varchar(6),  
  6. primary key(user_id));  
建立好的USER表在MySQL中显示以下:

[sql]  view plain  copy
  1. mysql> describe user;  
  2. +----------+-------------+------+-----+---------+-------+  
  3. | Field    | Type        | Null | Key | Default | Extra |  
  4. +----------+-------------+------+-----+---------+-------+  
  5. | user_id  | int(11)     | NO   | PRI | 0       |       |  
  6. name     | varchar(20) | YES  |     | NULL    |       |  
  7. password | varchar(12) | YES  |     | NULL    |       |  
  8. | type     | varchar(6)  | YES  |     | NULL    |       |  
  9. +----------+-------------+------+-----+---------+-------+  

3.编写POJO映射类User.java

[java]  view plain  copy
  1. package org.hibernate.entity;  
  2.   
  3. public class User {  
  4.   
  5.     private int id;//持久化类的标识属性,映射到数据表中的主键列  
  6.     private String name;  
  7.     private String password;  
  8.     private String type;  
  9.     public User() {  
  10.         // TODO Auto-generated constructor stub  
  11.     }  
  12.     public int getId() {  
  13.         return id;  
  14.     }  
  15.     public void setId(int id) {  
  16.         this.id = id;  
  17.     }  
  18.     public String getName() {  
  19.         return name;  
  20.     }  
  21.     public void setName(String name) {  
  22.         this.name = name;  
  23.     }  
  24.     public String getPassword() {  
  25.         return password;  
  26.     }  
  27.     public void setPassword(String password) {  
  28.         this.password = password;  
  29.     }  
  30.     public String getType() {  
  31.         return type;  
  32.     }  
  33.     public void setType(String type) {  
  34.         this.type = type;  
  35.     }  
  36.       
  37. }  

4.编写映射文件User.hbm.xml

[html]  view plain  copy
  1. <?xml version="1.0"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
  3. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  4. <!-- Generated 2014-12-28 22:18:36 by Hibernate Tools 3.4.0.CR1 -->  
  5. <hibernate-mapping>  
  6.     <!-- name 持久化类的类名,table 数据表的表名,MySQL不区分大小写 -->  
  7.     <class name="org.hibernate.entity.User" table="USER">  
  8.         <!-- 将User类中的id属性映射为数据表USER中的主键列user_id -->  
  9.         <id name="id" type="int">  
  10.             <column name="USER_ID" />  
  11.             <generator class="native" />  
  12.         </id>  
  13.         <!-- 映射User类的name属性 -->  
  14.         <property name="name" type="java.lang.String">  
  15.             <column name="NAME" length="20"/>  
  16.         </property>  
  17.         <!-- 映射User类的password属性 -->  
  18.         <property name="password" type="java.lang.String">  
  19.             <column name="PASSWORD"  length="12"/>  
  20.         </property>  
  21.         <!-- 映射User类的type属性 -->  
  22.         <property name="type" type="java.lang.String">  
  23.             <column name="TYPE" length="6"/>  
  24.         </property>  
  25.     </class>  
  26. </hibernate-mapping>  

5.编写hibernate.cfg.xml配置文件

前面咱们经过Hibernate Tools的向导工具新建了一个hibernate.cfg.xml配置文件,其实咱们也能够直接在src目录下新建一个XML文件将其命名为hibernate.cfg.xml。如今咱们须要编辑这个文件,增长一些配置,修改后的文件以下:

[html]  view plain  copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"  
  3.                                          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">  
  4. <hibernate-configuration>  
  5.     <session-factory>  
  6.         <!-- 数据库的JDBC驱动 -->  
  7.         <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>  
  8.         <!-- 数据库的URL -->  
  9.         <property name="hibernate.connection.url">jdbc:mysql://127.0.0.1:3306/mysqldb</property>  
  10.         <!-- 数据库的用户名和密码 -->  
  11.         <property name="hibernate.connection.username">root</property>  
  12.         <property name="hibernate.connection.password"></property>  
  13.         <!-- 数据库的方言 -->  
  14.         <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>  
  15.         <!-- Hibernate自动根据映射文件建立或者更新数据表 -->  
  16.         <property name="hibernate.hbm2ddl.auto">update</property>  
  17.         <!-- 在控制台输出运行时生成的SQL语句,方便调试 -->  
  18.         <property name="show_sql">true</property>  
  19.         <!-- 链接池大小 -->  
  20.         <property name="connection.pool_size">1</property>  
  21.         <!-- 列出全部映射文件 -->  
  22.         <mapping resource="org/hibernate/entity/User.hbm.xml" />  
  23.     </session-factory>  
  24. </hibernate-configuration>  

6.编写辅助工具类HibernateUtil.java

[java]  view plain  copy
  1. package org.hibernate.entity;  
  2.   
  3. import org.hibernate.HibernateException;  
  4. import org.hibernate.Session;  
  5. import org.hibernate.SessionFactory;  
  6. import org.hibernate.cfg.Configuration;  
  7.   
  8. public class HibernateUtil {  
  9.   
  10.     private static SessionFactory sessionFactory;  
  11.     // 建立线程局部变量threadLocal,用来保存Hibernate的Session  
  12.     private static final ThreadLocal<Session> threadLocal=new ThreadLocal<Session>();  
  13.     // 使用静态代码块初始化Hibernate  
  14.     static  
  15.     {  
  16.         try  
  17.         {  
  18.             // 读取配置文件  
  19.             Configuration cfg=new Configuration().configure();  
  20.             // 建立SessionFactory  
  21.             sessionFactory=cfg.buildSessionFactory();  
  22.         }catch(Throwable ex)  
  23.         {  
  24.             throw new ExceptionInInitializerError(ex);  
  25.         }  
  26.     }  
  27.     // 得到SessionFactory的实例  
  28.     public static SessionFactory getsSessionFactory()  
  29.     {  
  30.         return sessionFactory;  
  31.     }  
  32.     // 得到ThreadLocal对象管理的Session  
  33.     public static Session getsSession() throws HibernateException  
  34.     {  
  35.         Session session=(Session) threadLocal.get();  
  36.         if(session==null||!session.isOpen())  
  37.         {  
  38.             if(sessionFactory==null)  
  39.             {  
  40.                 rebuildSessionFactory();  
  41.             }  
  42.             // 经过SessionFactory对象建立Session对象  
  43.             session=(sessionFactory!=null)?sessionFactory.openSession():null;  
  44.             // 将Session对象保存到线程局部变量threadLocal中  
  45.             threadLocal.set(session);  
  46.         }  
  47.         return session;  
  48.     }  
  49.     // 关闭Session实例  
  50.     public static void closeSession()  
  51.     {  
  52.         // 从线程局部变量threadLocal中获取以前存入的Session实例  
  53.         Session session=(Session)threadLocal.get();  
  54.         threadLocal.set(null);  
  55.         if(session!=null)  
  56.         {  
  57.             session.close();  
  58.         }  
  59.     }  
  60.     // 重建SessionFactory  
  61.     public static void rebuildSessionFactory()  
  62.     {  
  63.         Configuration configuration=new Configuration();  
  64.         configuration.configure("/hibernate.cfg.xml");  
  65.         sessionFactory=configuration.buildSessionFactory();  
  66.     }  
  67.     // 关闭缓存和链接池  
  68.     public static void shutdown()  
  69.     {  
  70.         getsSessionFactory().close();  
  71.     }  
  72. }  

7.编写DAO层接口UserDAO.java

[java]  view plain  copy
  1. package org.hibernate.dao;  
  2.   
  3. import org.hibernate.entity.User;  
  4.   
  5. public interface UserDAO {  
  6.   
  7.     void save(User user);  
  8.     User findById(int id);  
  9.     void delete(User user);  
  10.     void update(User user);  
  11. }  

8.编写DAO层实现类UserDAOImpl.java

[java]  view plain  copy
  1. package org.hibernate.dao;  
  2.   
  3. import org.hibernate.Session;  
  4. import org.hibernate.Transaction;  
  5. import org.hibernate.entity.HibernateUtil;  
  6. import org.hibernate.entity.User;  
  7.   
  8. public class UserDAOImpl implements UserDAO {  
  9.   
  10.     // 添加用户  
  11.     @Override  
  12.     public void save(User user) {  
  13.         // TODO Auto-generated method stub  
  14.         // 建立Session实例  
  15.         Session session = HibernateUtil.getsSession();  
  16.         // 建立Transaction实例  
  17.         Transaction tx = session.beginTransaction();  
  18.         try {  
  19.             // 使用Session的save方法将持久化对象保存到数据库  
  20.             session.save(user);  
  21.             // 提交事务  
  22.             tx.commit();  
  23.         } catch (Exception e) {  
  24.             e.printStackTrace();  
  25.             // 出现异常,回滚事务  
  26.             tx.rollback();  
  27.         } finally {  
  28.             // 关闭Session链接  
  29.             HibernateUtil.closeSession();  
  30.         }  
  31.     }  
  32.   
  33.     // 根据id查找用户  
  34.     @Override  
  35.     public User findById(int id) {  
  36.         // TODO Auto-generated method stub  
  37.         User user = null;  
  38.         Session session = HibernateUtil.getsSession();  
  39.         Transaction tx = session.beginTransaction();  
  40.         try {  
  41.             // 使用session的get方法获取指定id的用户  
  42.             user = (User) session.get(User.class, id);  
  43.             tx.commit();  
  44.         } catch (Exception e) {  
  45.             e.printStackTrace();  
  46.             tx.rollback();  
  47.         } finally {  
  48.             HibernateUtil.closeSession();  
  49.         }  
  50.         return user;  
  51.     }  
  52.   
  53.     // 删除用户  
  54.     @Override  
  55.     public void delete(User user) {  
  56.         // TODO Auto-generated method stub  
  57.         Session session = HibernateUtil.getsSession();  
  58.         Transaction tx = session.beginTransaction();  
  59.         try {  
  60.             // 使用session的delete方法将持久化对象删除  
  61.             session.delete(user);  
  62.             tx.commit();  
  63.         } catch (Exception e) {  
  64.             e.printStackTrace();  
  65.             tx.rollback();  
  66.         } finally {  
  67.             HibernateUtil.closeSession();  
  68.         }  
  69.     }  
  70.   
  71.     // 修改用户信息  
  72.     @Override  
  73.     public void update(User user) {  
  74.         // TODO Auto-generated method stub  
  75.         Session session = HibernateUtil.getsSession();  
  76.         Transaction tx = session.beginTransaction();  
  77.         try {  
  78.             // 使用session的update方法更新持久化对象  
  79.             session.update(user);  
  80.             tx.commit();  
  81.         } catch (Exception e) {  
  82.             tx.rollback();  
  83.             e.printStackTrace();  
  84.         } finally {  
  85.             HibernateUtil.closeSession();  
  86.         }  
  87.     }  
  88.   
  89. }  

经过以上步骤,一个Hibernate项目就完成了,下面咱们来测试一下。

9.编写测试类UserTest.java

在HibernateDemo项目名称上右击,选择Properties,在弹出的窗口左侧选择Java Build Path选项,而后在右侧界面中选择Libraries标签,点击Add Library按钮,在弹出的窗口中选择Junit,以下图所示:



而后点击Next,在version一栏选择Junit 4,而后点击Finish。这样Junit包就引入到项目中了。

接下来在项目中新建org.hibernate.test包,在包名上右击,依次选择New->Junit Test Case菜单,在弹出的窗口中填写测试类的名称和须要测试的类的名称(这个须要填写完整包名),以下图所示:



点击Next按钮,能够选择须要测试的方法,根据须要选择便可。



点击Finish,系统会自动生成UserTest类的框架,里面包含了一些空方法,咱们将须要测试的方法进行重写就能够了。

这里以save方法为例,重写testSave方法。

[java]  view plain  copy
  1. package org.hibernate.test;  
  2.   
  3. import org.hibernate.dao.UserDAO;  
  4. import org.hibernate.dao.UserDAOImpl;  
  5. import org.hibernate.entity.User;  
  6. import org.junit.AfterClass;  
  7. import org.junit.Before;  
  8. import org.junit.Test;  
  9.   
  10. public class UserTest {  
  11.   
  12.     @AfterClass  
  13.     public static void tearDownAfterClass() throws Exception {  
  14.     }  
  15.   
  16.     @Before  
  17.     public void setUp() throws Exception {  
  18.     }  
  19.   
  20.     // @Test 注释表名是一个测试方法  
  21.     @Test  
  22.     public void testSave() {  
  23.         UserDAO userDAO=new UserDAOImpl();  
  24.         try{  
  25.             User u=new User();  
  26.             // 设置User对象的各个属性  
  27.             u.setId(20);  
  28.             u.setName("zhangsan");  
  29.             u.setPassword("123456");  
  30.             u.setType("admin");  
  31.             // 使用UserDAOImpl的save方法将User对象存入到数据库  
  32.             userDAO.save(u);  
  33.         }catch(Exception e){  
  34.             e.printStackTrace();  
  35.         }  
  36.     }  
  37. }  
接下来在UserTest.java文件名称上右击,依次选择Run As ->Junit Test菜单,咱们能够在Eclipse的Junit View中看到测试结果,若是进度条正确,表示结果正确,若是进度条为红色,代表有错误,咱们能够看到有什么错误。


而后咱们到数据库中看看数据有没有正确保存到数据库。

[sql]  view plain  copy
  1. mysql> select * from user;  
  2. +---------+----------+----------+-------+  
  3. | USER_ID | NAME     | PASSWORD | TYPE  |  
  4. +---------+----------+----------+-------+  
  5. |       1 | zhangsan | 123456   | admin |  
  6. +---------+----------+----------+-------+  
这里可能有人会感到奇怪,为何UserTest类中设置了id为20,结果保存到数据库中确是1呢?

由于咱们在User.hbm.xml文件中将id设置成了主键,以下所示:

[html]  view plain  copy
  1. <!-- 将User类中的id属性映射为数据表USER中的主键列user_id -->  
  2.    <id name="id" type="int">  
  3.        <column name="USER_ID" />  
  4.        <generator class="native" />  
  5.    </id>  
其中的generator元素指的是主键生成策略,hibernate会按照主键生成策略为id赋值,而不会将程序中的id值存储到数据库。


最后结合上面的项目咱们再看看Hibernate的工做原理:

(1)Hibernate初始化,建立Configuration对象。

a)从Hibernate配置文件hibernate.properties或者hibernate.cfg.xml中读取配置信息,存放到Configuration对象中。

b)根据配置文件中的mapping元素加载全部实体类对应的映射文件到Configuration对象中。

说明:Hibernate能够采起两种形式的配置文件,一种是hibernate.properties文件,另外一种是hibernate.cfg.xml文件。这两种文件本质上是同样的,均可以完成对Hibernate的配置工做,在实际开发中,更多地采用XML格式的配置文件。若两种配置文件同时存在且都有相同的配置信息,则hibernate.cfg.xml中的配置会覆盖掉hibernate.properties中的配置,这其中的缘由结合代码来解释。看以下代码:

[java]  view plain  copy
  1. Configuration cfg=new Configuration().configure();  
这是建立Configuration实例并读取配置文件的代码。

  • 当执行new Configuration()方法时,Hibernate会在classpath的根目录下查找hibernate.properties文件。若是找到了该文件,则全部的hibernate.*的属性被装载到Configuration对象中。
  • 当调用configure()方法时,Hibernate会在classpath根目录下查找hibernate.cfg.xml。若是找不到则抛出HibernateException。若是hibernate.cfg.xml中的某些属性和hibernate.properties中的重复了,则会覆盖。

(2)建立SessionFactory实例。

Configuration对象将配置信息存入SessionFactory的属性中,建立完SessionFactory实例,Configuration对象的使命就结束了,SessionFactory与Configuration之间的关联也断开了。SessionFactory充当数据源的代理,并负责建立Session对象。

  • SessionFactory实例是全局惟一的,它对应着应用程序中的数据源,一个数据源只须要一个SessionFactory实例,只有当应用中有多个数据源时,才为每一个数据源创建一个SessionFactory实例。
  • SessionFactory的实例是重量级的,建立和销毁都要消耗较多资源,所以只建立一次。
  • 经过SessionFactory能够得到多个Session实例。
  • SessionFactory是线程安全的,能够被多个线程共享。Session不是线程安全的,多个并发线程同时操做一个Session实例时会出现问题,一般使用ThreadLocal模式管理Session。

(3)建立Session实例,创建数据库链接。

SessionFactory能够有两种方式建立Session。

a)openSession()方法。此方法直接建立一个新的Session实例,使用完以后须要调用close方法手动关闭。

b)getCurrentSession()方法。此方法建立的Session实例会绑定到当前线程,在事务提交(commit)或回滚(rollback)后会自动关闭。使用此方法必须在hibernate.cfg.xml配置文件中添加以下配置:

[html]  view plain  copy
  1. <!-- 若是使用的是本地事务 -->  
  2. <propertynamepropertyname="hibernate.current_session_context_class">thread</property>  
  3. <!-- 若是使用的是全局事务 -->  
  4. <propertynamepropertyname="hibernate.current_session_context_class">jta</property>  

(4)建立Transaction实例,开始一个事务。

Hibernate的事务是对数据库底层事务的封装,在对Hibernate进行增、删、改操做的时候必须先建立一个Transaction对象,一个事务就是一个原子操做。

(5)利用Session的方法进行持久化操做。将实体对象持久化到数据库中。

(6)提交事务。

(7)关闭Session,断开与数据库的链接。