ORM

全称Object/Relationship Mapping(对象/关系映射)

为何引入ORM

Java、C++等许多语言是面向对象的编程思想,但是底层数据库往往是关系型数据库,为了往数据库中插入数据,需要编写相应的sql语句。比如向一张学生表中插入一条数据(包含学生的基本信息:姓名、年龄、家庭住址等)

insert into students values(1,"张三丰","16","男","1977-4-3","武当山屠龙馆")

timg?image&quality=80&size=b9999_10000&sec=1516013550680&di=7b04427e816e4ba501edaac01d86d6dd&imgtype=0&src=http%3A%2F%2Fimages2015.cnblogs.com%2Fblog%2F760530%2F201510%2F760530-20151007143147018-1799743061.png
这种在程序中大量插入SQL语句的方式有很多弊病,因为对于SQL语句来说,存在以下问题:

  1. 不同数据库使用的SQL语句不同,比如mysql、SQL Server(微软的产品)
  2. 同样的功能,在不同数据库中实现方式不同。因为不同数据库产品封装的不一样

因此,如果程序中写入大量SQL语句,将对程序的移植、维护带来很多麻烦。ORM就是这样诞生的,其目的是让程序员抛弃在程序中直接书写SQL的思想,完全使用面向对象的思想来开发软件。Hibernate就是一种ORM框架

关系数据库:可以简单的理解为二维数据库。复杂来说,是指采用了关系模型来组织数据的数据库(关系模型是1970年由IBM研究员E.F.Codd博士首先提出的,并逐渐发展为数据库架构的主流模型),一般而言,关系模型指的就是二维表格模型,而一个关系型数据库就是由二维表格和它们之间的联系组成的一个数据组织

题外话: 经常看到除了关系型数据库,还有一种非关系型数据库,其实这是一种误解。其英文为:NoSQL(全称:Not Only SQL),所以叫它不仅仅是SQL或者超关系型数据库都行,不知道为什么就翻译成了非关系型数据库。毕竟这个“非”字导致了很多理解困难

Hibernate

Hibernate是Java领域的一款开源ORM框架技术,对JDBC进行了轻量级的对象封装
timg?image&quality=80&size=b9999_10000&sec=1516013653575&di=2ebf9c9780b60ceb14be0bde3f43f21f&imgtype=jpg&src=http%3A%2F%2Fimg2.imgtn.bdimg.com%2Fit%2Fu%3D3627080182%2C4064784388%26fm%3D214%26gp%3D0.jpg

执行流程

timg?image&quality=80&size=b9999_10000&sec=1516014572802&di=84e22c87720d63175ef3a9fc229df03e&imgtype=0&src=http%3A%2F%2Fstatic9.photo.sina.com.cn%2Fbmiddle%2F51721d974511e2bdb3378

Session(会话)

不建议直接使用jdbc的connection来操作数据库,而是使用session,可以简单认为,session就是操作数据库的对象。
要想把数据保存在关系型数据库中,需要调用session的各种方法,如:save()、update()等

如何获取session对象

通常有两种方法,这两种方法都是sessionFactory中的
1) openSession
2) getCurrentSession
如果使用getCurrentSession,需要在hibernate.cfg.xml文件中进行配置:
如果是本地事务(jdbc事务)
<propertyname = "hibernate.current_session_context_class">thread</property>
如果是全局事务(jta事务)
<propertyname = "hibernate.current_session_context_class">jta</property>

openSession和getCurrentSession

  1. getCurrentSession在事务提交或者回滚之后会自动关闭;而openSession需要手动关闭,如果未进行手动关闭,多次之后会导致连接池溢出
  2. openSession每次都会创建新的session对象,getCurrentSession则使用先用的session对象

session操作

hibernate会把符合条件的数据寄存到内存上,那么也就存在一个对内存的管理,而session是有一级缓存(强制默认开启),其目的是为了减少查询数据库的时间,提高效率,一级缓存的生命周期和session是一样的。session.flush()和session.clear()就是针对session的一级缓存的处理。
简单来说:

  • session.flush()的作用就是将session缓存(在内存里)中的数据与数据库同步。
  • session.clear()的作用就是清除session中的缓存数据(不管缓存与数据库的同步)
  • session.evict(obj)的作用就是将指定的obj缓存对象进行清除

Flush方法

可以通过flush方法强制进行从内存到数据库的同步,主要分为了两步:清理缓存,执行SQL。例如:

public void testFlush(){  
    Session session =  HibernateUitl.getSessionFactory().getCurrentSession();  
    session.beginTransaction();  
    Teacher t = (Teacher) session.get(Teacher.class, 3);  
    t.setName("yyy");  
    session.flush();//有flush会执行2次UPDAE,没有会只执行一次  
    t.setName("yyyyy");  
    session.getTransaction().commit();  
}  

Flush方法是可以设置的,也就是 fulsh 什么时候执行是可以设置的,在session.beginTransaction 代码前设置 FlushMode

session.setFlushMode(FlushMode.Always|AUTO|COMMIT|NEVER|MANUAL);

这里 FlushMode 有 5 个值可选:

  1. Always: 任何代码都会 Flush
  2. AUTO: 默认方式 – 自动
  3. Commit: COMMIT 时
  4. Never: 始终不
  5. MANUAL: 手动方式

设置 FlushMode 有个好处是可以节省开销,比如默认 session 只做查询时,就可以不让他与数据库同步了。

注意:执行完session.flush()时,并不意味着数据就肯定持久化到数据库中的,因为事务控制着数据库,如果事务提交失败了,缓存中的数据还是照样会被回滚的。

transaction(事务)

hibernate对数据的操作都是封装在事务当中的,并且默认是非自动提交的方式。所以对session保存对象时,如果不开启事务,并且手工提交事务,对象并不会真正保存在数据库中。
如果想让hibernate像JDBC那样自动提交事务,必须调用session对象的doWork()方法,获得jdbc的connection后,设置为自动提交事务模式(注意:通常不推荐这么做)


简_矩_风
5 声望1 粉丝