众所周知。眼下流行的面向对象的对象关系映射的Java持久层框架有MyBatis和Hibernate。他们都是对象关系映射ORM。 解决的主要问题就是对象-关系的映射。域模型和关系模型都分别建立在概念模型的基础上。域模型是面向对象的,关系模型是面向关系的,普通情况下。一个持久化类和一个表相应,类的每一个实例相应表中的一条记录。 (可能存在类中多个属性相应一列的情况,映射组成关系), ORM中间件採用元数据来描写叙述对象-关系映射细节,元数据通常採用XML格式。而且存放在专门的对象-关系映射文件里,假设希望把ORM软件集成到自己的Java应用中。用户首先要配置对象-关系映射文件。Hibernate中也就是entity.hbm.xml,而MyBatis中就是entityMapper.xml

以下主要介绍一下Hibernate的运行过程:

  1. session.save(customer)

运行过程:

1)运用反射机制,获得customer对象的类型Customer.class

2)參考对象-关系映射元数据。了解Customer类相应的表,以及属性相应的列,Customer类和其它类关系。

3)依据以上映射信息。生成SQL语句

  1. insert into tab_customer values(id,name,password,telphone);

4)调用JDBC API。运行以上的SQL语句。


JDBC与Hibernate比較:

1,JDBC: Java中嵌入SQL。不便于维护

Hibernate: 无须编写SQL语句;由Hibernate通过读取映射文件在运行时自己主动生成SQL

  1. save(student)-> insert into customer values(?,?,?);

2。JDBC:查询数据。须要手动封装成对象;保存对象,须要手动插入值

Hibernate: 可自己主动实现对象和表中记录的转换

3,JDBC:查询内存中已存在的对象。改动属性值,均须要和数据库进行交互

Hibernate:通过Dirty checking(脏检查)避免交互;


Hibernate的工作原理:

1。Hibernate框架依据hibernate.cfg.xml的配置的信息来和数据库进行通信,当然和Spring结合后也能够通过注解来实现。

2,Hibernate框架依据详细的映射文件**.hbm.xml 来保存。更新。删除,查询对象。


Hibernate API。Hibernate中几个比較重要的类:

Configuration接口:

Configuration对象用于配置而且启动Hibernate,Hibernate应用通过Configuration实例还指定对象-关系映射文件的位置或者动态配置Hibernate的属性。然后创建SessionFactory实例

  1. Configuration config = new Configuration();
  2. Config.configure();
  3. SessionFactory factory = config.buildSessionFactory();

SessionFactory :

用来构造Session的实例对象,它的特点:

1)线程安全: 该实例对象何以被多个线程共享

2)重量级:该实例对象的构造和销毁消耗系统资源,所以一般在应用程序启动的时候就构造实例对象,一般一个数据库相应一个SessionFactory的实例对象。假设要訪问多个数据库,就须要创建多个该实例对象。

3)SessionFactory实例对象中维护了一个非常大的缓存,存放了一些提前定义的SQL语句和XML配置文件的信息,另外还维持了一个Hibernate的第二级缓存(缓存了全部Session对象所载入的POJO对象),用来保存在该生命周期中的一些业务对象,可是这个第二级缓存默认是关闭的,必须在xml中手动配置才干够开放

  1. Session session = factory.openSession();

Session(别名:持久化管理器),用来对对象的保存,更新,删除和查询

特点:

1)线程不安全。要避免同一个Session对象被多个线程共享,一般一个线程相应一个Session

2)轻量级:能够随意的构造和销毁该实例对象。

3)Session对象中维护了一个缓存,称为Hibernate的第二级缓存(缓存了当前Session对象所载入的那些POJO对象),每一个Session对象都有自己的缓存。

Query:

利用HQL语句(Hibernate Query Language)用来查询单个或者多个对象,面向对象的

  1. Query query = session.createQuery("from Student where studentId=1");
  2. Student s = (Student)query.uniqueResult();

Criteria:

功能同上。以面向对象的形式和数据库进行复杂的CRUD操作,还适用于动态查询。

Transaction:

用来处理事务,事务的启动,提交,回滚


OID:主键

在Java语言中。依照内存地址来识别或区分同一个类的不同对象。关系型数据库按主键值来识别或区分同一个表的不同记录,Hibernate使用OID来统一两者之间的矛盾,OID是关系数据库中的主键(通常为代理主键)在Java对象模型中的等价物。

在运行时,Hibernate依据OID来维持Java对象和数据库表中记录的相应关系。

为了保证持久化对象的OID的唯一性和不可变性。通常由Hibernate或底层数据库来为OID赋值,能够将OID的setId()方法设置为private类型,以禁止Java应用程序随便改动OID。

:子元素用来设定标识符生成器

Hibernate提供了标识符生成器口:net.sf.hibernate.id.IdentifierGenerator,而且提供了非常多内置实现。

net.sf.hibernate.id.IdentityGenerator –缩写名– identity

net.sf.hibernate.id.IncrementGenerator –缩写名– increment

主键生成方式:

1,increment:

其生成方式与底层数据库无关。大部分数据库都支持,该方式的实现机制是在当前应用实例中维持一个变量,以保存着当前的最大值。之后每次须要生成主键的时候将此值加1作为主键。其不足之处是当多个线程并发对数据库表进行写操作时。可能出现同样的主键值,发生主键反复的冲突。所以在多线程并发操作的时候不应该使用该方法。

  1. <id name="id" column="ID">
  2. <!-- 主键生成机制 -->
  3. <generator class="increment"/>
  4. </id>

2,identity:

与底层数据库有关,要求数据库支持Identity。如MySQL中auto_increment,SQL Server中的identity。支持的数据库有MySQL,SQL Server,DB2,Sybase,可是不支持oracle,它同一时候支持并发操作。

  1. <id name="id" column="ID">
  2. <!-- 主键生成机制 -->
  3. <generator class="identity" />
  4. </id>

3,assigned:

主键由外部程序负责生成。无需Hibernate參与。假设要由程序代码来指定主键,就採有这样的方式。

  1. <id name="id" column="ID">
  2. <!-- 主键生成机制 -->
  3. <generator class="assigned" />
  4. </id>

4,sequence

使用序列生成主键,须要底层数据库支持在数据库中建一个序列

  1. create sequence seq_name increment by 1 start with 1;

然后在映射文件里指定使用序列的名字

  1. <id name="id" column="ID">
  2. <!-- 主键生成机制 -->
  3. <generator class="sequence">
  4. <param name="sequence">seq_name</param>
  5. </generator>
  6. </id>

5,hilo

通过hi/lo算法生成主键,须要一个表来保存主键的信息,在数据库中建一张表:

  1. create table hi_value(next_hi number not null);
  2. insert into hi_value(next_hi) values(1);
  3. commit;

映射文件里须要指明表的这些信息

  1. <id name="id" column="ID">
  2. <!-- 主键生成机制 -->
  3. <generator class="hilo">
  4. <param name="table">hi_value</param>
  5. <param name="column">next_hi</param>
  6. <param name="max_lo">100</param>
  7. </generator>
  8. </id>

6,seqhilo

与hilo 相似,通过hi/lo 算法实现的主键生成机制,仅仅是主键历史状态保存在Sequence中。适用于支持Sequence的数据库,

在数据库中建一个序列

  1. create sequence seq_name increment by 1 start with 1;
  1. <id name="id" column="ID">
  2. <!-- 主键生成机制 -->
  3. <generator class="seqhilo">
  4. <param name="sequence">seq_name</param>
  5. <param name="max_lo">100</param>
  6. </generator>
  7. </id>

7。 native:

由Hibernate依据不同的数据库方言自行推断採用identity、hilo、sequence当中一种作为Hibernate主键生成方式,native的长处是与底层无关。便于不同数据库之间的移植,由Hibernate依据不同数据库选择主键的生成方式。在oracle中须要创建叫 Hibernate_sequence名字的sequence。假设设置了Hibernate.hbm2ddl.auto属性,不须要手动建立序列,前提是数据库帐号必须有Create Sequence这样的高级权限。mysql等数据库则不用建立sequence。

  1. <id name="id" column="ID">
  2. <!-- 主键生成机制 -->
  3. <generator class="native" />
  4. </id>

8,foreign

外键生成方式,依赖其它表的主键。在主键一对一映射中须要使用到

  1. <id name="id" column="ID">
  2. <!-- 主键生成机制 -->
  3. <generator class="foreign>
  4. <param name="property">id</param>
  5. </generator>
  6. </id>

9,uuid.hex:

採用基于128位的算法生成唯一值,并编制成32位长度的唯一字符串作为主键值,uuid.hex的长处是支持大部分数据库,缺点就是要占用较大的存储空间。

对于并发Insert要求较高的系统。推荐採用uuid.hex 作为主键生成机制。

  1. <id name="id" column="ID">
  2. <!-- 主键生成机制 -->
  3. <generator class="uuid.hex" />
  4. </id>

10。uuid.string:

使用UUID算法。UUID被编码为一个16个字符长的随意ASCII字符组成的字符串。

不能在PostgreSQL数据库中使用。

uuid.string同uuid.hex相似,须要占非常大的存储空间。

11,select

使用触发器生成主键(主要用于早期的数据库主键生成机制,少用)


介绍完以上这些内容之后,以下就简单的体验一下搭建Hibernate的开发环境:

1.导入Hibernate的jar包,我这里新建的是Maven项目,因此首先须要加入关于Hibernate的依赖,由于我们还须要与数据库打交道。因此还须要加入数据库以及数据源的依赖jar包,以下是我的pom.xml文件的内容:

  1. <properties>
  2. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  3. <hibernate.version>4.1.7.Final</hibernate.version>
  4. <druid.version>1.0.12</druid.version>
  5. <mysql.version>5.1.18</mysql.version>
  6. </properties>
  7. <dependencies>
  8. <dependency>
  9. <groupId>junit</groupId>
  10. <artifactId>junit</artifactId>
  11. <version>4.12</version>
  12. <scope>test</scope>
  13. </dependency>
  14. <!-- hibernate4 -->
  15. <dependency>
  16. <groupId>org.hibernate</groupId>
  17. <artifactId>hibernate-core</artifactId>
  18. <version>${hibernate.version}</version>
  19. </dependency>
  20. <!--Druid连接池包 -->
  21. <dependency>
  22. <groupId>com.alibaba</groupId>
  23. <artifactId>druid</artifactId>
  24. <version>${druid.version}</version>
  25. </dependency>
  26. <dependency>
  27. <groupId>mysql</groupId>
  28. <artifactId>mysql-connector-java</artifactId>
  29. <version>${mysql.version}</version>
  30. </dependency>
  31. </dependencies>

2.在src/main/resources文件夹下新建一个hibernate.cfg.xml的文件。里面我们主要配置数据源:

  1. <hibernate-configuration>
  2. <session-factory>
  3. <!-- 数据库连接设置 -->
  4. <!-- Database connection settings -->
  5. <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
  6. <property name="connection.url">jdbc:mysql://localhost:3306/hibernate</property>
  7. <property name="connection.username">root</property>
  8. <property name="connection.password">admin</property>
  9. <!-- SQL方言 -->
  10. <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
  11. <!-- 在控制台打印出运行的SQL语句 -->
  12. <!-- Echo all executed SQL to stdout -->
  13. <property name="show_sql">true</property>
  14. <!-- 是否格式化打印出来的SQL -->
  15. <property name="format_sql">true</property>
  16. <!-- 将映射文件转换为数据库定义语言 -->
  17. <!-- Drop and re-create the database schema on startup -->
  18. <!-- web项目启动时怎么操作表结构:更新、删除重建 -->
  19. <property name="hbm2ddl.auto">update</property>
  20. <!-- 映射文件 -->
  21. <mapping resource="student.hbm.xml" />
  22. </session-factory>
  23. </hibernate-configuration>

3.我们这里新建一个Student的实体类。而且也在src/main/resources文件夹下创建一个映射文件:student.hbm.xml

Student.java

  1. package com.ecjtu.hibernate.entity;
  2. import java.io.Serializable;
  3. import java.util.Date;
  4. public class Student implements Serializable {
  5. private static final long serialVersionUID = 1L;
  6. private String major;
  7. private Long id;
  8. private String name;
  9. private String sex;
  10. private Integer age;
  11. private Date birthday;
  12. public Student() {
  13. }
  14. public Student(String major, Long id, String name, String sex, int age,
  15. Date birthday) {
  16. super();
  17. this.major = major;
  18. this.id = id;
  19. this.name = name;
  20. this.sex = sex;
  21. this.age = age;
  22. this.birthday = birthday;
  23. }
  24. public String getSex() {
  25. return sex;
  26. }
  27. public void setSex(String sex) {
  28. this.sex = sex;
  29. }
  30. public Date getBirthday() {
  31. return birthday;
  32. }
  33. public void setBirthday(Date birthday) {
  34. this.birthday = birthday;
  35. }
  36. public String getMajor() {
  37. return major;
  38. }
  39. public void setMajor(String major) {
  40. this.major = major;
  41. }
  42. public Long getId() {
  43. return id;
  44. }
  45. public void setId(Long id) {
  46. this.id = id;
  47. }
  48. public String getName() {
  49. return name;
  50. }
  51. public void setName(String name) {
  52. this.name = name;
  53. }
  54. public Integer getAge() {
  55. return age;
  56. }
  57. public void setAge(Integer age) {
  58. this.age = age;
  59. }
  60. @Override
  61. public String toString() {
  62. return "Student[Major:" + getMajor() + " Id:" + getId() + " Name:"
  63. + getName() + " sex:" + getSex() + " Age:" + getAge()
  64. + " birthday:" + getBirthday() + "]";
  65. }
  66. }

student.hbm.xml

  1. <?
  2. xml version="1.0" encoding="UTF-8"?>
  3. <!DOCTYPE hibernate-mapping PUBLIC
  4. "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  5. "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
  6. <hibernate-mapping package="com.ecjtu.hibernate.entity">
  7. <class name="Student" table="TAB_STUDENT">
  8. <id name="id" column="id">
  9. <!-- 主键生成机制:自增长 -->
  10. <generator class="increment"/>
  11. </id>
  12. <!-- 属性字段 -->
  13. <property name="major"/>
  14. <property name="name"/>
  15. <property name="sex"/>
  16. <property name="age"/>
  17. <property name="birthday"/>
  18. </class>
  19. </hibernate-mapping>

4.建好这些之后基本上也就大功告成了,接下来就能够測试了。在src/test/java以下新建一个測试类HibernateTest.java

  1. package com.ecjtu.hibernate.Test;
  2. import java.util.Date;
  3. import org.hibernate.Session;
  4. import org.hibernate.SessionFactory;
  5. import org.hibernate.Transaction;
  6. import org.hibernate.cfg.Configuration;
  7. import org.junit.Before;
  8. import org.junit.Test;
  9. import com.ecjtu.hibernate.entity.Student;
  10. /**
  11. * @ClassName: HibernateTest
  12. * @Description: Hibernate測试
  13. * @author Zhouxh
  14. * @date 2017年2月19日
  15. */
  16. public class HibernateTest {
  17. private SessionFactory sessionFactory;
  18. @SuppressWarnings({ "deprecation"})
  19. @Before
  20. public void init(){
  21. //1.创建配置对象
  22. Configuration configuration=new Configuration();
  23. //2.读取配置文件,參数可为空。Document。File,配置文件的路径或者URL
  24. //HibernateTest/src/main/resources/hibernate.cfg.xml
  25. configuration.configure();
  26. //3.依据配置文件,创建一级缓存(sessionFactory)
  27. sessionFactory=configuration.buildSessionFactory();
  28. }
  29. @Test
  30. public void test(){
  31. /**
  32. * 建立与数据库的连接
  33. * 映射文件,映射对象
  34. * session 代码与数据库之间的会话
  35. */
  36. //4.创建Session。打开会话
  37. Session session=sessionFactory.openSession();
  38. //5.开启事物
  39. Transaction transaction=session.beginTransaction();
  40. Student student=new Student("软件工程", 1000L, "李四", "男", 34, new Date(System.currentTimeMillis()));
  41. session.save(student);
  42. //6.事物的提交
  43. transaction.commit();
  44. //7.session的关闭
  45. session.close();
  46. }
  47. }

5.运行完Junit单元測试成功了就可以。这时控制台也会打出insert into语句,这就说明我们的配置没有问题了。

6.封装HibernateSessionFactory工具类,由于Session是线程不安全的。为了保证当前线程仅仅有一个session对象,而且当前线程中的Session不能让其它线程来訪问,须要将获取Session的方法进行封装。为了保证Session的线程安全性。须要将Session放到ThreadLocal中,ThreadLocal为线程本地变量

HibernateSessionFactory.java,主要是为了维护Session的创建和关闭。

  1. package com.ecjtu.hibernate.util;
  2. import org.hibernate.Session;
  3. import org.hibernate.SessionFactory;
  4. import org.hibernate.cfg.Configuration;
  5. /**
  6. * @ClassName: HibernateSessionFactory
  7. * @Description: 封装一个创建Session的工厂而且得到Session的方法
  8. * @author Zhouxh
  9. * @date 2017年2月20日
  10. */
  11. @SuppressWarnings("deprecation")
  12. public class HibernateSessionFactory {
  13. //hibernate.cfg.xml文件的位置
  14. //private static String configFile = "hibernate.cfg.xml";
  15. private static SessionFactory factory;
  16. // 用于存放Session,该对象是线程安全的。仅仅有当前线程才干訪问
  17. private static ThreadLocal<Session> threadLocal;
  18. static {
  19. Configuration config = new Configuration( );
  20. // 无參默认系统去找src以下的hibernate.cfg.xml"
  21. config.configure();
  22. // 重量级:该实例对象的构造和销毁消耗系统资源,所以一般在应用程序启动的时候就构造实例对象,
  23. // 一般一个数据库相应一个SessionFactory的实例对象,
  24. // 假设要訪问多个数据库,就须要创建多个该实例对象。
  25. factory = config.buildSessionFactory();
  26. threadLocal = new ThreadLocal<Session>();
  27. }
  28. /**
  29. * @Title: getSession
  30. * @Description: 获取Session
  31. * @return
  32. * @throws
  33. */
  34. public static Session getSession() {
  35. // 该方法底层是一个map实现的Key为当前线程的对象,value为Session
  36. // 假设当前线程没有打开过Session,那么就返回空,意味着我们须要去创建一个Session,
  37. // 保证了一个线程里面相应一个Session
  38. Session session = threadLocal.get();
  39. // 第一个为空的话,第二个表达式不会运行,避免了空指针
  40. // session为空而且或者他没有被打开过就去创建
  41. if (session == null || !session.isOpen()) {
  42. session = factory.openSession();
  43. // 该方法底层通过Map来保存的,调用该方法会自己主动帮你创建一个map出来。
  44. // 并通过key-value保存Session到map中,获取session的时候通过key去取的话
  45. // 不同的key就会返回不同的session
  46. threadLocal.set(session);
  47. }
  48. return session;
  49. }
  50. /**
  51. * @Title: closeSession
  52. * @Description: 关闭Session
  53. * @throws
  54. */
  55. public static void closeSession() {
  56. Session session = threadLocal.get();
  57. threadLocal.set(null);
  58. if (session != null) {
  59. session.close();
  60. }
  61. }
  62. }

到这里。Hibernate复习的第一部分也就结束了。主要就是简介一下Hibernate的使用和主要的一些信息。

最后附上一张Hibernate的内置映射类型,也就是Hibernate的类型—Java类型—标准SQL类型三者之间的相应关系:

Hibernate复习之Hibernate基本介绍的更多相关文章

  1. hibernate复习第(二)天

    今日要点: 关联映射 多对一(Employee - Department) 一对多(Department - Employee) 一对一(Person - IdCard) 多对多(teachet - ...

  2. Hibernate 系列 02 - Hibernate介绍及其环境搭建

    引导目录: Hibernate 系列教程 目录 昨晚喝多了,下午刚清醒,继续搞Hibernate.走起. 觉得还行的话,记得点赞哈,给我这个渣渣点学习的动力.有错误的话也请指出,省的我在错误上走了不归 ...

  3. hibernate复习第(一)天

    首先导入jar. 这个版本是3.2.5 开发流程: 1.由Domain object ->mapping ->db (官方推荐) 2.由DB开始,使用工具生成mapping和Domain ...

  4. (Hibernate进阶)Hibernate系列——总结篇(九)

    这篇博文是hibernate系列的最后一篇,既然是最后一篇,我们就应该进行一下从头到尾,整体上的总结,将这个系列的内容融会贯通. 概念 Hibernate是一个对象关系映射框架,当然从分层的角度看,我 ...

  5. (Hibernate进阶)Hibernate基本映射(三)

    介绍Hibernate的经典内容:对象关系映射.主要介绍映射的基本概念,映射的分类,映射文件. 概念 ORM(Object Relational Mapping),即对象关系映射.它的作用就是在关系型 ...

  6. Hibernate入门6.Hibernate检索方式

    Hibernate入门6.Hibernate检索方式 20131128 代码下载 链接: http://pan.baidu.com/s/1Ccuup 密码: vqlv Hibernate的整体框架已经 ...

  7. (Hibernate进阶)Hibernate搭建开发环境+简单实例(二)

    hibernate是非常典型的持久层框架,持久化的思想是非常值得我们学习和研究的.这篇博文,我们主要以实例的形式学习Hibernate,不深究Hibernate的思想和原理,否则,一味追求,苦学思想和 ...

  8. Hibernate 系列 04 - Hibernate 配置相关的类

    引导目录: Hibernate 系列教程 目录 前言: 通过上一篇的增删改查小练习之后,咱们大概已经掌握了Hibernate的基本用法. 我们发现,在调用Hibernate API的过程中,虽然Hib ...

  9. org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here

    org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not a ...

随机推荐

  1. Qt 之 QApplication

    1.QApplication QApplication类管理GUI程序的控制流和主要设置,是基于QWidget的,为此特化了QGuiApplication的一些功能,处理QWidget特有的初始化和结 ...

  2. Web前端基础怎么学? JavaScript、html、css知识架构图

    以前开发者只要掌握 HTML.CSS.JavaScript 三驾马车就能胜任一份前端的工作了.而现在除了普通的编码以外,还要考虑如何性能优化,如何跨端.跨平台实现功能,尤其是 AI.5G 技术的来临, ...

  3. python 03 8/25-8/27 range 、randint

    import random """字符串的操作中 三种方法,只包含左索引,不包含右索引""" hi= "bokeyuan pyth ...

  4. c++_核桃的数量

    #include <iostream> using namespace std; int gcd(int x,int y){ int temp; ){ temp=x%y; x=y; y=t ...

  5. oracle如何重做日志组

    1.查询数据库中的重做日志组 SQL> select * from v$log; GROUP# THREAD# SEQUENCE# BYTES BLOCKSIZE MEMBERS ARC STA ...

  6. ServletContext作用功能详解

    ServletContext,是一个全局的储存信息的空间,服务器开始,其就存在,服务器关闭,其才释放.request,一个用户可有多个:session,一个用户一个:而servletContext,所 ...

  7. Python2和Python3共存安装robotframework

    1.下载Python2.Python3安装包 https://www.python.org/ 2.下载pip.tar.gz https://pypi.python.org/pypi/pip#downl ...

  8. selenium grid使用(windows+centos7.4)

    windows作为hub,centos7.4作为node. firefox用的centos7自带的52版本,懒得更新. vm虚拟机必须设置成bridge模式上网,否则报错.具体参见博文:Vmware改 ...

  9. spring用到的设计模式

    https://www.cnblogs.com/yuefan/p/3763898.html https://www.cnblogs.com/hwaggLee/p/4510687.html https: ...

  10. xtu字符串 C. Marlon's String

    C. Marlon's String Time Limit: 2000ms Memory Limit: 65536KB 64-bit integer IO format: %lld      Java ...