一、Hibernate:ORM(Object Relation Mapping)对象关系映射框架
常用的ORM框架有:Hibernate、TopLink、OJB。
Hibernate 框架完全是进行对象的操作,不再会有对字段、属性的操作。如Hibernate 删除则是删除一个对象,更新则是对某一个对象状态进行更新
小贴士:应用Hibernate开发时,可与JDBC相联想
二、开发流程:
1.由Domain Object ----》mapping -----》db(官方推荐)
2.由DB开始,用工具生成mapping和Domain Object(使用较多)
3.由映射文件开始
Domain Object 限制:
1.默认的构造方法(必须的)
2.有无意义的标示符id(主键)(可选)
3.非final,对懒加载有影响
三、需要一个工具类,只加载一次 hibernate.cfg.xml 文件
package cn.itcast.hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
publicfinalclass HibernateUtil {
private HibernateUtil() {}
privatestatic SessionFactory sf = null;
static {
Configuration cfg = new Configuration();
cfg.configure();
//cfg.configure(new File("filename")); //指定配置文件的路径,不指定则默认
sf = cfg.buildSessionFactory();
}
publicstatic SessionFactory getSessionFactory() {
returnsf;
}
publicstatic Session getSession() {
returnsf.openSession();
}
}
小贴士:将java类与hibernate源码绑定
四、Mysql 有多种引擎:
MyISAM:5.0以前的缺省引擎,效率高但不支持事务。
InnoDB:支持事务,则Hibernate操作时需要开启事务,进行操作后提交事务,这样才能将数据持久化:
Transaction tx = s.beginTransaction();//开启事务
User user = new User();
user.setName("name");
user.setBirthday(new Date());
s.save(user);
tx.commit(); //事务提交
五、Hibernate 核心接口概述:
Configuration:
负责管理Hibernate的配置信息,这些信息由配置文件提供,包括如下内容:
1.Hibernate运行的底层信息:数据库的URL、用户名、密码、JDBC驱动类等,数据库Dialect,数据库连接池等。
2.Hibernate映射文件(*.hbm.xml)
调用代码:
1.属性文件(hibernate.properties)
Configuration cfg = new Configuration();
cfg.addClass(XXX.class);//该方法加载XXX.hbm.xml
cfg.addResource();
2.XML文件(hibernate.cfg.xml)
Configuration cfg = new Configuration();
cfg.configure();
SessionFactory:
1.应用程序从SessionFactory(会话工厂)里获得Session(会话)实例。它在多个应用线程间进行共享。通常情况下,整个应用只有唯一的一个会话工厂---例如在应用初始化时被创建。然而,如果你使用Hibernate访问多个数据库,你需要每个数据库使用一个会话工厂。
2.会话工厂缓存了生成的SQL语句和Hibernate在运行时使用的映射元数据。
3.调用代码:
privatestatic SessionFactory sf = null;
static {
Configuration cfg = new Configuration();
cfg.configure();
sf = cfg.buildSessionFactory();
}
Session:
1.Session不是线程安全的,它代表与数据库之间的一次操作会话
2.Session也称为持久化管理器,因为它是与持久化有关的操作接口
3.Session通过SessionFactory打开,在所有的工作完成后,需要关闭
4.Session缓存其管理的持久化对象
5.调用代码:
Session session sessionFactory.openSession();
Transaction:
1.它将应用代码从底层的事务实现中抽象出来---这可能是一个JDBC事务,一个JTA用户事务或者甚至是一个公共对象请求代码结构(CORBA)---允许应用通过一组一致的API控制事务边界
2.这有助于保持Hibernate应用在不同类型的执行环境或容器中的可移植性
3.Hibernate提供的事务提交模式默认为非自动提交模式(默认:autoCommit=false),因此使用Hibernate进行操作时(增、删、改)必须显示的调用Transaction的API
4.调用代码:
Transaction tx = session.beginTransction();
Tx.commit()/rollback();
Query/Criteria:
1.Query接口封装了Hibernate强大的对象查询能力,同时也支持数据库的更新操作
2.提供了动态查询的参数绑定功能
3.提供list(),iterator(),scroll()等对象导航方法
4.提供uiqueResult()方法获取单独的对象
5.提供executeUpdate()方法来执行DML语句
6.提供了可移植的分页查询方法
Session:
1、save,presist保存数据,persist在事务外不会产生insert语句。
2、delete,删除对象
3、update,更新对象,如果数据库中没有记录,会出现异常,脱管对象如属性改变需要保存,则调用update方法
4、get,根据ID查,会立刻访问数据库
5、load,根据ID查,(返回的是代理,不会立即访问数据库)
6、saveOrUpdate,merge(根据ID和version的值来确定是否是save或update),调用merge你的对象还是托管的。当不知该对象的状态时可调用该方法
小贴士:瞬时对象id无值,脱管对象有值,hibernate通过该方式判断对象的状态
7、lock(把对象变成持久对象,但不会同步对象的状态)
六、Hibernate中对象的状态:
状态的参考:数据库中是否有记录;是否有session关联
1、瞬时(transient):数据库中没有数据与之对应,超过作用域被JVM垃圾回收器回收,一般是new出来且session没有关联的对象
2、持久(persistent):数据库中有数据与之对应,当前session有关联,并且相关联的session没有关闭,事务没有提交;持久对象状态发生改变,在事务提交时会影响到数据库(hibernate能检测到)
3、脱管(detached):数据库中有数据与之对应,但当前没有session与之关联;托管对象状态发生改变,hibernate不能检测到
对象在的状态转化:
当对象被save,commit后,Hibernate Session 任然能察觉到对象,如果此时对象属性发生改变,则数据库中持久化的值同样被改变,如:
//标准方法
static void addUser(User user) {
Session s = null;
Transaction tx = null;
try {
s = HibernateUtil.getSession();
tx = s.beginTransaction();
s.save(user);
user.setName("new name");
tx.commit();
} catch (HibernateException e) {
if (tx != null) {
tx.rollback();
}
throw e;
} finally {
if (s != null)
s.close();
}
}
该user对象在数据库中最终持久化的name=="new name",如果在commit之前修改过的属性,将会在commit时候统一对对象进行update。
七、Hibernate Query Language(HQL)和Criteria(QBC)
HQL:面向对象的查询语言,与SQL不同,HQL中的对象名是区分大小写的(除了JAVA类和属性其他部分不区分大小写);HQL中查的是对象而不是和表,并且支持多态;HQL主要通过Query来操作,Query的创建方式:
Query q = session.createQuery(hql);
1.from Person
2.from User user where user.name=:name
3.from User user where user.name=:name and user.birthday<:birthday
static void query(String name) {
Session s = null;
try {
s = HibernateUtil.getSession();
String hql = "from User as user where user.name=?"; //from Object ... 因为HQL支持多态,所以执行 from Object时,将会将所有的表都查一遍
/**
* 当查询条件有多个的时候,则参数 "?" 将会有多个,这样对我们的维护带来极大不便,在HQL中我们利用命名参数处理
* "from User as user where user.name=?" -->> "from User as user where user.name=:n"
* query.setString("n", name);
* 经过这样设置后在多条件情况下,我们不需要再顾及参数的先后顺序了
*/
Query query = s.createQuery(hql);
query.setString(0, name);
/**
* Hibernate 分页: 200-210 条
* query.setFirstResults(200);
* query.setMaxResults(10);
* 这样的分页,为数据库的移植做到了很好的兼容,根据数据库设置的方言来判断
*/
List<User> list = query.list();
//Object obj = query.uniqueResult(); 当我们确定返回的结果集就一条记录,则可调用此方法,如有多条,则会报异常
for(User user : list) {
System.out.println(user.getName());
}
} finally {
if (s != null) {
s.close();
}
}
}
HQL 跟SQL 查询的区别:
HQL根据属性名查对象,SQL根据字段查表
Creteria:Criteria是一种比HQL更面向对象的条件查询方式;Criteria的创建方式:
Criteria crit = session.createCrieria(DomainClass.class);
简单属性条件如:
criteria.add(Restrictions.eq(propertyName, value);
criteria.add(Restrictions.eqProperty(propertyName, otherPropertyName));
staticvoid cri(String name) {
Session s = null;
try {
s = HibernateUtil.getSession();
Criteria c = s.createCriteria(User.class); //对User进行约束查询
c.add(Restrictions.eq("name", name)); //添加约束条件
c.add(Restrictions.lt("birthday", new Date()));
/**
* Criteria 查询同样提供了分页
*/
c.setFirstResult(200);
c.setMaxResults(210);
List<User> list = c.list();
for (User user : list) {
System.out.println(user.getName());
}
} finally {
if (s != null) {
s.close();
}
}
}
小贴士:1、官方推荐HQL 查询
2、Hibernate try的异常可以不去操作,因为事务收不到commit事务就会回滚
八、对象关系的关联映射
1.多对一(Employee - Department) --- 最常用
2.一对多(Department - Employee)
3.一对一(Person - IdCard)
4.多对多(Teacher - Student) -- 需要建立中间表
在操作和性能方面都不太理想,所以多对多的映射,实际使用中最好转换成一对多的对象模型;Hibernate会为我们创建中间关联表,转换成两个一对多。
<set name="teacher" table="teacher_student">
<key column="teacher_id"/>
<many-to-many class="Student" column="student_id"/>
</set>
5.组件映射(User - Name)
关联的属性是个复杂类型的持久化类,但不是实体,即:数据库中没有表与该属性对应,但该类的属性要永久保存的。
<component name="name" class="com.test.hibernate.domain.Name">
<property name="initial" />
<property name="first" />
<property name="last" />
</component>
当组件的属性不能和表中的字段简单对应的时候可以选择实现:
org.hibernate.usertype.UserType or
org.hibernate.usertype.CompositeUserType
6.集合映射(set,list,map,bag)
绝大部分使用set
如果习惯使用list,又不想让Hibernate维护顺序,对象里用List,映射时用bag
映射用list比bag少
键值对方式用map
数组因为对元素变化应用不方便
<set name="employees">
<key column="depart_id" />
<one-to-many class="Employee" />
<!-- <element type="string" column="name" /> -->
<!--
<composite-element class="YourClass">
<property name="prop1" />
<property name="prop2" />
</composite>
-->
</set>
7.Inverse和cascade(Employee - Department)
九、映射文件剖析
1.hbm.cfg.xml
a)
2.Xxx.hbm.xml
a)
十、Hibernate的持久化操作
1.save() //保存对象
a) 把临时对象加载到缓存中,使之成为持久化对象
b) 使用指定的ID生成器为持久化对象分配OID
c) 当对象处于持久化状态Hibernate不允许修改其IOD
2.update() //修改对象
a) 把游离对象加入到缓存中,使一个游离对象变成持久化对象
b) 计划执行update SQL语句,根据对象IOD来更新对象所对应的数据
c) Update不能更新一个在session中已经关联的相同OID的对象
3.saveOrUpdate() //保存或修改对象
a) 同时包含save和update方法的功能,根据对象的状态自动执行相应的功能
b) 若对象为临时状态则执行save,若为游离状态则执行update方法
4.merge()//合并对象
a) 直接修改表中的记录,并不影响该对象原来的状态
5.delete() //删除指定的对象
a) 如果是持久态对象,就计划执行delete语句
b) 如果是游离状态的对象,先使用游离对象被session缓存关联,变成持久化对象,再计划执行delete语句
5.contains() //判断实体对象是否与session关联
a) 可以用此方法判断对象是否处于持久化状态
6.evict() //把实体对象从缓存中移除
7.clear() //清除session缓存中所有持久化对象
8.get/load 方法区别:
a) 都是根据OID从数据库中加载一个持久化对象
b) 当数据库中不存在与OID对象的记录时,get()返回一个null引用,而load则会抛出ObjectNotFoundException异常
c) Load方法可以返回一个实体的代理类实例,而get方法只是直接返回实体类对象