一、什么是ORM?
ORM,即Object Relational Mapping。我们知道,利用面向对象的思想编写的数据库应用程序最终都是把对象信息保存在关系型数据库中,于是需要编写与底层数据库相关的SQL语句,显然这与面向对象的思想格格不入。
编写大量底层SQL语句不好之处:
1.不同数据库使用的SQL语法略有不同。比如:PL/SQL与T-SQL。
2.程序过分依赖SQL对程序的移植与扩展,维护等带来很大的麻烦。
使用ORM框架技术就可以彻底抛弃SQL语句,使我们完全使用面向对象的思想开发软件。
二、Hibernate简介
Hibernate是Java领域一款开源的ORM框架。它对JDBC进行了非常轻量级的对象封装,也就说Hibernate最终还是通过JDBC进行数据库的操作。Hibernate在项目中扮演持久化层的角色,将业务逻辑层中的对象数据保存到数据库表中。
三、第一个Hibernate例子
使用Hibernate之前要准备好Hibernate相关jar包。Hibernate jar包
创建Hibernate项目主要步骤:
1.创建Hibernate配置文件
2.创建持久化类
3.创建对象-关系映射文件
4.通过Hibernate API编写访问数据库的代码
--------------------------------------------------------------------------------------------------------------------------------------------
下面开始编写第一个Hibernate例子。
① 创建项目HibernateDemo,并导入Hibernate相关jar包,mysql驱动jar包,Junit jar包。
② 在src下创建Hibernate配置文件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="hibernate.connection.username">root</property> <!-- 数据库密码 --> <property name="hibernate.connection.password">botao521</property> <!-- 数据库链接 --> <property name="hibernate.connection.url">jdbc:mysql://localhost/hibernate_demo?user=root&password=botao521&unicode=true&characterEncodeing=utf-8</property> <!-- 数据库驱动 --> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <!-- 数据库方言 --> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <!-- 在控制台中输出sql --> <property name="show_sql">true</property> <!-- 格式化控制台中的sql --> <property name="format_sql">true</property> <!-- hbm2ddl.auto的作用为:自动创建/更新/验证数据库表结构 有以下值: create: 表示启动的时候先drop,再create create-drop: 也表示创建,只不过再系统关闭前执行一下drop update: 这个操作启动的时候会去检查schema是否一致,如果不一致会做scheme更新 validate: 启动时验证现有schema与你配置的hibernate是否一致,如果不一致就抛出异常,并不做更新 --> <property name="hbm2ddl.auto">create</property> <!-- 引入对象-关系映射文件 --> <mapping resource="com/cbt/bean/Student.hbm.xml" /> </session-factory> </hibernate-configuration>
③ 创建持久化类Student.java
package com.cbt.bean;
import java.util.Date;
/**
* 学生类
* @author caobotao
*/
public class Student {
private int sid; //学号
private String sname; //姓名
private String gender; //性别
private Date birthday; //出生日期
private String address;//地址
public Student(){}
public Student(int sid, String sname, String gender, Date birthday,
String address) {
this.sid = sid;
this.sname = sname;
this.gender = gender;
this.birthday = birthday;
this.address = address;
}
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
④ 创建对象-关系映射文件Student.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <!-- JavaBean与对应的表名 --> <class name="com.cbt.bean.Student" table="STUDENT"> <!-- 主键 --> <id name="sid" type="int"> <column name="SID" /> <generator class="assigned" /> </id> <!-- 字段 --> <property name="sname" type="java.lang.String"> <column name="SNAME" /> </property> <!-- 字段 --> <property name="gender" type="java.lang.String"> <column name="GENDER" /> </property> <!-- 字段 --> <property name="birthday" type="java.util.Date"> <column name="BIRTHDAY" /> </property> <!-- 字段 --> <property name="address" type="java.lang.String"> <column name="ADDRESS" /> </property> </class> </hibernate-mapping>
⑤ 在hibernate.cfg.xml中引入Student.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> ...... <!-- 引入对象-关系映射文件 --> <mapping resource="com/cbt/bean/Student.hbm.xml" /> </session-factory> </hibernate-configuration>
⑥ 在mysql中创建数据库 hibernate_demo
create database hibernate_demo;
⑦ 通过Hibernate API访问操作数据库
1> 创建配置对象
Configuration config = new Configuration().configure();
2> 创建服务注册对象
ServiceRegistry service = new ServiceRegistryBuilder().applySettings(config.getProperties()).buildServiceRegistry();
3> 创建会话工厂对象
sessionFactory = config.buildSessionFactory(service);
4> 打开会话
session = sessionFactory.openSession();
5> 开启事务
transaction = session.beginTransaction();
使用Junit编写测试类StudentTest.java
import java.util.Date; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.cbt.bean.Student; @SuppressWarnings("deprecation") public class StudentTest { private SessionFactory sessionFactory; private Session session; private Transaction transaction; @Before public void before(){ //创建配置对象 Configuration config = new Configuration().configure(); //创建服务注册对象 ServiceRegistry service = new ServiceRegistryBuilder().applySettings(config.getProperties()).buildServiceRegistry(); //创建会话工厂对象 sessionFactory = config.buildSessionFactory(service); //创建会话对象 session = sessionFactory.openSession(); //开启事务 transaction = session.beginTransaction(); } @After public void after(){ transaction.commit(); //提交事务 session.close(); //关闭会话 sessionFactory.close(); //关闭会话工厂 } @Test public void testSaveStudent() { //创建学生对象 Student s = new Student(1,"张三","男",new Date(),"武当山"); /* * 由于hibernate.cfg.xml中配置的hbm2ddl.auto值为'Create',所以执行save * 方法会检查数据库中是否有student表,没有的话会创建此表,并将s对象保存进去 */ session.save(s); } }
运行测试用例,会发现控制台打印出下列SQL语句,在数据库中有一个STUDENT表被创建,以及对应的一条学生记录被插入。
Hibernate:
drop table if exists STUDENT
Hibernate:
create table STUDENT (
SID integer not null,
SNAME varchar(255),
GENDER varchar(255),
BIRTHDAY datetime,
ADDRESS varchar(255),
primary key (SID)
)
Hibernate:
insert
into
STUDENT
(SNAME, GENDER, BIRTHDAY, ADDRESS, SID)
values
(?, ?, ?, ?, ?)
至此第一个Hibernate例子结束。
源码下载:HibernateDemo.zip
四、Hibernate执行流程
1> 获取Configuration对象,目的是读取hibernate.cfg.xml配置文件
2> 获取SessionFactory对象,目的是读取hibernate.cfg.xml中配置的对象-关系配置文件
3> 获取Session对象,相当于获取一个Connection对象,可以持久化操作,需要先开启事务
4> 提交事务,完成持久化操作,然后关闭session
五、Session简介
Hibernate是对JDBC进行了封装,它不建议使用JDBC的Connection操作数据库,而是通过Session操作数据库。Session可以简单的理解为操作数据库的对象。Session与Connection是多对一的关系,一个Connection不同时刻可以供多个Session 使用。
使用Session进行持久化操作需要调用Session的各种方法,如:save(),update(),delete(),createQuery()等。
获取Session的方式:
① 使用SessionFactory的openSession()方法
② 使用SessionFactory的getCurrentSession()方法
使用getCurrentSession需要在hibernate.cfg.xml文件中进行配置:
如果是本地事务(JDBC事务):
<property name="hibernate.current_session_context_class">thread</property>
如果是全局事务(jta事务):
<property name="hibernate.current_session_context_class">jta</property>
openSession()与getCurrentSession()的区别:
① getCurrentSession()在事务提交或回滚后会自动关闭,而openSession()需要手动关闭,否则多次之后会造成连接池溢出。
② openSession()每次创建新的session对象,getCurrentSession()返回同一个session对象。