Hibernate运用

1 Hibernate基本使用

1.1 问题

使用Hibernate实现对员工表的增、删、改、查。

 

1.2 方案

Hibernate使用步骤:

  1. 导入Hibernate包,以及数据库驱动包。
  2. 引入Hibernate主配置文件hibernate.cfg.xml。
  3. 创建实体类。
  4. 创建映射关系文件。
  5. 使用Hibernate常用API执行增删改查操作。

1.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:准备工作

创建员工表EMP,建表语句如下:

CREATE TABLE EMP(

  ID                   NUMBER(4) CONSTRAINT EMP_ID_PK PRIMARY KEY,

  NAME         VARCHAR(50)  NOT NULL,

  AGE          NUMBER(11),

  SALARY               NUMBER(7,2),

  MARRY                CHAR(1),

  BIRTHDAY     DATE,

  LAST_LOGIN_TIME      DATE

  );

CREATE SEQUENCE emp_seq;

创建一个WEB项目,名为HibernateDay01。

步骤二:导包

导入Hibernate开发包和数据库驱动包,完成后项目的包结构如下图

Antlr-2.7.6.jar

Asm-attrs.jar

Asm.jar

C3p0-0.9.1.jar

Cglib-2.1.3.jar

Commons-collections-2.1.1.jar

Commons-logging-1.0.4.jar

Dom4j-1.6.1.jar

Freemarker.jar

Hibernate-tools.jar

Hibernate3.jar

Jta.jar

Junit-4.4.jar

Log4j-1.2.11.jar

Ojdbc6.jar

 

步骤三:引入Hibernate主配置文件

将Hibernate主配置文件hibernate.cfg.xml复制到项目中,放在src根路径下。并在主配置文件中配置好数据库连接信息,以及Hibernate框架参数,代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
               "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
               "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
        <session-factory>
               <!-- 数据库连接信息,根据自己的数据库进行配置 -->
               <property name="connection.url">
                       jdbc:oracle:thin:@localhost:1521:xe
               </property>
               <property name="connection.username">lhh</property>
               <property name="connection.password">123456</property>
               <property name="connection.driver_class">
                       oracle.jdbc.OracleDriver
               </property>
               
               <!-- Hibernate配置信息 -->
               <!-- dialect方言,用于配置生成针对哪个数据库的SQL语句 -->
               <property name="dialect">
                       <!-- 方言类,Hibernate提供的,用于封装某种特定数据库的方言 -->
                       org.hibernate.dialect.OracleDialect
               </property>
               <!-- Hibernate生成的SQL是否输出到控制台 -->
               <property name="show_sql">true</property>
               <!-- 将SQL输出时是否格式化 -->
               <property name="format_sql">true</property>
               
        </session-factory>
</hibernate-configuration>

步骤四:创建实体类

创建包com.tarena.entity,并在该包下创建员工表对应的实体类Emp.java,用于封装员工表的数据,代码如下:

package com.tarena.entity;
 
import java.sql.Date;
import java.sql.Timestamp;
 
public class Emp {
 
        private Integer id;
        private String name;
        private Integer age;
        private Double salary;
        private Boolean marry;
        private Date birthday;
        private Timestamp lastLoginTime;
 
        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 Integer getAge() {
               return age;
        }
        public void setAge(Integer age) {
               this.age = age;
        }
        public Double getSalary() {
               return salary;
        }
        public void setSalary(Double salary) {
               this.salary = salary;
        }
        public Boolean getMarry() {
               return marry;
        }
        public void setMarry(Boolean marry) {
               this.marry = marry;
        }
        public Date getBirthday() {
               return birthday;
        }
        public void setBirthday(Date birthday) {
               this.birthday = birthday;
        }
        public Timestamp getLastLoginTime() {
               return lastLoginTime;
        }
        public void setLastLoginTime(Timestamp lastLoginTime) {
               this.lastLoginTime = lastLoginTime;
        }
}

步骤五:创建映射关系文件

在com.tarena.entity包下,创建员工实体类的映射关系文件,名为Emp.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">
<hibernate-mapping>
        <!-- 配置实体类和表的关系 -->
        <class name="com.tarena.entity.Emp" table="emp">
               <!-- 配置主键属性和字段的关系 -->
               <id name="id" type="java.lang.Integer" column="id">
                       <!-- 用来指明主键的生成方式 -->
                       <generator class="sequence">
                               <!-- 指定用于生成主键的sequence -->
                              <param name="sequence">emp_seq</param>
                       </generator>
               </id>
               
               <!-- 配置实体类中属性与表中字段的关系 -->
               <property name="name" 
                       type="java.lang.String" column="name"/>
               <property name="age" 
                       type="java.lang.Integer" column="age"/>
               <property name="salary" 
                       type="java.lang.Double" column="salary"/>
               <property name="birthday" 
                       type="java.sql.Date" column="birthday"/>
               <property name="lastLoginTime" 
                       type="java.sql.Timestamp" column="last_login_time"/>
        </class>
</hibernate-mapping>
<!DOCTYPE hibernate-configuration PUBLIC
               "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
               "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
        <session-factory>
               <!-- 数据库连接信息,根据自己的数据库进行配置 -->
               <property name="connection.url">
                       jdbc:oracle:thin:@localhost:1521:xe
               </property>
               <property name="connection.username">lhh</property>
               <property name="connection.password">123456</property>
               <property name="connection.driver_class">
                       oracle.jdbc.OracleDriver
               </property>
               
               <!-- Hibernate配置信息 -->
               <!-- dialect方言,用于配置生成针对哪个数据库的SQL语句 -->
               <property name="dialect">
                       <!-- 方言类,Hibernate提供的,用于封装某种特定数据库的方言 -->
                       org.hibernate.dialect.OracleDialect
               </property>
               <!-- Hibernate生成的SQL是否输出到控制台 -->
               <property name="show_sql">true</property>
               <!-- 将SQL输出时是否格式化 -->
               <property name="format_sql">true</property>
               
#cold_bold             <!-- 声明映射关系文件 -->
#cold_bold             <mapping resource="com/tarena/entity/Emp.hbm.xml" />
        </session-factory>
</hibernate-configuration>
 

步骤七:创建Session工具类

创建HibernateUtil工具类,用于创建Session对象,代码如下:

package com.tarena.util;

package com.tarena.util;
 
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
 
public class HibernateUtil {
        private static SessionFactory sessionFactory; static {
               // 加载Hibernate主配置文件
               Configuration conf = new Configuration();
               conf.configure("/hibernate.cfg.xml");
               sessionFactory = conf.buildSessionFactory();
        }
        /**
         * 创建session
         */
        public static Session getSession() {
               return sessionFactory.openSession();
        }
        public static void main(String[] args) {
               System.out.println(getSession());
        }
}
 
 

步骤八:练习使用Hibernate对员工表进行增删改查

创建包com.tarena.test,并在该包下创建一个JUNIT测试类,并在类中使用Hibernate写出对EMP表的增删改查的方法,代码如下:

package com.tarena.test;

 

import java.sql.Date;

import java.sql.Timestamp;

import java.util.List;

import org.hibernate.HibernateException;

import org.hibernate.Query;

import org.hibernate.Session;

import org.hibernate.Transaction;

import org.junit.Test;

import com.tarena.entity.Emp;

import com.tarena.util.HibernateUtil;

/**

 *      演示Hibernate的基本使用

 */

public class TestEmp {

        /**

         * 新增emp

         */

        @Test

        public void add() {

               // 模拟要新增的emp

               Emp e = new Emp();

               e.setName("ggg");

               e.setAge(29);

               e.setMarry(false);

               e.setSalary(8000.00);

               e.setBirthday(Date.valueOf("1983-10-20"));

               e.setLastLoginTime(

                       new Timestamp(System.currentTimeMillis()));

 

               // 获取session

               Session session = HibernateUtil.getSession();

               // 开启事务

               Transaction ts = session.beginTransaction();

               try {

                       // 执行新增

                       session.save(e);

                       // 提交事务

                       ts.commit();

               } catch (HibernateException e1) {

                       e1.printStackTrace();

                       // 回滚事务

                       ts.rollback();

               } finally {

                       session.close();

               }

        }

 

        /**

         * 根据ID查询emp

         */

        @Test

        public void findById() {

               Session session = HibernateUtil.getSession();

               Emp emp = (Emp) session.get(Emp.class, 201);

               System.out.println(emp.getName());

               System.out.println(emp.getBirthday());

               System.out.println(emp.getLastLoginTime());

               session.close();

        }

 

        /**

         * 修改emp

         */

        @Test

        public void update() {

               Session session = HibernateUtil.getSession();

               // 查询要修改的数据

               Emp emp = (Emp) session.get(Emp.class, 42);

               // 开启事务

               Transaction ts = session.beginTransaction();

               try {

                       // 模拟修改数据

                       emp.setName("ee");

                       emp.setAge(20);

                       // 执行修改

                       session.update(emp);

                       // 提交事务

                       ts.commit();

               } catch (HibernateException e) {

                       e.printStackTrace();

                       // 回滚事务

                       ts.rollback();

               } finally {

                       // 关闭连接

                       session.close();

               }

        }

 

        /**

         * 删除emp

         */

        @Test

        public void delete() {

               Session session = HibernateUtil.getSession();

               Emp emp = (Emp) session.get(Emp.class, 148);

               Transaction ts = session.beginTransaction();

               try {

                       session.delete(emp);

                       ts.commit();

               } catch (HibernateException e) {

                       e.printStackTrace();

                       ts.rollback();

               } finally {

                       session.close();

               }

        }

 

        /**

         * 查询全部emp

         */

        @Test

        public void findAll() {

               String hql = "from Emp";

               Session session = HibernateUtil.getSession();

               Query query = session.createQuery(hql);

               List<Emp> emps = query.list();

               for (Emp e : emps) {

                       System.out.println(e.getName());

               }

               session.close();

        }

 

}

 
 

2 Hibernate映射类型

2.1 问题

使用Hibernate预定义类型配置属性和字段的映射关系。

2.2 方案

将项目HibernateDay01中,Emp.hbm.xml里面每个属性的配置,其type用Hibernate预定义类型来重构。由于Hibernate预定义类型支持布尔值,因此在该配置文件中追加marry属性的配置。

2.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:重构Emp.hbm.xml

重构Emp.hbm.xml,将各个属性的type由Java类型改为Hibernate预定义类型,同时追加marry属性,并使用布尔型来配置该属性,代码如下:

<?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">
<hibernate-mapping>
        <!-- 配置实体类和表的关系 -->
        <class name="com.tarena.entity.Emp" table="emp">
               <!-- 配置主键属性和字段的关系 -->
#cold_bold             <id name="id" type="integer" column="id">
                       <!-- 用来指明主键的生成方式 -->
                       <generator class="sequence">
                               <!-- 指定用于生成主键的sequence -->
                               <param name="sequence">emp_seq</param>
                       </generator>
               </id>
               
               <!-- 配置实体类中属性与表中字段的关系 -->
#cold_bold             <property name="name" 
#cold_bold                     type="string" column="name"/>
#cold_bold             <property name="age" 
#cold_bold                     type="integer" column="age"/>
#cold_bold             <property name="salary" 
#cold_bold                     type="double" column="salary"/>
#cold_bold             <property name="birthday" 
#cold_bold                     type="date" column="birthday"/>
#cold_bold             <property name="lastLoginTime" 
#cold_bold                     type="timestamp" column="last_login_time"/>
#cold_bold             <property name="marry"
#cold_bold                     type="yes_no" column="marry"/>
        </class>
</hibernate-mapping>

步骤二:测试

再次以JUNIT方式执行测试代码中的每个方法,看控制台输出结果是否正确。

2.4 完整代码

以下是本案例的完整代码。

其中Emp.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">
<hibernate-mapping>
        <!-- 配置实体类和表的关系 -->
        <class name="com.tarena.entity.Emp" table="emp">
               <!-- 配置主键属性和字段的关系 -->
               <id name="id" type="integer" column="id">
                       <!-- 用来指明主键的生成方式 -->
                       <generator class="sequence">
                               <!-- 指定用于生成主键的sequence -->
                               <param name="sequence">emp_seq</param>
                       </generator>
               </id>
               
               <!-- 配置实体类中属性与表中字段的关系 -->
               <property name="name" 
                       type="string" column="name"/>
               <property name="age" 
                       type="integer" column="age"/>
               <property name="salary" 
                       type="double" column="salary"/>
               <property name="birthday" 
                       type="date" column="birthday"/>
               <property name="lastLoginTime" 
                       type="timestamp" column="last_login_time"/>
               <property name="marry"
                       type="yes_no" column="marry"/>
        </class>
</hibernate-mapping>
Hibernate预定义类型
整数:
Java.lang.Byte 类型   byte  数据库类型number(m)
Java.lang.Short类型   short       number(m)
Java.lang.Integer类型  integer    number(m)
Java.lang.Long类型  long   number(m)
Java.lang.Float   float   number(m,n)
Jva.lang.Double   double   number(m,n)
Java.lang.String   string   varchar
Java.sql.Date      date   date
Java.sql.Time     time   date 
Java.sql.Timestame   timestamp   date
Java.lang.Boolean   yes_no   char(1)
Java.lang.Boolean   true_false   char(1)
 
 
 

Struts与Hibernate整合导包

导入Hibernate开发包和数据库驱动包,完成后项目的包结构如下图

Antlr-2.7.6.jar

Asm-attrs.jar

Asm.jar

C3p0-0.9.1.jar

Cglib-2.1.3.jar

Commons-collections-2.1.1.jar

Commons-logging-1.0.4.jar

Dom4j-1.6.1.jar

Freemarker.jar

Hibernate-tools.jar

Hibernate3.jar

Jta.jar

Junit-4.4.jar

Log4j-1.2.11.jar

Ojdbc6.jar

 
 
 
Commons-fileupload-1.2.1.jar
Jstl.jar
Ognl-2.7.3.jar
Standard.jar
Struts2-core-2.1.8.jar
Struts2-json-plugin-2.1.8.jar
Xwork-core-2.1.6.jar
 
 

步骤三:使用Hibernate重构CostDaoImpl

使用HibernateUtil的增删改查API,来重构CostDaoImpl,代码如下:

copytextpop-up
1.package com.netctoss.dao;
2.    
3.  import java.util.List;
4.   
5.  import org.hibernate.HibernateException;
6.   
7.  import org.hibernate.Query;
8.   
9.  import org.hibernate.Session;
10. 
11.import org.hibernate.Transaction;
12. 
13.import com.netctoss.entity.Cost;
14. 
15.import com.netctoss.util.HibernateUtil;
16. 
17./**
18. 
19. *    当前阶段学习重点是Struts2,对于DAO的实现就模拟实现了。
20. 
21. *    同学们可以使用JDBC/MyBatis自行实现该DAO。
22. 
23. */
24. 
25.public class CostDaoImpl implements ICostDao {
26. 
27.    @Override
28. 
29.    public List<Cost> findAll() {
30. 
31.        String hql = "from Cost"; 
32.        Session session = HibernateUtil.getSession(); 
33.        Query query = session.createQuery(hql); 
34.        List<Cost> list = query.list(); 
35.        session.close(); 
36.        return list; 
37.    }
38. 
39.    @Override
40. 
41.    public void delete(int id) {
42. 
43.        Cost cost = new Cost(); 
44.        cost.setId(id); 
45. 
46.        Session session = HibernateUtil.getSession(); 
47.        Transaction ts = session.beginTransaction(); 
48.        try { 
49.            session.delete(cost); 
50.            ts.commit(); 
51.        } catch (HibernateException e) { 
52.            e.printStackTrace(); 
53.            ts.rollback(); 
54.        } finally { 
55.            session.close(); 
56.        } 
57.    }
59.    @Override
60. 
61.    public Cost findByName(String name) {
63.        // 模拟根据名称查询资费数据,假设资费表中只有一条名为tarena的数据
65.        if("tarena".equals(name)) {
67.            Cost c = new Cost();
69.            c.setId(97);
71.            c.setName("tarena");
73.            c.setBaseDuration(99);
75.            c.setBaseCost(9.9);
77.            c.setUnitCost(0.9);
79.            c.setDescr("tarena套餐");
81.            c.setStatus("0");
83.            c.setCostType("2");
85.            return c;
87.        }
89.        return null;
90. 
91.    }
93.    @Override
95.    public Cost findById(int id) {
97.        Session session = HibernateUtil.getSession(); 
98.        Cost cost = (Cost) session.get(Cost.class, id); 
99.        session.close(); 
100.         return cost; 
101.     }
103. }