Hibernate

mark

持久化

即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。持久化的主要应用是将内存中的数据存储在关系型的数据库中,当然也可以存储在磁盘文件中、XML 数据文件中等等,那么什么是持久层(Persistence Layer),即专注于实现数据持久化应用领域的某个特定系统的一个逻辑层面,将数据使用者和数据实体相关联。

持久化是将程序数据在持久状态和瞬时状态间转换的机制。比如 JDBC 就是一种持久化机制。文件 IO 也是一种持久化机制。

广义的理解,”持久化” 包括和数据库相关的各种操作:
保存:把对象永久保存到数据库中。
更新:更新数据库中对象 (记录) 的状态。
删除:从数据库中删除一个对象。
查询:根据特定的查询条件,把符合查询条件的一个或多个对象从数据库加载到内存中。
加载:根据特定的 OID,把一个对象从数据库加载到内存中

ORM

对象关系映射 Object Relational Mapping,一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。从效果上说,它其实是创建了一个可在编程语言里使用的 ——“虚拟对象数据库”。
| 面向对象概念 | 面向关系概念 |
| :—————- | :——————- |
| 类 | 表 |
| 对象 | 表的行(记录) |
| 属性 | 表的列(字段) |

ORM 的思想:将关系数据库中表中的记录映射成为对象,以对象的形式展现,程序员可以把对数据库的操作转化为对对象的操作。

ORM 采用元数据来描述对象 —— 关系映射细节, 元数据通常采用 XML 格式,并且存放在专门的对象 —— 关系映射文件中.

那么什么是元数据呢?
元数据是一种描述数据的数据,任何文件系统中的数据分为数据和元数据。数据是指普通文件中的实际数据,而元数据指用来描述一个文件的特征的系统数据,诸如访问权限、文件拥有者以及文件数据块的分布信息等等,其实在 Linux 文件系统中元数据就是 INode!
mark

hibernate

hibernate 为应用程序提供了高效的 O/R 关系映射和查询服务,为面向对象的领域模型到传统的关系型数据库的映射,提供了一个使用方便的框架。

hibernate 的 Helloworld

hibernate 这个框架呢我还是从 helloworld 开始复习,第一步纯粹当做是预习了,首先说一下普通的 Java 工程中如何使用 hibernate 框架,Java 版本的 HelloWorld 正式开始!

首先需要一些 jar 包(点击这里即可下载),我要说明的是这些 jar 包的 hibernate 版本是 4.2,如果你需要新的去网上下载就好了!接着我使用的 eclipse 演示这个额 HelloWorld 程序,需要安装一个 hibernate 的插件:
在 workwith 里面输入:http://download.jboss.org/jbosstools/updates/stable/kepler/
mark

我的项目目录结构就是这样了:
mark
hibernate.cfg.xml 是通过刚才安装的 eclipse 的 hibernate 插件生成的,内容如下 (指定关联的 .hbm.xml 文件是后面生成的):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?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>
<!-- 指定数据库的驱动、用户名、密码 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.password">1234</property>
<property name="hibernate.connection.url">jdbc:mysql://127.0.0.1/hibernate4</property>
<property name="hibernate.connection.username">root</property>

<!-- 重点,这里容易出错,最常使用 MySQL5InnoDBDialect 或者 MySQLInnoDBDialect -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>

<!-- 在执行过程中打印 sql 语句 -->
<property name="show_sql">true</property>
<!-- 将打印的 sql 语句格式化 -->
<property name="format_sql">true</property>
<!-- 指定自动生成数据表的策略 -->
<property name="hbm2ddl.auto">update</property>

<!-- 设置 Hibernate 的事务隔离级别 -->
<property name="connection.isolation">2</property>

<!-- 指定关联的 .hbm.xml 文件 -->
<mapping resource="com/xpu/demo_01/News.hbm.xml"/>

</session-factory>
</hibernate-configuration>

从上面也可以看出来,hibernate.cfg.xml 是 hibernate 的基本配置信息,在 JDBC 阶段就已经接触过,我就不在此一一细说了,接下来我们需要一个实体类来对应表,类的对象来对应表的记录,于是此设计如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.xpu.demo_01;

import java.util.Date;

public class News {
private Integer id;
private String title;
private String author;
private Date date;
public News() {
super();
}
//ID 我们在数据库中设定的是自增,所以不在构造方法的参数中
public News(String title, String author, Date date) {
super();
this.title = title;
this.author = author;
this.date = date;
}
public Integer getId() {...}
public void setId(Integer id) {...}
public String getTitle() {...}
public void setTitle(String title) {...}
public String getAuthor() {...}
public void setAuthor(String author) {...}
public Date getDate() {...}
public void setDate(Date date) {...}
@Override
public String toString() {...}
}

根据此类生成一个对象关系映射文件,就是 News.hbm.xml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2019-1-30 13:27:35 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
<class name="com.xpu.demo_01.News" table="NEWS">
<id name="id" type="java.lang.Integer">
<!-- 主键自增让数据库原生的去操作 -->
<column name="ID" />
<generator class="native" />
</id>
<property name="title" type="java.lang.String">
<column name="TITLE" />
</property>
<property name="author" type="java.lang.String">
<column name="AUTHOR" />
</property>
<property name="date" type="java.sql.Date">
<column name="DATE" />
</property>
</class>
</hibernate-mapping>

相信这个还是非常容易明白的,ID 主键自增让数据库原生的去操作,所以 generaor 配置的是 native,其他的内容标题、作者等都是 String 类型,时间就是 Java 的 java.util.Date 类型,这样就建立了类的属性和表的字段的关系,这很关键!
接下来就该使用代码去操作了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.xpu.demo_01;

import java.util.Date;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

public class HibnateTest1 {
public void main(String [] args) {

// 1、创建配置对象 负责加载配置文件
Configuration configuration = new Configuration().configure ();

// 2、创建一个 ServiceRegistry 对象,hibernate 的任何配置和服务都需要在该对象中注册后才能有效.
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings (configuration.getProperties ())
.buildServiceRegistry ();
// 3、创建一个 SessionFactory 对象
SessionFactory sessionFactory = configuration.buildSessionFactory (serviceRegistry);

// 4、获得 Session 对象
Session session = sessionFactory.openSession ();

// 5、开启事务
Transaction transaction = session.beginTransaction ();

// 6、创建对象,通过 Session 保存相应的数据至数据库
News tabledataEntity = new News("Java", "Tim", new Date());
session.save (tabledataEntity);

// 6.1 获取对象(如果你之前保存过一条数据,那么此时也可以取出)
// News news2 = (News) session.get (News.class, 15);
// System.out.println (news2);

// 7、提交事务
transaction.commit ();

// 8、关闭 Session
session.close ();

// 9、关闭 SessionFactory
sessionFactory.close ();
}
}

执行完毕后,数据库的表中就会多一条数据,如果失败,可能是由于编码问题导致的,我的 eclipse 工程配置的都是 UTF-8 的编码,你可以在项目属性中尝试如下编码配置方式:
mark
普通 Java 工程的 hibernate 的 Helloworld 就说完了,API 以后再慢慢解释,下面说一下 Maven 工程下如何搭建这个 Helloworld,Maven 的依赖如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.2.4.Final</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-c3p0 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>4.2.4.Final</version>
</dependency>

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>

与普通 Java 工程不同之处就在于 News.hbm.xml 文件和 hibernate.cfg.xml 文件的放置位置,很显然在 Maven 下,这两个文件都可以放在 resource 目录下:
mark
只不过稍微有点不同的是:在 hibernate.cfg.xml 中配置 News.hbm.xml 的位置的时候,直接写名字就好了!