1. hibernate框架java
框架的含义:mysql
javaEE三层开发框架及hibernate框架对应的位置以下:程序员
Hibernate框架优势: 操做数据库的时候,能够以面向对象的方式来完成.不须要书写SQL语句web
Hibernate框架:是当今主流的Java持久层框架之一,因为它具备简单易学、灵活性强、扩展性强等特色,可以大大地简化程序的代码量,提升工做效率,所以受到广大开发人员的喜好。sql
Hibernate是一个开放源代码的ORM(object relationship mapping,关系对象映射)框架,它对JDBC进行了轻量级的对象封装,使得Java开发人员可使用面向对象的编程思想来操做数据库。数据库
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了很是轻量级的对象封装,它将POJO与数据库表创建映射关系,是一个全自动的orm框架,hibernate能够自动生成SQL语句,自动执行,使得Java程序员能够为所欲为的使用对象编程思惟来操纵数据库。 Hibernate能够应用在任何使用JDBC的场合,既能够在Java的客户端程序使用,也能够在Servlet/JSP的Web应用中使用,最具革命意义的是,Hibernate能够在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任。编程
为何学习Hibernate?缓存
使用传统的JDBC开发应用系统时,若是是小型应用系统,并不以为有什么麻烦,可是因为大型应用系统的开发,使用JDBC就会显得力不从心。例如对几10、几百张包含几十个字段的表进行插入操做时,编写的SQL语句不但很长,并且繁琐,容易出错;在读取数据时,须要写多条getXxx语句从结果集中取出各个字段的信息,不但枯燥重复,而且工做量很是大。为了提升数据访问层的编程效率,Gravin King开发出了一个当今最流行的ORM框架,它就是Hibernate框架。安全
所谓的ORM就是利用描述对象和数据库表之间映射的元数据,自动把Java应用程序中的对象,持久化到关系型数据库的表中(自动建立表)。经过操做Java对象,就能够完成对数据库表的操做。能够把ORM理解为关系型数据和对象的一个纽带,开发人员只须要关注纽带一端映射的对象便可。ORM原理:session
与其它操做数据库的技术相比,Hibernate具备如下优点:
orm分4级
hibernate属于4级:彻底面向对象操做数据库
mybatis属于2级
dbutils属于1级
Hibernate5.0.7的目录介绍:
2. Hibernate入门
框架搭建
lib/required子目录中,包含的JAR包
驱动包
日志记录包
持久化类是应用程序中的业务实体类,这里的持久化是指类的对象可以被持久化保存到数据库中。
Hibernate使用普通Java对象(Plain Old Java Object),即POJO的编程模式来进行持久化。POJO类中包含的是与数据库表相对应的各个属性,这些属性经过getter和setter方法来访问,对外部隐藏了内部的实现细节。下面就来编写Customer持久化类。
在项目src目录下,建立cn.eagle.domain包,并在保重建立类Customer(对应数据库表cst_customer),Customer类包含了与cst_customer数据表字段对应的属性,以及相应的getXxx()和setXxx()方法。
1 package cn.eagle.domain; 2 3 public class Customer { 4 5 private Long cust_id; 6 private String cust_name; 7 private String cust_source; 8 private String cust_industry; 9 private String cust_level; 10 private String cust_phone; 11 private String cust_mobile; 12 13 public Long getCust_id() { 14 return cust_id; 15 } 16 17 public void setCust_id(Long cust_id) { 18 this.cust_id = cust_id; 19 } 20 21 public String getCust_name() { 22 return cust_name; 23 } 24 25 public void setCust_name(String cust_name) { 26 this.cust_name = cust_name; 27 } 28 29 public String getCust_source() { 30 return cust_source; 31 } 32 33 public void setCust_source(String cust_source) { 34 this.cust_source = cust_source; 35 } 36 37 public String getCust_industry() { 38 return cust_industry; 39 } 40 41 public void setCust_industry(String cust_industry) { 42 this.cust_industry = cust_industry; 43 } 44 45 public String getCust_level() { 46 return cust_level; 47 } 48 49 public void setCust_level(String cust_level) { 50 this.cust_level = cust_level; 51 } 52 53 public String getCust_phone() { 54 return cust_phone; 55 } 56 57 public void setCust_phone(String cust_phone) { 58 this.cust_phone = cust_phone; 59 } 60 61 public String getCust_mobile() { 62 return cust_mobile; 63 } 64 65 public void setCust_mobile(String cust_mobile) { 66 this.cust_mobile = cust_mobile; 67 } 68 69 @Override 70 public String toString() { 71 return "Customer [cust_id=" + cust_id + ", cust_name=" + cust_name + ", cust_source=" + cust_source 72 + ", cust_industry=" + cust_industry + ", cust_level=" + cust_level + ", cust_phone=" + cust_phone 73 + ", cust_mobile=" + cust_mobile + "]"; 74 } 75 76 }
实体类Customer目前还不具有持久化操做的能力,而Hibernate须要知道实体类Customer映射到数据库Hibernate中的哪一个表,以及类中的哪一个属性对应数据库表中的哪一个字段,这些都须要在映射文件中配置。
在实体类Customer所在的包中,建立一个名称为Customer.hbm.xml的映射文件,在该文件中定义了实体类Customer的属性是如何映射到cst_customer表的列上的。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 3 <hibernate-mapping> 4 <class name="cn.eagle.domain.Customer" table="cst_customer"> 5 <id name="cust_id" column="cust_id"> 6 <generator class="native"></generator> 7 </id> 8 <property name="cust_name" column="cust_name"></property> 9 <property name="cust_source" column="cust_source"></property> 10 <property name="cust_industry" column="cust_industry"></property> 11 <property name="cust_level" column="cust_level"></property> 12 <property name="cust_phone" column="cust_phone"></property> 13 <property name="cust_mobile" column="cust_mobile"></property> 14 </class> 15 </hibernate-mapping>
Hibernate的映射文件反映了持久化类和数据库表的映射信息,而Hibernate的配置文件则主要用来配置数据库链接以及Hibernate运行时所须要的各个属性的值。在项目的src下建立一个名称为hibernate.cfg.xml的文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd" > 3 <hibernate-configuration> 4 <session-factory> 5 <property name="hibernate.connection.dirver_class">com.mysql.jdbc.Driver</property> 6 <property name="hibernate.connection.url">jdbc:mysql:///day24_db</property> 7 <property name="hibernate.connection.username">root</property> 8 <property name="hibernate.connection.password">toor</property> 9 <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> 10 <property name="hibernate.show_sql">true</property> 11 <property name="hibernate.format_sql">true</property> 12 <property name="hibernate.hbm2ddl.auto">update</property> 13 <mapping resource="cn/eagle/domain/Customer.hbm.xml"/> 14 </session-factory> 15 </hibernate-configuration>
3. Hibernate配置文件详解
在以上部分中,咱们已经接触过Hibernate的映射文件和配置文件。接下来,将对这些文件进行详细的讲解。
<?xml version="1.0" encoding="UTF-8"?>
<!-- 映射文件的dtd信息 -->
<!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:完整类名;
table:数据库表名。(若是类名和表名是一致的,那么table属性能够省略) -->
<class name="cn.eagle.domain.Customer" table="cst_customer">
<!-- id元素:配置主键映射的属性
name:主键对应的属性名;
column(可选):填写表中的主键列名。默认值:列名会默认使用属性名;
type(可选):填写列(属性)的类型。Hibernate会自动检测实体的属性类型。
每一个类型有三种填法:java类型|hibernate类型(默认)|数据库类型;
not-null(可选):配置该属性(列)是否不能为空。默认值:false
length(可选):配置数据库中列的长度,默认值:使用数据库类型的最大长度
-->
<id name="cust_id" column="cust_id">
<generator class="native"></generator> // 主键的生成策略
</id>
<!-- 其它属性使用property标签来映射 -->
<property name="cust_name" column="cust_name"></property>
<property name="cust_source" column="cust_source"></property>
<property name="cust_industry" column="cust_industry"></property>
<property name="cust_level" column="cust_level"></property>
<property name="cust_phone" column="cust_phone"></property>
<property name="cust_mobile" column="cust_mobile"></property>
</class>
</hibernate-mapping>
映射文件一般是一个xml文件便可,但通常命名为类名.hbm.xml
上述两种配置文件是等价的,具体使用哪一个能够自由选择。XML格式的配置文件更易于修改,配置能力更强,当改变低层应用配置时不须要改变和从新编译代码,只修改配置文件的相应属性便可,而properties格式的文件则不具备次优点,所以,在实际开发项目中,大多数状况会使用XML格式的配置文件。下面将对XML格式的配置文件进行详细介绍。
hibernate.cfg.xml配置文件通常在开发时会放置在src的源文件夹下,发布后,该文件会在项目的WEB-INF/classes路径下。配置文件的经常使用配置信息以下所示。
<?xml version="1.0" encoding="UTF-8"?>
<!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>
<!-- 5个必选链接数据库基本参数属性
hibernate.connection.dirver_class 数据库驱动
hibernate.connection.url 数据库url
hibernate.connection.username 数据库链接用户名
hibernate.connection.password 数据库链接密码
hibernate.dialect 数据库方言,不一样的数据库中,sql语法略有区别,
指定方言可让hibernate框架在生成sql语句时,针对数据库的方言生成;
sql99标准:DDL 定义语言 库表的增删改查
DCL 控制语言 事务、权限
DML 操纵语言 增删改查
注意: Mysql在选择方言时,请选择最短的方言
hibernate.connection.autocommit 可选,事务是否自动提交
-->
<property name="hibernate.connection.dirver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///day24_db</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">toor</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 3个可选属性
hibernate.show_sql 将hibernate生成的sql语句打印到控制台
hibernate.format_sql 将hibernate生成的sql语句格式化(语法缩进)
hibernate.hbm2ddl.auto (auto scheme export 自动导出表结构,自动建表)
create: 自动建表.每次框架运行都会建立新的表,之前的表将会被覆盖,表数据会丢失。(开发环境中测试使用)
create-drop: 自动建表。每次框架运行结束都会将全部表删除。(开发环境中测试使用)
update: 推荐使用 自动生成表,若是已经存在不会再生成,若是表有变更,自动更新表(不会删除任何数据)
validate: 校验 不自动生成表。每次启动会校验数据库中表是否正确,只会使用原有的表 -->
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 引入orm源数据
路径书写:填写src下的路径 -->
<mapping resource="cn/eagle/domain/Customer.hbm.xml" />
</session-factory>
</hibernate-configuration>
4. Hibernate API详解
Configuration主要用于Hibernate框架加载映射文件,它的做用是对Hibernate进行配置,以及对它进行启动。在Hibernate的启动过程当中,Configuration类的实例首先定位映射文档的位置,读取这些配置,而后建立一个SessionFactory对象。虽然Configuration类在整个Hibernate项目中只扮演着一个很小的角色,但他是启动hibernate时所遇到的第一个对象;
Configuration实例用于启动、加载、管理hibernate的配置文件信息。在启动Hibernate的过程当中,Configuration实例首先肯定Hibernate配置文件的位置,而后读取相关配置,最后建立一个惟一的SessionFactory实例。Configuration对象只存在于系统的初始化阶段,它将SessionFactory建立完成后,就完成了本身的使命。
Configuration cfg = new Configuration().configure();
此种方式默认会去src下读取hibernate.cfg.xml配置文件。若是不想使用默认的hibernate.cfg.xml配置文件,而是使用指定目录下(或自定义)的配置文件,则须要向configuration()方法中传递一个文件路径的参数便可。
也可使用该对象加载映射文件:
configuration.addResource("cn/eagle/domain/Customer.hbm.xml");
该接口负责初始化Hibernate。它充当数据存储源的代理,并负责建立Session对象。这里用到了工厂模式。须要注意的是SessionFactory并非轻量级的,由于通常状况下,一个项目一般只须要一个SessionFactory就够,当须要操做多个数据库时,能够为每一个数据库指定一个SessionFactory。
SessionFactory接口负责Hibernate的初始化和创建Session对象。它在Hibernate中起到一个缓冲区做用,Hibernate能够将自动生成的SQL语句、映射数据以及某些可重复利用的数据放在这个缓冲区中。同时它还保存了对数据库配置的全部映射关系,维护了当前的二级缓存。
SessionFactory实例是经过Configuration对象获取的,其获取方法以下所示:
SessionFactory sessionFactory = cfg.buildSessionFactory();
它的特色以下:
1. 它是线程安全的,它的同一个实例可以供多个线程共享。
2. 它是重量级的,不能随意的建立和销毁它的实例
3. 负责保存和使用全部配置信息,消耗内存资源很是大
4. 保证在web项目中,值建立一个SessionFactory
因为SessionFactory的这些特色,通常状况下,一个项目中只须要一个SessionFactory,只有当应用中存在多个数据源时,才为每一个数据源创建一个SessionFactory实例。所以,在实际项目使用中,一般会抽取出一个HibernateUtils的工具类,用来提供Session对象。
SessionFactory内部还维护了一个链接池,若是咱们须要使用第三方的链接池如C3P0,那么须要咱们本身手动进行配置
<!-- 配置C3P0链接池 -->
<property name="connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider</property>
<!-- 在链接池中可用的数据库链接的最少数目 -->
<property name="c3p0.min_size">5</property>
<!-- 在链接池中全部数据库链接的最大数目 -->
<property name="c3p0.max_size">20</property>
<!-- 设定数据库链接的过时时间,以秒为单位,若是链接池中的某个数据库链接处于
空闲状态的时间超过了timeout时间,就会从链接池中清除 -->
<property name="c3p0.timeout"></property>
<!-- 每3000秒检查全部链接池中的空闲链接,以秒为单位 -->
<property name="c3p0.idle_test_period">3000</property>
测试C3P0链接池
新建测试单元
1 package cn.eagle.test; 2 3 import static org.junit.Assert.*; 4 5 import java.sql.Connection; 6 import java.sql.SQLException; 7 8 import org.hibernate.Session; 9 import org.hibernate.SessionFactory; 10 import org.hibernate.Transaction; 11 import org.hibernate.cfg.Configuration; 12 import org.hibernate.jdbc.Work; 13 import org.junit.After; 14 import org.junit.Before; 15 import org.junit.Test; 16 17 public class HibernateTestC3P0 { 18 private SessionFactory sessionFactory; 19 private Session session; 20 private Transaction transaction; 21 22 @Before 23 public void init() { 24 Configuration configuration = new Configuration().configure(); 25 sessionFactory = configuration.buildSessionFactory(); 26 session = sessionFactory.openSession(); 27 transaction = session.beginTransaction(); 28 } 29 30 @After 31 public void destroy() { 32 transaction.commit(); 33 session.close(); 34 sessionFactory.close(); 35 } 36 37 @Test 38 public void test() { 39 session.doWork(new Work() { 40 41 @Override 42 public void execute(Connection conn) throws SQLException { 43 System.out.println(conn); 44 } 45 46 }); 47 } 48 49 }
Session接口负责执行被持久化对象的CRUD操做(CRUD的任务是完成与数据库的交流,包含了不少常见的SQL语句)。但须要注意的是Session对象是非线程安全的。同时,Hibernate不一样于JSP应用中的HttpSession。这里当使用session这个术语时,其实指的是Hibernate中的session,而之后会将HttpSession对象称为用户session。
Session是应用程序与数据库之间交互操做的一个单线程对象,是Hibernate运做的中心,它的主要功能是为持久化对象提供建立、读取和删除的能力,全部持久化对象必须在session的管理下才能够进行持久化操做。
建立SessionFactory实例后,就能够经过它获取Session实例。获取Session实例有两种方式,
一种是经过openSession()方法,另一种是经过getCurrentSession()方法。两种方法获取session的代码以下所示:
Session session = sessionFactory.openSession();
Session session = sessionFactory.getCurrentSession();
以上两种获取session实例方式的主要区别是,采用openSession方法获取Session实例时,SessionFactory直接建立一个新的Session实例,而且在使用完成后须要调用close方法进行手动关闭。而getCurrentSession方法建立的Session实例会被绑定到当前线程中,它在提交或回滚操做时会自动关闭。
Session是线程不安全的,多个并发线程同时操做一个Session实例时,就可能致使Session数据存取的混乱(方法内部定义和使用Session时,不会出现线程问题)。所以设计软件架构时,应避免多个线程共享一个Session实例。同时,它也是轻量级的,实例的建立和销毁不须要消耗太多的资源。它还有给个缓存,即Hibernate的一级缓存,这个缓存主要用于存放当前工做单元加载的对象。
在Session中提供了大量的经常使用方法,具体以下:
1. save()、update()和saveOrUpdate()方法:用于增长和修改对象。
2. delete()方法:用于删除对象。
3. get()和load()方法:根据主键查询。
4. createQuery()和createSQLQuery()方法:用于数据库操做对象。
5. createCriteria()方法:条件查询。
Transaction接口是一个可选的API,能够选择不适用这个接口,取而代之的是Hibernate的设计者本身写的底层事务处理代码。Transaction接口是对实际事务实现的一个抽象,这些实现包括JDBC事务、JTA中的UserTransaction、甚至能够是CORBA事务。之因此这样设计是能让开发者可以使用一个统一事务的操做界面,使得本身的项目能够在不一样的环境和容器之间方便地移植。
Transaction接口主要用于管理事务,它是Hibernate的数据库事务接口,且对底层的事务接口进行了封装。Transaction接口的事务对象是经过Session对象开启的,其开启方式以下所示。
Transaction tx = session.beginTransaction();
在Transaction接口中,提供了事务管理的经常使用方法,具体以下:
1. commit()方法:提交相关联的session实例。
2. rollback()方法: 撤销事务操做。
Session执行完数据库操做后,要使用Transaction接口的commit()方法进行事务提交,才能真正的将数据库操做同步到数据库中。发生异常时,须要使用rollback()方法进行事务回滚,以免数据发生错误。所以,在持久化操做后,必须调用Transaction接口的commit()方法和rollback()方法。若是没有开启事务,那么每一个Session操做,都至关于一个独立的操做。