Hibernate是什么?
- Hibernate是一个框架(framework);
- Hibernate是一个ORM框架(Object Relation Mapping,对象关系映射);
- Hibernate处于项目的持久层(故也称之为持久层框架);(持久的意思就是把对象的信息保存到数据库或者是文件中)
- Hibernate实际上就是对JDBC进行了轻量级封装;
- Hibernate的基础还是Java的反射机制。
总结:Hibernate是对JDBC进行轻量级封装的ORM框架,充当项目的持久层。
Hibernate的好处
- 引入Hibernate可以使工作人员角色细化,让程序员更关心业务流程。让数据库人员关注数据库相关的各种操作;
- 分层更清晰,耦合性更小;
- 通用性强:可以更轻松的从一个数据库平台转移到别的平台;
- 对象化:把关系型数据库变成了Java的对象,更加方便操作;
- 性能保证:Hibernate可能按不同的数据库,处理不同的操作时用最优化的SQL语句,不用我们去想;
- 增加了程序的鲁棒性。
快速入门案例
Hibernate可以用在J2SE项目中,也可以用在J2EE项目中。(Struts是Web层框架,只能用在J2EE项目中)
开发流程:
1. 创建一个项目
2. 引入Hibernate的开发包
3. 开发Hibernate有三种方式:
(1)由Domain Object -> mapping -> db (官方推荐)
(2)由DB开始,用工具生成mapping和Domain Object (使用较多)
(3)由映射文件开始
4. 我们使用第二种方式开发,使用MySQL数据库,先创建employee表
CREATE TABLE employee (
id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY(id),
NAME VARCHAR (64) NOT NULL,
email VARCHAR (64) NOT NULL,
hiredate date NOT NULL
);
5. 开发domain对象和对象关系映射文件
对象关系文件:用于指定domain对象和表的映射关系,该文件的取名有要遵循一定的规范:domain对象.hbm.xml,一般放在和domian对象同一个文件夹下(即同一个包下)
domain对象的要求如下:
- (1) domain对象应该和一张表对应
- (2) 一般我们放在com.xxx.domain包下
- (3) domain需要一个主键属性(用于标识一个domain对象)
- (4) 除了主键属性外,它应当还有其他属性,属性的访问权限为private
- (5) 提供setter和getter方法
- (6) 应当有一个无参的构造方法(hibernate反射)
domain对象如下:
public class Employee {
private Integer id;
private String name;
private String email;
private Date hiredate;
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 String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getHiredate() {
return hiredate;
}
public void setHiredate(Date hiredate) {
this.hiredate = hiredate;
}
}
配置文件如下:
<?xml version="1.0" encoding="utf-8" ?>
<!--XML文件需要DTD文件来规定格式-->
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/xsd/hibernate-mapping-3.0.dtd">
<!--package用于指定映射domain对象所在的包-->
<hibernate-mapping package="com.gavin.domain">
<!--name用于指定映射的domain对象,table用于指定数据库中的表-->
<class name="Employee" table="employee">
<!--id元素用于指定domain对象中与表对应的主键属性,column用于指定表中的主键属性-->
<!--当然一般我们的命名是一致的,这里都是id-->
<id name="id" column="id" type="java.lang.Integer"/>
<!--对其他属性还要配置-->
<!--指定属性name,是String类型的,其对应表中的列为name,并且不允许为空-->
<property name="name" type="java.lang.String">
<column name="name" not-null="false"/>
</property>
<property name="email" type="java.lang.String">
<column name="email" not-null="false"/>
</property>
<property name="hiredate" type="java.util.Date">
<column name="hiredate" not-null="false"/>
</property>
</class>
</hibernate-mapping>
6. 手动配置我们的hibernate.cfg.xml文件,该文件用于配置连接数据库的类型,driver,用户名,密码,url等等,同时还要管理对象关系映射文件。该文件的名称我们一般不修改。
hibernate.cfg.xml配置文件如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!--hibernate设计者给我们提供了一些常用设置的配置-->
<!--show_sql可以让Hibernate输出SQL语句-->
<property name="show_sql">true</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3333/hibernate</property>
<property name="connection.username">root</property>
<property name="connection.password">your_password</property>
<!--配置dialect方言,明确告诉Hibernate现在连接的是哪种数据库-->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 下面这个配置指定Hibernate自动帮我们创建表(如果数据库中没有该表的话)。-->
<!--create表示每次使用都创建新表,如果存在表,则删除过再创建-->
<!--update则表示如果表结构有变化,则删除后创建新表,如果没有,则不创建新表-->
<!-- <property name="hbm2ddl.auto">create</property> -->
<!--mapping用于指定对象关系映射文件-->
<mapping resource="com/gavin/domain/Employee.hbm.xml"/>
</session-factory>
</hibernate-configuration>
7. 测试文件TestMain.java
package com.gavin.view;
import com.gavin.domain.Employee;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import java.util.Date;
public class TestMain {
public static void main(String[] args) {
addEmployee();
}
/**
* 向数据库中添加一个Employee对象
*/
public static void addEmployee() {
// 我们使用Hibernate完成CRUD操作
// 这里我们只见对象,不见表了;也就是说,我们不关心表了,对表的操作由Hibernate接管了
// 我们不使用service,直接测试
// 1.创建Configuration,并调用configure方法读取配置文件完成初始化,
// 默认的文件名为hibernate.cfg.xml,故可以不写文件名
Configuration configuration = new Configuration().configure("hibernate.cfg.xml");
// 2.创建SessionFactory,这是一个会话工厂,是一个重量级的类
SessionFactory sessionFactory = configuration.buildSessionFactory();
// 3.创建一个会话,相当于JDBC中的Connection
Session session = sessionFactory.openSession();
/*对于Hibernate而言,要求程序在进行增加,删除,修改的时候使用事务提交*/
Transaction transaction = session.beginTransaction();
// 4.添加一个Employee
Employee employee = new Employee();
employee.setName("Gavin");
employee.setEmail("gavin@163.com");
employee.setHiredate(new Date());
// 之前的插入是insert语句,现在不用了
// 直接调用session.save(),就可以将Employee对象插入数据库
session.save(employee); // save employee 就是持久化该对象(把数据保存到了数据库中)
transaction.commit();
session.close();
}
}
运行上述测试文件,Hibernate会向数据库中插入一条数据。由于我们配置Hibernate的时候,设置了show_sql
属性为true
,所以控制台会输出被Hibernate执行的SQL语句。
下图展示了在运行测试代码前后查询数据库的结果。
我们的目录结构如下:
更多的测试
1. SessionFactory是一个重量级的类,所以应该保证其是单态的。所以将其封装起来。如下:
package com.gavin.util;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
* 单例模式
*
* 在使用Hibernate开发项目的时候,一定保证只有一个SessionFactory,
* 原则:理论上是一个数据库对应一个SessionFactory,项目中用了两个数据库,则可以存在两个SessionFactory
*/
final public class MySessionFactory {
private static SessionFactory sessionFactory;
static{
sessionFactory = new Configuration().configure().buildSessionFactory();
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
private MySessionFactory(){}
}
2. 此时我们再测试对Employee的修改,编写updateEmployee
方法并调用执行。
public static void main(String[] args) {
// addEmployee();
updateEmployee();
}
/**
* 修改Employee
*/
public static void updateEmployee() {
// 获取一个会话
Session session = MySessionFactory.getSessionFactory().openSession();
// 获取要修改的对象,再修改
Transaction transaction = session.beginTransaction();
// load是通过主键属性获取对象实例 <--> 与表的记录对应
Employee employee = session.load(Employee.class, 1);
// 下面这句话会导致一个update语句产生
employee.setEmail("gavin_update@163.com");
transaction.commit();
session.close();
}
执行成功之后,数据库中的数据如下:
可以看到,数据库中的数据已经被修改了。
3. 同样的我们可以测试删除。
public static void main(String[] args) {
// addEmployee();
// updateEmployee();
delectEmployee();
}
public static void delectEmployee() {
// 获取一个会话
Session session = MySessionFactory.getSessionFactory().openSession();
// 删除,先获取该雇员,然后再删除
Transaction transaction = session.beginTransaction();
Employee employee = session.load(Employee.class, 1);
session.delete(employee);
transaction.commit();
session.close();
}
4. 查询的功能之后再作介绍。我们已经使用了session.load()
方法来获取一个对象,但是查询是多样化的,并不一定非要通过id
号来查询,而且有更多的查询需求比如分页等等,后面会重点介绍HQL
语句。
使用工具(IDEA)自动生成domain对象和hbm配置文件
前面提到,开发Hibernate有三种方式,前面的示例我们使用了第二种开发方式,即:由DB开始,用工具生成mapping和Domain Object (使用较多)
。
在前面的示例中,我们都是通过手动地编写代码和配置文件,其实这些步骤完全可以由工具帮我们完成。
MyEclipse中有这样的操作,同样IDEA也是有的。下面介绍一下在IDEA里面的操作。
1. 首先目录结构是下面这样的,我们将原来的domain对象和配置文件先备份在pojo
包中。同时删除hibernate.cfg.xml
文件中的mapping
配置(这个配置待会儿工具也会自动帮我们加上)。
在Project框下面有Persistence工具框,这就是我们操作Hibernate工具的地方。
2. 首先我们要配置一下数据库
在跳出来的对话框中设置数据库连接的参数,IP,用户名和密码等。
3. 右键HibernateTest
,依次选择Generate Persistence Mapping
和 By Database Scheme
4. 在跳出来的对话框中进行设置,如下:
5. 上述操作完成之后,我们可以在domain包下看到生成的Employee
对象和Employee.hbm.xml
关系映射文件。
这时我们再次测试TestMain
,发现没有任何异常。