JAVA Hibernate DAY01
1 Hibernate基本使用
1.1 问题
使用Hibernate实现对员工表的增、删、改、查。
1.2 方案
Hibernate使用步骤:
- 导入Hibernate包,以及数据库驱动包。
- 引入Hibernate主配置文件hibernate.cfg.xml。
- 创建实体类。
- 创建映射关系文件。
- 使用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开发包,以及数据库驱动包,完成后项目的包结构如下图:
图-1
步骤三:引入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,用于封装员工表的数据,代码如下:
- packagecom.tarena.entity;
- importjava.sql.Date;
- importjava.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() {
- returnlastLoginTime;
- }
- 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>
注意,先不要配置布尔型属性marry,后面会单独讲解布尔型属性的配置及使用。
步骤六:声明映射关系文件
在主配置文件hibernate.cfg.xml中,声明映射关系文件Emp.hbm.xml,代码如下:
- <?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>
-
- <!--声明映射关系文件 -->
- <mapping resource="com/tarena/entity/Emp.hbm.xml" />
- </session-factory>
- </hibernate-configuration>
步骤七:创建Session工具类
创建HibernateUtil工具类,用于创建Session对象,代码如下:
- packagecom.tarena.util;
- importorg.hibernate.Session;
- importorg.hibernate.SessionFactory;
- importorg.hibernate.cfg.Configuration;
- public class HibernateUtil {
- private static SessionFactorysessionFactory;
-
- static {
- // 加载Hibernate主配置文件
- Configuration conf = new Configuration();
- conf.configure("/hibernate.cfg.xml");
- sessionFactory = conf.buildSessionFactory();
- }
- /**
- * 创建session
- */
- public static Session getSession() {
- returnsessionFactory.openSession();
- }
-
- public static void main(String[] args) {
- System.out.println(getSession());
- }
- }
步骤八:练习使用Hibernate对员工表进行增删改查
创建包com.tarena.test,并在该包下创建一个JUNIT测试类,并在类中使用Hibernate写出对EMP表的增删改查的方法,代码如下:
- packagecom.tarena.test;
- importjava.sql.Date;
- importjava.sql.Timestamp;
- importjava.util.List;
- importorg.hibernate.HibernateException;
- importorg.hibernate.Query;
- importorg.hibernate.Session;
- importorg.hibernate.Transaction;
- importorg.junit.Test;
- importcom.tarena.entity.Emp;
- importcom.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();
- Empemp = (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();
- // 查询要修改的数据
- Empemp = (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();
- Empemp = (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();
- }
- }
步骤九:测试
以JUNIT方式运行上面的每一个测试方法,并观察控制台输出的SQL。
1.4 完整代码
以下是本案例的完整代码。
其中建表语句完整代码如下:
主配置文件hibernate.cfg.xml完整代码如下:
实体类Emp.java完整代码如下:
映射关系文件Emp.hbm.xml完整代码如下:
HibernateUtil完整代码如下:
JUNIT测试类代码如下:
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">
- <!--配置主键属性和字段的关系 -->
- <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>
步骤二:测试
再次以JUNIT方式执行测试代码中的每个方法,看控制台输出结果是否正确。
2.4 完整代码
以下是本案例的完整代码。
其中Emp.hbm.xml完整代码如下:
其他代码不变,此处不再重复。
3 在NETCTOSS中引入Hibernate
3.1 问题
将Hibernate框架引入到NETCTOSS。
3.2 方案
将Hibernate框架引入到NETCTOSS,以保证在项目中可以使用Hibernate来进行数据库访问。根据Hibernate的使用步骤,我们需要在项目中引入Hibernate开发包、主配置文件,并创建HibernateUtil工具类。
3.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:导包
在NETCTOSS项目中,导入Hibernate开发包,导入后项目的包结构如下图:
图-2
步骤二:引入主配置文件
将Hibernate主配置文件引入到项目中,放于src根路径下,该文件可以从HibernateDay01项目中直接复制过来,并将声明映射关系文件部分代码去掉,代码如下:
- <?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>
步骤三:创建HibernateUtil工具类
在com.netctoss.util包下,创建HibernateUtil工具类,该类可以直接从HibernateDay01项目中复制过来,代码如下:
- packagecom.netctoss.util;
- importorg.hibernate.Session;
- importorg.hibernate.SessionFactory;
- importorg.hibernate.cfg.Configuration;
- public class HibernateUtil {
- private static SessionFactorysessionFactory;
-
- static {
- // 加载Hibernate主配置文件
- Configuration conf = new Configuration();
- conf.configure("/hibernate.cfg.xml");
- sessionFactory = conf.buildSessionFactory();
- }
- /**
- * 创建session
- */
- public static Session getSession() {
- returnsessionFactory.openSession();
- }
-
- public static void main(String[] args) {
- System.out.println(getSession());
- }
- }
3.4 完整代码
下面是本案例的完整代码。
其中主配置文件完整代码如下:
HibernateUtil工具类完整代码如下:
4 使用Hibernate重构资费DAO
4.1 问题
使用Hibernate重构资费DAO的实现类。
4.2 方案
使用Hibernate的增删改查API,重构资费DAO的实现类。
4.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:创建资费的映射关系文件
在com.netctoss.entity包下,创建资费的映射关系文件,名为Cost.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.netctoss.entity.Cost" table="cost">
- <id name="id" type="integer" column="id">
- <!--用来指明主键的生成方式 -->
- <generator class="sequence">
- <param name="sequence">cost_seq</param>
- </generator>
- </id>
-
- <property name="name"
- type="string" column="name" />
- <property name="baseDuration"
- type="integer" column="base_duration" />
- <property name="baseCost"
- type="double" column="base_cost" />
- <property name="unitCost"
- type="double" column="unit_cost" />
- <property name="status"
- type="string" column="status" />
- <property name="descr"
- type="string" column="descr" />
- <property name="createTime"
- type="date" column="creatime" />
- <property name="startTime"
- type="date" column="startime" />
- <property name="costType"
- type="string" column="cost_type" />
- </class>
- </hibernate-mapping>
步骤二:声明映射关系文件
在hibernate.cfg.xml中声明映射关系文件,代码如下:
- <?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>
-
- <!--在配置文件中关联映射文件 -->
- <mapping resource="com/netctoss/entity/Cost.hbm.xml" />
- </session-factory>
- </hibernate-configuration>
步骤三:使用Hibernate重构CostDaoImpl
使用HibernateUtil的增删改查API,来重构CostDaoImpl,代码如下:
- packagecom.netctoss.dao;
- importjava.util.List;
- importorg.hibernate.HibernateException;
- importorg.hibernate.Query;
- importorg.hibernate.Session;
- importorg.hibernate.Transaction;
- importcom.netctoss.entity.Cost;
- importcom.netctoss.util.HibernateUtil;
- /**
- * 当前阶段学习重点是Struts2,对于DAO的实现就模拟实现了。
- * 同学们可以使用JDBC/MyBatis自行实现该DAO。
- */
- public class CostDaoImpl implements ICostDao {
- @Override
- public List<Cost>findAll() {
- String hql = "from Cost";
- Session session = HibernateUtil.getSession();
- Query query = session.createQuery(hql);
- List<Cost> list = query.list();
- session.close();
- return list;
- }
- @Override
- public void delete(int id) {
- Cost cost = new Cost();
- cost.setId(id);
- Session session = HibernateUtil.getSession();
- Transaction ts = session.beginTransaction();
- try {
- session.delete(cost);
- ts.commit();
- } catch (HibernateException e) {
- e.printStackTrace();
- ts.rollback();
- } finally {
- session.close();
- }
- }
- @Override
- public Cost findByName(String name) {
- // 模拟根据名称查询资费数据,假设资费表中只有一条名为tarena的数据
- if("tarena".equals(name)) {
- Cost c = new Cost();
- c.setId(97);
- c.setName("tarena");
- c.setBaseDuration(99);
- c.setBaseCost(9.9);
- c.setUnitCost(0.9);
- c.setDescr("tarena套餐");
- c.setStatus("0");
- c.setCostType("2");
- return c;
- }
- return null;
- }
- @Override
- public Cost findById(int id) {
- Session session = HibernateUtil.getSession();
- Cost cost = (Cost) session.get(Cost.class, id);
- session.close();
- return cost;
- }
- }
注:目前我们还没学习有条件的查询,因此先不重构findByName方法。
步骤四:测试
重新部署项目,并重启tomcat,访问资费模块,对其各功能进行测试。
4.4 完整代码
下面是本案例的完整代码。
其中映射关系文件完整代码如下:
主配置文件完整代码如下:
CostDaoImpl完整代码如下:http://pdf7.tarena.com.cn/tts8_source/ttsPage/JAVA/JSD_V04/HIBERNATE/DAY01/CASE/01/index.html