在Java Web程序中使用Hibernate与普通Java程序一样。本文中将使用Servlet和JSP结合Hibernate实现数据库表的增删改查操作。
Web程序中,hibernate.cfg.xml中必须配置current_session_context_class参数。如果使用JBoss等内置Hibernae的容器,参数值要配置为jta,其他容器(如Tomcat等)需要配置为thread。
1. 创建工程并搭建Hibernate框架
在MyEclipse中创建一个Web工程,工程名为hibernate_web,把MySQL数据库驱动包和JSTL需要的jar包复制到WebRoot/WEB-INF/lib目录下;然后使用MyEclipse向导把Hibernate的jar包导到工程中。关于搭建Hibernate框架,可以参考网上的教程,这里就不再介绍了。接着,使用Hibernate连接数据库,并通过数据库表自动生成数据库对应的实体类和实体类映射文件。所使用的数据库表是MySQL的bank数据库中的users表。
自动生成及修改的代码如下:
package com.cn.vo; /** * UsersVo entity. @author MyEclipse Persistence Tools */ public class UsersVo implements java.io.Serializable { // Fields private Integer id; private String name; private Integer age; private String tel; private String address; // Constructors /** default constructor */ public UsersVo() { } /** minimal constructor */ public UsersVo(Integer id) { this.id = id; } /** full constructor */ public UsersVo(Integer id, String name, Integer age, String tel, String address) { this.id = id; this.name = name; this.age = age; this.tel = tel; this.address = address; } // Property accessors public Integer getId() { return this.id; } public void setId(Integer id) { this.id = id; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public Integer getAge() { return this.age; } public void setAge(Integer age) { this.age = age; } public String getTel() { return this.tel; } public void setTel(String tel) { this.tel = tel; } public String getAddress() { return this.address; } public void setAddress(String address) { this.address = address; } }
UsersVo.hbm.xml
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping> <class name="com.cn.vo.UsersVo" table="users" catalog="bank"> <id name="id" type="java.lang.Integer"> <column name="id" /> <generator class="assigned" /> </id> <property name="name" type="java.lang.String"> <column name="name" length="20" /> </property> <property name="age" type="java.lang.Integer"> <column name="age" /> </property> <property name="tel" type="java.lang.String"> <column name="tel" length="20" /> </property> <property name="address" type="java.lang.String"> <column name="address" length="50" /> </property> </class> </hibernate-mapping>
hibernate.cfg.xml(修改)
<?xml version='1.0' encoding='gbk'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <!-- Generated by MyEclipse Hibernate Tools. --> <hibernate-configuration> <session-factory> <!-- 声明使用SQL语句是MySQL数据库的SQL语句(MySQL方言) --> <property name="dialect"> org.hibernate.dialect.MySQLDialect </property> <!-- 在控制台打印执行的SQL语句 --> <property name="show_sql">true</property> <!-- 指定Hibernate启动的时候自动更新表,如果不存在则创建 --> <property name="hbm2ddl.auto">update</property> <!-- 使用线程,防止遇到异常 --> <property name="current_session_context_class">thread</property> <!-- JDBC配置代码包括数据库驱动、用户名密码及连接地址 --> <property name="connection.url"> jdbc:mysql://localhost:3306/bank </property> <property name="connection.username">root</property> <property name="connection.password">1234</property> <property name="connection.driver_class"> com.mysql.jdbc.Driver </property> <property name="myeclipse.connection.profile"> com.mysql.jdbc.Driver </property> <!-- 指定Hibernate的映射文件 --> <mapping resource="com/cn/vo/UsersVo.hbm.xml" /> </session-factory> </hibernate-configuration>
HibernateSessionFactory.java
package com.cn.hibernate; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.cfg.Configuration; /** * Configures and provides access to Hibernate sessions, tied to the * current thread of execution. Follows the Thread Local Session * pattern, see {@link http://hibernate.org/42.html }. */ public class HibernateSessionFactory { /** * Location of hibernate.cfg.xml file. * Location should be on the classpath as Hibernate uses * #resourceAsStream style lookup for its configuration file. * The default classpath location of the hibernate config file is * in the default package. Use #setConfigFile() to update * the location of the configuration file for the current session. */ private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml"; private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>(); private static Configuration configuration = new Configuration(); private static org.hibernate.SessionFactory sessionFactory; private static String configFile = CONFIG_FILE_LOCATION; static { try { configuration.configure(configFile); sessionFactory = configuration.buildSessionFactory(); } catch (Exception e) { System.err .println("%%%% Error Creating SessionFactory %%%%"); e.printStackTrace(); } } private HibernateSessionFactory() { } /** * Returns the ThreadLocal Session instance. Lazy initialize * the <code>SessionFactory</code> if needed. * * @return Session * @throws HibernateException */ public static Session getSession() throws HibernateException { Session session = (Session) threadLocal.get(); if (session == null || !session.isOpen()) { if (sessionFactory == null) { rebuildSessionFactory(); } session = (sessionFactory != null) ? sessionFactory.openSession() : null; threadLocal.set(session); } return session; } /** * Rebuild hibernate session factory * */ public static void rebuildSessionFactory() { try { configuration.configure(configFile); sessionFactory = configuration.buildSessionFactory(); } catch (Exception e) { System.err .println("%%%% Error Creating SessionFactory %%%%"); e.printStackTrace(); } } /** * Close the single hibernate session instance. * * @throws HibernateException */ public static void closeSession() throws HibernateException { Session session = (Session) threadLocal.get(); threadLocal.set(null); if (session != null) { session.close(); } } /** * return session factory * */ public static org.hibernate.SessionFactory getSessionFactory() { return sessionFactory; } /** * return session factory * * session factory will be rebuilded in the next call */ public static void setConfigFile(String configFile) { HibernateSessionFactory.configFile = configFile; sessionFactory = null; } /** * return hibernate configuration * */ public static Configuration getConfiguration() { return configuration; } }
2. 编写数据持久层
为了使程序结构清晰,数据持久层独立出来,放在DAO层中,在DAO层的类中编写数据的增删修改查方法,通过这些方法操作数据。在使用时,只需要根据实际情况来调用DAO层中的方法就可以了。这个例子中,DAO层只有一个类,类名为HibernateDao,HibernateDao类的代码如下:
package com.cn.dao; import org.hibernate.HibernateException; import org.hibernate.Session; import java.util.List; import com.cn.hibernate.HibernateSessionFactory; import com.cn.vo.UsersVo; public class HibernateDao { //添加数据的方法 public void add(UsersVo usersVo){ //调用HibernateSessionFactory的会话 Session session = HibernateSessionFactory.getSession(); try { session.beginTransaction(); //开启事务 session.persist(usersVo); //将对象添加到数据库 session.getTransaction().commit(); //提交事务 } catch (Exception e) { session.getTransaction().rollback(); //回滚事务 } finally { session.close(); //关闭session } } //修改数据的方法 public void modifyUsers(UsersVo usersVo){ Session session = HibernateSessionFactory.getSession(); try { session.beginTransaction(); //开启事务 session.update(usersVo); //修改数据 session.getTransaction().commit(); //提交事务 } catch (Exception e) { session.getTransaction().rollback(); //回滚事务 } finally { session.close(); //关闭session } } //从表中删除数据 public void delete(int id){ Session session = HibernateSessionFactory.getSession(); try { session.beginTransaction(); UsersVo users = (UsersVo)session.get(UsersVo.class, id); session.delete(users); session.getTransaction().commit(); } catch (Exception e) { session.getTransaction().rollback(); } finally { session.close(); } } //根据id查找数据 @SuppressWarnings("unchecked") public UsersVo queryUsersById(int id){ Session session = HibernateSessionFactory.getSession(); UsersVo users = (UsersVo)session.get(UsersVo.class, id); return users; } //查找多条数据 @SuppressWarnings("unchecked") public List<UsersVo> showlist(String hql){ Session session = HibernateSessionFactory.getSession(); try { session.beginTransaction(); return session.createQuery(hql).list(); //使用HQL查询结果,返回List对象 } catch (Exception e) { session.getTransaction().rollback(); } finally { session.getTransaction().commit(); session.close(); } return null; } }
该类中接受UsersVo类,Hibernate能够判断实体类的类型,决定操作哪个数据表。HibernateDao封装了最基本的CURD操作。