1.Hibernate框架介绍
hibernate是数据持久化工具,也是一个开源代码的ORM解决方案。Hibernate内部封装了通过JDBC访问数据库的操作,向上层应用提供面向对象的数据访问API
2.Hibernate框架的优缺点
优点:
(1).hibernate功能强大,是java应用的关系型数据库之间的桥梁,较之JDBC方式操作数据库,代码量大大减少,提高持久化代码的开发速度,降低了维护成本
(2).支持面向对象的特征
(3).可移植性高,系统不会绑定某个特定的关系型数据库上,对于系统更换数据库,通常只需修改hibernate配置文件即可正常运行
(4).开源免费,具有可扩展性
缺点:
(1).不适合以数据为中心大量使用存储过程的应用
(2).大规模的批量插入,修改删除不适合用hibernate.
1.下载jar文件——>2.部署jar文件——>3.创建配置文件hibernate.cfg.xml——>4.创建持久化类和映射文件
(1).下载jar文件
官方网站是http://hibernate.org(也可以联系博主)
(2).部署jar文件(导包,省略)
(3).创建配置文件hibernate.cfg.xml
<!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>
<!-- 数据库连接 -->
<property name="connection.driver_class">
oracle.jdbc.driver.OracleDriver
</property>
<property name="connection.url">
jdbc:oracle:thin:@localhost:1521:orcl
</property>
<property name="connection.username">scott</property>
<property name="connection.password">Liujz0321</property>
<!-- 辅助参数 -->
<property name="show_sql">true</property>
<!-- 是否格式化 -->
<property name="format_sql">true</property>
<--每个数据库都有对应的方言以匹配平台特性-->
<property name="dialect">
org.hibernate.dialect.Oracle10gDialect
</property>
<property name="current_session_context_class">thread</property>
<property name="javax.persistence.validation.mode">none</property>
<!-- 映射信息 -->
<mapping resource="pojo/Dept.hbm.xml" />
<mapping resource="pojo/Emp.hbm.xml" />
</session-factory>
</hibernate-configuration>
(3).创建持久化类和映射文件
Dept类(部门表)
public class Dept {
private Short deptNo;
private String deptName;
private String location;
//省略get,set方法
}
Dept的映射文件(Dept.hbm.xml)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >
<hibernate-mapping>
<class name="pojo.Dept" table="`DEPT`" schema="scott"
dynamic-update="true">
<id name="deptNo" column="`DEPTNO`" type="java.lang.Short">
<generator class="increment" />
</id>
<property name="deptName" type="java.lang.String" column="`DNAME`" />
<property name="location" type="java.lang.String" column="`LOC`" />
</class>
</hibernate-mapping>
经验:表名或字段名是数据库关键字,或包含空格,建议使用反单引号(`);
在这里重点介绍一个generator节点:
id元素的子元素,用于指定主键的生成策略
class的取值有如下
class | 作用 |
---|---|
assigned | 主键由应用程序负责生成,无需hibernate参与,默认 |
increment | 对类型为long,short,int的主键,以自动增长的方式生成主键的值,主键按顺序递增1 |
identity | 对支持标识列的数据库,可使用主键生成策略生成自动增长主键,但在数据库中将相应的主键字段设置成标识列 |
sequence | 对支持Oracle,DB2等支持序列的数据库,可使用该主键生成策略自动增长主键,通过子元素param可穿入数据库中序列的名称 |
native | 根据底层数据库自行判断采用何种主键生成策略,即有使用的数据库生成主键的值 |
3.使用hibernate完成持久化操作
1.在项目开发中,通常使用工具类来管理SessionFactory 和Session
public class HibernateUtil {
private static Configuration configuration;
private final static SessionFactory sessionFactory;
static {
try {
configuration = new Configuration().configure();
sessionFactory = configuration.buildSessionFactory();
} catch (HibernateException e) {
throw new ExceptionInInitializerError(e);
}
}
private HibernateUtil() {
}
public static Session currentSession() {
return sessionFactory.getCurrentSession();
}
}
2.使用hibernate实现按主键查询
(1).DeptDao关键代码
public class DeptDao extends BaseDao {
// get加载(用于查询)
public Dept get(Serializable id) {
return (Dept) currentSession().get(Dept.class, id);
}
(2).业务层关键代码
public Dept findDeptById(Byte id) {
Transaction tx = null;
Dept dept = null;
try {
tx = HibernateUtil.currentSession().beginTransaction();
dept = deptDao.get(id);
tx.commit();
} catch (HibernateException e) {
e.printStackTrace();
if (tx != null) {
tx.rollback();
}
}
return dept;
}
(3)测试类
Dept dept=new DeptBiz().findDeptById(new Byte("10"));
System.out.println(dept.getDeptName());
使用Session的get()方法查询主键为10的部门信息,如果数据表中没有主键为10的数据,get()返回的是null,还有一种方法是load(),若加载数据不存在,则会抛出异常
load方法就不举例实现了,跟get方法查询时一致的
3.实现增删改操作
(1)保存: save(对象) //不举例实现了
(2)修改
DeptDao 的关键代码
// load加载(用于查询)
public Dept load(Serializable id) {
return (Dept) currentSession().load(Dept.class, id);
}
业务层的关键代码
// 修改用户
public void updateDept(Dept dept) {
Transaction tx = null;
try {
tx = deptDao.currentSession().beginTransaction();
Dept dept2 = deptDao.load(dept.getDeptNo());
dept2.setDeptName(dept.getLocation());
dept2.setLocation(dept.getLocation());
tx.commit();
} catch (HibernateException e) {
e.printStackTrace();
if (tx != null) {
tx.rollback();
}
}
}
测试方法
Dept dept=new Dept();
dept.setDeptNo(new Short("10"));
dept.setDeptName("质管部");
new DeptBiz().updateDept(dept);
在hibernate修改数据时,首先要加载对象,然后才可以修改对象的属性,最后提交事务。
3.删除 :跟修改类似,删除时也先加载数据,
注意:操作一定要在事务环境中完成
4.Hibernate中java对象的三种状态
1瞬时状态(Transient)
通过new创建对象后,对象并没有立即持久化
他并未与数据库发生任何关系,此时java对象的状态为瞬时状态,Session对与瞬时状态的对象一无所知,当对象不在被其他对象引用时他的数据也就丢失了,对象将按照垃圾回收机制处理
2持久状态(Persistent)
当对象与Session关联 被Session管理时
他就除于持久状态,处于持久状态的对象拥有数据标识(数据库中的主键值)那么对象是什么时候与session对象关联的呢有两种方式:第一种通过Session的查询接口或者是get()方法或者是load方法()从数据库中加载对象的时候,家在状态的对象,通过调用session的save方法或者saveOrUpdate方法时java对象也与session发生关联,对于处于持久状态的对象,session会跟踪和管理他们,如果对象的内部状态发生了任何变化,hibernate会选择合适的实际(如事务提交时)将变更固化到数据库中。
3游离状态(Detached)
处于持久化的对象
脱离与其关联的Session管理后对象就处于游离状态,处于游离状态的对象Hibernate无法感知到对象的任何操作Session提供了两个方法(Update()
merge())将处于游离状态的对象与一个新的session发生关联,这是对象的状态就从游离转持久化。
三种状态的转换
1.瞬时状态转为持久状态
使用Session对象的save()或saveOrUpdate()方法保存对象后,该对象的状态由瞬时状态转换为持久状态。
使用Session对象的get()或load()方法获取对象,该对象的状态是持久状态。
2.持久状态转为瞬时状态
执行Session对象的delete()方法后,对象由原来的持久状态变为瞬时状态,因为此时该对象没有与任何的数据库数据关联。
3.持久状态转为游离状态
执行了Session对象的evict()–清除单个对象、clear()–清除所有对象或close()方法,对象由原来的持久状态转为游离状态。
4.游离状态转为持久状态
重新获取Session对象,执行Session对象的update()或saveOrUpdate()方法,对象由游离状态转为持久状态,该对象再次与Session对象相关联。
5.游离状态转为瞬时状态
执行Session对象的delete()方法,对象由游离状态转为瞬时状态。
处于瞬时状态或游离状态的对象不再被其他对象引用时,会被Java虚拟机按照垃圾回收机制处理。
4.脏检查及刷新缓存机制
脏检查:
在Hibernate中,数据前后发生的变化的对象,称为脏对象
tx = session.beginTransaction();
//获取部门对象,dept对象处于持久状态
Dept dept2 = (Dept)session.load(Dept.class,new Byte("11"));
//修改后,部门信息和之前不同,此时dept对象称为所谓的“”脏对象“”
dept2.setDname(“质管部”);
tx.commit();
刷新缓存机制
使用commit()
5.更新数据的方法
update() 用户将游离状态恢复持久状态,进行更新操作,如果主键为null,报错
saveOrUpdate() 包含了save()和update()方法的功能.如果入参是瞬时状态的对象,就调用save方法,如何使游离,则update方法
merge()
新new一个对象,如果该对象设置了ID,则这个对象就当作游离态处理:
当ID在数据库中不能找到时,用update的话肯定会报异常,然而用merge的话就会insert。 当ID在数据库中能找到的时候,update与merge的执行效果都是更新数据,发出update语句; 如果没有设置ID的话,则这个对象就当作瞬态处理:用update的话,由于没有ID,所以会报异常,merge此时则会保存数据,根据ID生产策略生成一条数据