1 开始使用Hibernate
- 什么是Hibernate
- 概念与作用
- 概念:Hibernate英文意义为冬眠。是开源的、用于封装数据访问层的组件,我们称之为数据访问层框架(戒持久层框架)
- 作用(Hibernate的出现解决了以下的事情):
- SQL语句过于繁杂, 和数据库的耦合度高。有些 SQL 会涉及到多表操作,或者有些表会非常庞大,这时候写在 DAO 中的SQL就会非常复杂,同时导致 DAO 和数据库的耦合度较高。
- 不同数据库之间SQL的不同,导致移植困难:不同数据库虽然 SQL 语句大致相同,但是还有一些细节上的差别,比如 Oracle 中的分页方式 和 mysql 中的分页是不同的,所以会有代码移植困难的因素。
- 二维关系表和对象之间数据结构的不匹配:我们从数据库中取出的数据是结果集(一张表),而我们开发时需将查询到的结果集封装为 对象,然而数据库中二维表的数据结构和内存中 Java 对象的数据结构是匹配的(表中的数 据需要经过处理才能变为 Java 对象)。
- 对象与关系型数据库(以下内容先做了解即可,过后会有详细讲解)
- 对象的三种状态:毕竟是要做高大上的程序员工作,让我们把英文的读音校准一下。Transient [‘trænziənt] (瞬时状态),Persistent [pə’sistənt] (持久状态),Detached [dɪ’tætʃt] (游离状态)
- 持久化:将处于 Persistent 状态的对象固化到数据库中的过程称为持久化。
- ORM映射:
- 对象关系映射(Object Relational Mapping,简称 ORM)将Java程序中的对象自动持久化到关系数据库中,反过来将数据库中的记录自动的读取到内存对象中。 以往我们开发一个应用程序,当需要用到数据的时候,需要访问数据库,这就需要编 写大量的代码去操纵数据库中的数据。我们的做法是将 java 对象中保存的数据拼写成 sql 语句,通过 sql 语句将对象中保存的数据更新或者增加到数据库中,或者将数据删除掉。 当我们需要数据库中的数据的时候,也是通过编写 sql 语句将数据查询出来,然后将一条 一条的结构化的数据在转换成 java 对象,供我们的应用程序使用。编写的代码基本上就 是从对象到数据库或者从数据库到对象。这些代码非常繁琐,而且容易出错,并且工作量 很大,占用了我们大量的开发时间。 有没有什么办法能将数据库中的表之间的关系与 java 对象之间的关系对应起来,将 java 对象之间的关系“映射”成数据库表之间的关系,或者将数据库表的关系“映射”成 java 脆响之间的关系。这就是ORM 了,即ORM 映射。 当我们要保存数据的时候,只需要保存对象,ORM 就会自动将对象映射到数据库表 中。ORM 所采取的办法就是将对象“翻译”成 SQL 语句交给数据库服务器,数据库服务 器根据 sql 语句对数据进行存取。 后面的图也要翻译。
- 搭建环境
- 获取Hibernate
-
到 hibernate 的官方网站去下载 hibernate 的 jar 包,地址为: http://www.hibernate.org/。
- 配置文件hibernate.cfg.xml
- 作用:配置数据库链接和 hibernate 运行时所需的各种属性hibernate初始化期间会自动在CLASSPATH中寻找这 个文件,并读取其中的配置信息。
- 建立:在 src 目录中新建这个 hibernate.cfg.xml 文件 。tips:可以在你于官网下载的Hibernate包中找到这个文件的模版。
1 <DOCTYPE hibernate-configuration PUBLIC 2 "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> 3 4 <hibernate-configuration> 5 6 <session-factory> 7 <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> 8 <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> 9 <!-- 因为&符号在 xml 文件中式一个特殊字符,所以使用的时候需要用&来替代 --> 10 <property name="hibernate.connection.url"> jdbc:mysql://localhost:3306/stuDB?useUnicode=true&characterEncoding=utf8 </property> 11 <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">root</property> <property name="show_sql">true</property> 12 </session-factory> 13 </hibernate-configuration>
- hibernate.cfg.xml属性解释
- 新建持久化类
1 public class Student implements Serializable { 2 3 4 private int id; 5 private String name; 6 private int age; 7 private String address; 8 //省略 getter 和 setter 方法还有构造方法 9 }
- 编写映射文件
- 映射文件:映射问价指定了上面编写的类与数据库中的哪个表进行映射。表的名字是什么,类的属性与表的哪 个字段对应,是什么数据类型等信息。命名方式是类名.hbm.xml.例如上面的Student类对应的映射文件就是Student.hbm.xml。映射文件通常与实体类放在一个包中。
- 建立映射文件:在下载的发行包中搜索*.hbm.xml,找到参考的 xml 文件。针对上面的Student类我们可以如下编写配置文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd” > 3 4 <hibernate-mapping package="com.company.po"> 5 6 <class name="Student" table="student"> 7 <id name="id" column="id" type="integer"> 8 <generator class="native"></generator> 9 </id> 10 <property name="name" column="name" type="string" /> 11 <property name="age" column="age" type="integer" /> 12 <property name="address" column="address" type="string" /> 13 </class> 14 </hibernate-mapping>
- 配置说明:
- <hibernate-mapping> 的 package 属性: 映射文件中 持久化类(也就是 class 标记 的 name 属性) 所在的包名,如果不指定则必须指定类的全名
- <class>标记中的 name 属性:指定要映射的持久化类
- <class>标记中的 table 属性:持久化类所对应的数据库的表名
- <id>: 定义了持久化类的唯一标识字段到数据 键字段的映射
- <id>标记中的 name 属性:持久化对象的唯一标识符,对应到类中的一个属性
- <id>标记中的 column 属性:数据库中的主键列
- <id>标记中的 type 属性: 持久化类的唯一标识的类型
- <id> 的子标记<generator>:主键生成方式
- <property> :非主键属性到数据库中非主键的映射关系
- 将映射文件配置到hibernate.cfg.xml:在 hibernate.cfg.xml 文件中的session-factory标签对中添加子标签
<mapping resource=“com/company/po/Student.hbm.xml"/>
- 可选:配置日志。为了使得开发过程更加直观,需要调整 Hibernate 日志选项以便观察运行的细节 。在 发行包的 etc 目录中附带了一个示例配置 log4j.properties.将这个文件复制到工程的 src 目 录中,并将 log4j 的 jar 包加入到项目中。
- 运行
- 常见主键生成方式:
- assigned:主键由外部程序负责生成,无需Hibernate参与
- increment:自增1,与底层无关,Mysql mssql,oracle都支持,缺点是线程不安全,可能会出现相同的主键。
- hilo:高低位。是hibernate中最常用的一种生成方式,需要一张额外的表保存hi的值。保存hi值的表至少有一条记录(只与第一条记录有关),否则会出现错误。可以跨数据库。采用数据库提供的sequence机制生成主键,需要数据库支持
- sequence:如oralce、DB、SAP DB、PostgerSQL、McKoi中的sequence。MySQL这种不支持sequence的数据库则不行(可以使用identity)
- identity:由底层数据库生成标识符。identity是由数据库自己生成的,但这个主键必须设置为自增长,使用identity的前提条件是底层数据库支持自动增长字段类型,如DB2、SQL Server、MySQL、Sybase和HypersonicSQL等,Oracle这类没有自增字段的则不支持。
- uuid.hex:由Hibernate基于128位唯一产生算法生成16进制数值
- nativenative由hibernate根据使用的数据库自行判断采用identity、hilo、sequence其中一种作为主键生成方式,灵活性很强。如果能支持identity则使用identity,如果支持sequence则使用sequence。
- foreign使用另外一个相关联的对象的主键作为该对象主键。主要用于一对一关系中。
- 数据类型映射(Java-Hibernate数据类型映射表)
To be someone special