1.hibernate概述
一个开发源代码的对象关系映射框架;
对JDBC进行了非常轻量级的对象封装;
将JavaBean对象和数据库的表建立对应关系;
简化了JDBC或C3P0和DBUtils实现的dao层.
hibernate是一种ORM框架实现:
ORM:Object Relation Mapping 对象关系映射
1).把对象映射到数据表的记录行中.
2).通过操作对象的方式操作数据表.
hibernate优点:3).是一种操作数据表的规范,可以不写sql语句操作数据库.
a.开源的持久层框架.
b.ORM(Object/Relational Mapping)映射工具,建立面向对象的域 模型和关系数据模型之间的映射.
c.连接java应用和数据库的中间件.
d.对JDBC进行封装,负责java对象的持久化.
e.在分层结构中处于持久化层,封装对数据库的访问细节,使业务逻辑层更专注于实现业务逻辑.
a.很大程度上简化了JDBC的操作(如sql语句的拼接等),并进行了封装.b.提高了Dao层的代码效率.c.使用java的反射机制,OOP/而不是关系,提高了透明性.d.性能非常好,因为它是一个轻量级框架,映射灵活.
2.hibernate框架应用体验
1).主配置文件hibernate.cfg.xml
<span style="font-size:14px;"><hibernate-configuration> <span style="white-space:pre"> </span><session-factory> <!-- 数据库连接信息 --> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/day32</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">root</property> <!-- 数据库方言配置(告诉hibernate使用哪一种数据库,hibernat会自动生成符合当前数据库语法特征的SQL语句!) --> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <!-- 加载的所有映射文件 --> <mapping resource="cn/hibernate_/a_config/Employee.hbm.xml"/> </session-factory> </hibernate-configuration></span></span>
2).实体类Employee.java
<span style="font-size:14px;">// 持久化对象! public class Employee { private int empId; private String empName; private double salary; private Date birth; //属性略 }</span>
3).对象与数据表的映射关系配置文件Employee.hbm.xml
<span style="font-size:14px;"><!-- 描述:对象与数据库的某张表的,映射关系! --> <hibernate-mapping package="cn.hibernate_.a_config"> <class name="Employee" table="employee"> <!-- 主键 --> <id name="empId" column="id"> <generator class="native"/> </id> <!-- 其他字段 --> <!-- name为对象的属性名,colum为数据表的字段名--> <property name="empName" column="name"></property> <property name="salary" column="salary"></property> <property name="birth" column="birth"></property> </class> </hibernate-mapping></span>
4).测试
<span style="font-size:14px;">public class App { // 不写sql,保存对象,到对象对应的表中! @Test public void testSave() { <span style="white-space: pre;"> </span>// 对象 <span style="white-space: pre;"> </span>Employee emp = new Employee(); <span style="white-space: pre;"> </span>emp.setEmpName("Jack"); <span style="white-space: pre;"> </span>emp.setSalary(8000); <span style="white-space: pre;"> </span>emp.setBirth(new Date()); <span style="white-space: pre;"> </span>//1. 创建配置管理器对象; <span style="white-space: pre;"> </span>Configuration config = new Configuration(); <span style="white-space: pre;"> </span>//2. 加载主配置文件hibernate.cfg.xml (在主配置文件中有加载所有的映射文件Employee.hbm.xml) <span style="white-space: pre;"> </span>//config.configure("hibenrate.cfg.xml"); // 默认加载src/hibernate.cfg.xml <span style="white-space: pre;"> </span>config.configure(); <span style="white-space: pre;"> </span>//3. 根据加载的主配置文件,创建SessionFactory对象 <span style="white-space: pre;"> </span>SessionFactory sf = config.buildSessionFactory(); <span style="white-space: pre;"> </span>//4. 创建Session对象 <span style="white-space: pre;"> </span>Session session = sf.openSession(); <span style="white-space: pre;"> </span>//5. 开启事务 <span style="white-space: pre;"> </span>Transaction tx = session.beginTransaction(); <span style="white-space: pre;"> </span>//6. 执行操作 <span style="white-space: pre;"> </span>session.save(emp); <span style="white-space: pre;"> </span>//7. 提交事务、关闭Session <span style="white-space: pre;"> </span>tx.commit(); session.close(); } // 不写sql,实现查询,直接封装返回指定的对象! @Test public void get() { Configuration config = new Configuration().configure(); SessionFactory sf = config.buildSessionFactory(); Session session = sf.openSession(); // 开启事务 session.beginTransaction(); // 执行操作: Employee emp = (Employee) session.get(Employee.class, 3); System.out.println(emp); // 提交事务、关闭 session.getTransaction().commit(); // 获取绑定到当前session上的事务! session.close(); } }</span>
3.简单执行流程简述
1).应用程序先调用Configuration类,创建Configuration对象,读取hibernate配置文件及映射文件;2).根据配置信息,Configuration对象创建SessionFactory对象;3).SessionFactory对象生成一个程序与数据库会话的session对象;4).session对象生成Transaction事务对象a.可以通过session对象的get()/load()/save()/update()/delete()/saveOrUpdate()等方法对数据表进行操作;b.在查询的情况下,可以通过session对象生成一个Query对象,然后利用Query对象执行查询操作;如果没有异常,Transaction对象将提交操作到数据库;transation.commit();若有异常,transaction.rollback();5).关闭session.
4.关于hibernate的数据更新
<span style="font-size:14px;">private static SessionFactory sf;
static {
sf = new Configuration()
.configure()
.addClass(Employee.class) // Employee .hbm.xml
.buildSessionFactory();
}
// 更新操作:保存
@Test
public void testSave() {
// 创建session
Session session = sf.openSession();
// 开启事务
session.beginTransaction();
// -- 1. 执行 “保存” 操作--
//session.save(new Employee());
// -- 2. 执行 “更新” 操作--
//Employee emp = new Employee();
//emp.setEmpId(4);
//session.update(emp); // 要求:更新数据的主键,必须存在;否则报错!
// -- 3. 执行 “保存or更新” 操作--
/*
Employee emp = new Employee();
emp.setEmpId(5);
emp.setEmpName("Jack");
* 如果有设置主键,
* 主键存在,就执行更新!
* 主键不存在,更新没有主键更新不了,就报错!
* 如果没有设置主键,
* 执行保存!
session.saveOrUpdate(emp);
*/
/* -- 4. 执行 “保存or更新” 操作--
Employee emp = new Employee();
emp.setEmpId(40);
session.delete(emp); // 删除的主键如果在DB不存在,则报错 (如果主键自增长,删除主键是0的记录,数据库不存在,但没有报错!只有这一种情况删除主键不存在不会报错!) */
// 删除2: 先查询载删除
Object obj = session.get(Employee.class, 500);
// 再判断,删除
if (obj != null) {
session.delete(obj);
}
// 提交事务
session.getTransaction().commit();
session.close();}</span>
}
5.一些细节
1).为了避免在操作数据库时有异常,所以,要对hibernate的操作进行异常处理
<span style="font-size:14px;">Session session = null; Transaction tx = null; try { // 创建session session = HibernateUtils.getSession(); // 开启事务 tx = session.beginTransaction(); // 先查询 Object obj = session.get(Employee.class, id); // 判断 if (obj != null) { session.delete(obj); } tx.commit(); } catch (Exception e) { tx.rollback(); // 回滚事务 throw new RuntimeException(e); } finally { session.close(); }</span>
2).get()与load()查询的区别
get主键查询: 当执行get方法,立刻向数据库发送SQL语句;如果主键不存在返回null
load主键查询: 当使用数据对象的时候才向数据库查询(懒加载)!
如果查询的主键不存在,使用就报错!由于是使用查询结果是才向数据库查询,所以,使用之前不能关闭session对象.
====两个查询都可以不开启事务,就能执行.3).分页查询
<span style="font-size:14px;">//-- 操作 --- Query q = session.createQuery("FROM Employee");//HQL语句 // 设置分页参数 q.setFirstResult(index); // 返回起始行; MySQL中,limit的第一个参数 q.setMaxResults(count); // 查询返回行数; MySQL中,limit的第二个参数 // 查询 List<Employee> list = q.list();</span>
6.对象与数据表的映射配置文件JavaBean.hbm.xml
<span style="font-size:14px;"><!-- 描述:对象与数据库的某张表的,映射关系! -->
<!-- package 当前映射文件中实体类默认的包(可选!) -->
<hibernate-mapping package="cn.hibernate_.c_hbm.xml">
<!--
class 表示的是一个实体类与一张表的映射, 一个映射文件可以有多个class!
但建议一个实体类对应一个映射文件!
name 类名称,一定要定位到类的全名!
table 当前类,映射到的表, 如果不写默认表与类名一样!
-->
<class name="Employee" table="Employee">
<!-- 主键 (必须有) -->
<!--
hibernate要求表必须有主键!
id 表示主键映射,即必须有id节点,只能出现一次!
class 表示主键的生成策略:
【5.1.2.2.1. Various additional generators】
identity mysql总自增长的方式!实际上是identity!
sequence oracle中主键自增长的方式,是以序列方式完成!
native 主键自增长 (根据底层数据库的能力选择 identity、sequence )
推荐!
assigned 手动指定主键的值!(控制主键不重复!)
uuid uuid值作为主键!
-->
<span style="white-space:pre"> </span><id name="empId" column="id">
<generator class="uuid"/>
</id>
<!-- 其他字段 -->
<!--
property 表示所有非主键字段的映射!
name 指对象的属性名称!
column 属性对应的字段!
默认与属性名一致!
length 指定字符的长度! 只对字符类型有效!
type 字段的类型!
1. Hibernate提供的类型:
小写开头: 如, type="string"
2. java中类型:
对象类型,一定是对象的全名!
如:type="java.lang.String"
如果没有指定,默认会匹配 ben的属性的类型!
注意:
1. 日期类型的属性,不指定默认到数据库是datetime
2. type="java.util.Date" 同上, datetime
3. type="date" 对应数据库就是date类型!
-->
<property name="empName" not-null="true" column="name" type="string" length="50"></property>
<property name="salary"></property>
<property name="birth" type="date"></property>
<!-- 关键字字段映射, 需要用反引号! ~ ~~~~~~~~```````` -->
<property name="desc" column="`desc`"></property>
</class>
</hibernate-mapping></span>
7.联合主键
<span style="font-size:14px;">//1).实体对象
public class User {
// 联合主键对象
private Keys key;
private Date birth;
private char sex;
//属性略
}
//2).联合主键类
public class Keys implements Serializable{
//成员名与实体对象成员名一致
private String name;
private String address;
//属性略
}</span>
<span style="font-size:14px;"><!-- 3).关系映射配置文件User.hbm.xml -->
<hibernate-mapping>
<class name="cn.itcast.d_composite.User">
<!-- 联合主键映射 -->
<composite-id name="key"> <!-- 联合主键对象 -->
<key-property name="name"></key-property> <!-- 联合主键对象 ,属性 -->
<key-property name="address"></key-property> <!-- 联合主键对象 ,属性 -->
</composite-id>
<property name="sex" type="character"></property>
<property name="birth"></property>
</class>
</hibernate-mapping></span>