Hibernate是一款优秀的持久化ORM框架;解决持久化操作,使得程序员可以从编写繁复的JDBC工作中解放出来,专注于业务,提高程序员开发效率;并且具有可靠的移植性,降低了系统耦合度;
2.1 持久(Persistence),即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。
持久化的主要应用是将内存中的数据存储在关系型的数据库中,当然也可以存储在磁盘文件中、XML数据文件中等等。Hibernate当中叫做加载。
1. 狭义概念:数据存储在物理介质不会丢失
2. 广义概念:对数据的CRUD操作都叫做持久化
3. 加载:Hibernate的概念是数据从数据库加载到session
2.2 ORM
O-Object,R-Relation,M-Mapping,顾名思义就是对象(JavaBean)关系(关系型数据库)映射。它的作用是在关系型数据库和对象之间作一个映射,这样,我们在具体的操作数据库的时候,就不需要再去和复杂的SQL语句打交道,只要像平时操作对象一样操作它就可以了 。
1.1创建项目:创建maven---quikstart项目
1.2 添加hibernate核心依赖:
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.3.7.Final</version>
1.3编写核心配置文件hibernate.cfg.xml
<?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="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/test</property>
<property name="connection.username">root</property>
<property name="connection.password">shsxt</property>
<!-- 数据库方言 -->
<property name="dialect">org.hibernate.dialect.MySQL57Dialect</property>
<!-- 数据库更新方式 -->
<property name="hbm2ddl.auto">update</property>
<!-- 添加*.hbm.xml映射 -->
<mapping resource="com/sxt/pojo/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
主要配置连接数据库的相关信息
1.4编写*.hbm.xml配置文件
*一般为POJO类名称,比如User.hbm.xml,该文件放在POJO类所在包下。从官方下载的资源包当中搜索.hbm.xml,随便找一个该后缀结尾的文件至POJO类所在包下且重命名为User.hbm.xml。
1.5编写测试类
package com.sxt;
import com.sxt.pojo.User;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.junit.Test;
public class HibernateTest {
@Test
public void testSave() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null;
try {
// 注册服务
StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
.configure() // 默认加载 hibernate.cfg.xml
.build();
// 通过元数据对象创建SessionFactory
sessionFactory = new MetadataSources( registry )
.buildMetadata().buildSessionFactory();
// 通过工厂对象创建Session
session = sessionFactory.openSession();
// 通过Session创建事务并开启事务
tx = session.beginTransaction();
// 保存对象
User user = new User();
user.setUsername("张三");
user.setPassword("123456");
session.save(user);
// 提交事务
tx.commit();
} catch (Exception e) {
e.printStackTrace();
// 回滚事务
tx.rollback();
} finally {
if (null != session && session.isOpen())
session.close();// 关闭Session
}
}
}
1.7测试结果在数据库中显示
@Test
public void testConfig() {
// 读取src下hibernate.properties,不推荐使用
Configuration cfg1 = new Configuration();
// 默认读取src下的hibernate.cfg.xml,推荐
Configuration cfg2 = new Configuration().configure();
// 如果hibernate的核心配置文件不叫hibernate.cfg.xml,比如hb.cfg.xml
Configuration cfg3 = new Configuration().configure("hb.cfg.xml");
// 可编程式,可以不使用配置文件
//cfg.addProperties();
//cfg.addResource()
@Test
public void testSessionFactory() {
// 默认读取src下的hibernate.cfg.xml,推荐
Configuration cfg = new Configuration().configure();
// 通过Configuration创建SessionFactory对象
// 在hibernate3.x中是这种写法
SessionFactory sf1 = cfg.buildSessionFactory();
// 在hibernate4.x中是这种写法
StandardServiceRegistry sr = new StandardServiceRegistryBuilder()
.applySettings(cfg.getProperties()).build();
SessionFactory sf2 = cfg.buildSessionFactory(sr);
// 在hibernate5.x中是这种写法,不需要自己创建Configuration()对象
StandardServiceRegistry serviceRegistry = new
StandardServiceRegistryBuilder().configure().build();
SessionFactory sessionFactory = new MetadataSources(serviceRegistry).buildMetadata()
.buildSessionFactory();
}
Session 接口对于Hibernate 开发人员来说是一个最重要的接口。在Hibernate中,实例化的Session是一个轻量级的类,创建和销毁它都不会占用很多资源。这在实际项目中非常很重要,因为在程序中,可能会不断地创建以及销毁Session对象,如果Session 的开销太大,会给系统带来不良影响。但是Session对象是非线程安全的,因此在你的设计中,最好是一个线程只创建一个Session对象。 Session可以看作介于数据连接与事务管理一种中间接口。我们可以将Session想象成一个持久对象的缓冲区,Hibernate能检测到这些持久对象的改变,并及时刷新数据库。我们有时也称Session是一个持久层管理器,因为Session负责执行被持久化对象的增、删、改、查操作,类似于JDBC的Connection和Statement, 诸如存储持久对象至数据库,以及从数据库从获得它们。需要注意的是,Hibernate的Session不同于JSP 应用中的HttpSession。在Hibernate中,我们使用Session这个术语时,指的是Hibernate 自己的Session.
@Test
public void testSession() {
// 在hibernate5.x中是这种写法,不需要自己创建Configuration()对象StandardServiceRegistry serviceRegistry = newStandardServiceRegistryBuilder().configure().build();
SessionFactory sessionFactory = newMetadataSources(serviceRegistry).buildMetadata().buildSessionFactory();
// 通过SessionFactory得到Session
Session session = sessionFactory.openSession()
负责事务相关的操作,它代表的是Hibernate事务,本质上也是数据库事务。一般在Hibernate的增删改中出现,但是使用Hibernate一般使用Spring去管理事务。
@Test
public void testTransaction() {
// 在hibernate5.x中是这种写法,不需要自己创建Configuration()对象
StandardServiceRegistry serviceRegistry = newStandardServiceRegistryBuilder().configure().build();
SessionFactory sessionFactory = newMetadataSources(serviceRegistry).buildMetadata().buildSessionFactory();
// 通过SessionFactory得到Session
Session session = sessionFactory.openSession();
// 第一种写法,创建对象并直接开启事务
Transaction tx1 = session.beginTransaction();
// 第二种写法,只是创建对象而已,需要调用begin()开启事务
Transaction tx2 = session.getTransaction();tx2.begin()
负责执行各种数据查询功能,它可以使用Hibernate特有的HQL语言和SQL语言两种方式。
1.对象状态及生命周期:
瞬时状态:刚刚使用new语句创建,还没有被持久化,不处于Session的缓存中。处于临时状态的Java对象被称为临时对象。Session中没有,数据库中没有。
持久化状态:已经被持久化,加入到Session的缓存中。处于持久化状态的Java对象被称为持久化对象。Session中有,数据库中有。
游离状态:已经被持久化,但不处于Session的缓存中。处于游离状态的Java对象被称为游离对象。Session中没有,数据库中有.
瞬时状态转为持久状态使用Session对象的save()或saveOrUpdate()方法保存对象后,该对象的状态由瞬时状态转换为持久状态。使用Session对象的get()或load()方法获取对象,该对象的状态是持久状态。
持久状态转为瞬时状态执行Session对象的delete()方法后,对象由原来的持久状态变为瞬时状态,因为此时该对象没有与任何的数据库数据关联。
持久状态转为游离状态执行了Session对象的evict()、clear()或close()方法,对象由原来的持久状态转为游离状态。
游离状态转为持久状态重新获取Session对象,执行Session对象的update()或saveOrUpdate()方法,对象由游离状态转为持久状态,该对象再次与Session对象相关联。
游离状态转为瞬时状态执行Session对象的delete()方法,对象由游离状态转为瞬时状态。处于瞬时状态或游离状态的对象不再被其他对象引用时,会被Java虚拟机按照垃圾回收机制处理.
get/load的区别:get会立即去查询对象,load在使用才去查询(懒加载),get找不到对象时返回null,load找不到对象时抛异常.
Hibernate方言是用来告诉Hibernte如何对指定的数据库生成相应的SQL语句。
尽管做了很多尝试去使SQL语句标准化,但是不同的数据库支持的SQL语句还是有很多不同的地方。所以Hibernate使用方言来辅助生成正确的SQL语句.
MySQLDialect与MySQL5Dialect的区别:MySQLDialect是针对MySQL5之前的版本。主要变化还是在于建表SQL语句。MySQL由于4到5还是有不小的变化。比如varchar在4及之前版本最大长度限制为255,5.0.3X之后版本最大长度限制为65535。MySQLInnoDBDialect会在生成的建表SQL语句最后加上"TYPE=InnoDB”.
简单来说Hibernate是ORM映射的持久层框架,全称是(Object Relational Mapping),即对象关系映射。它将数据库中的表映射成对应的对象,以对象的形式展现,这样我们就可以通过映射的对象来对数据库中的数据进行间接的操作。映射关系是将数据库中的表映射成与之相对应的对象,当你对这个对象进行操作的时候,Hibernate会对数据库中对应的表执行相应的操作,你对该实体的操作实际上就是在间接的操作数据库中与之相对应的表。Hibernate正是实现了这种思想,达到了方便开发人员以面向对象的思想来实现对数据库的操作.
Hibernate在实现ORM功能的时候主要用到的文件有:映射类 *.Java 、映射文件 *.hbm.xml 和数据库配置文件 *.properties/*.cfg.xml ,它们各自的作用如下。
映射类 *.java :它是描述数据库表的结构,表中的字段在类中被描述成属性,将来就可以实现把表中的记录映射成为该类的对象了。
映射文件 *.hbm.xml :它是指定数据库表和映射类之间的关系,包括映射类和数据库表的对应关系、表字段和类属性类型的对应关系以及表字段和类属性名称的对应关系等。
数据库配置文件 *.properties/*.cfg.xml :它是指定与数据库连接时需要的连接信息,比如连接哪种数据库、登录数据库的用户名、登录密码以及连接字符串等。当然还可以把映射类的地址映射信息放在这里.
1.1 BLOB,CLOB数据的处理
1.1.1 编写实体类
1.1.2 编写配置文件
1.1.3 进行测试
2.1 什么是组件映射:组件映射实际上就是将组合关系的数据映射成一张表,组件类和被包含的组件类映射成一张表。有的时候,两个类的关系明显不是继承关系,但两个类的亲密程度很高,在一个类里边需要用到另外一个类,那么就在类中定义一个变量来维护另一个类的关系,这种就叫组合关系。
2.2 实现组件类
2.2.1 编写组件类
2.2.2 在主类中引用对应的组件类
2.2.3 编写配置文件
2.2.4 编写测试类并运行
3.1 什么是复合主键映射:当一个字段无法确定唯一性的时候,需要其他字段来一起形成唯一性。就是用2个或2个以上的字段组成主键。多个字段组成的这个组合在数据表中是唯一,且加了主键索引。
3.2 实现复合主键映射
3.2.1 编写复合主键类
3.2.2 在主类中引用对应的复合主键类
3.2.3 编写配置文件
3.2.4 编写测试类并运行
@Entity -->将一个类声明为一个持久化类
@Id -->声明了持久化类的标识属性(相当于数据表的主键)
@GeneratedValue -->定义标识属性值的生成策略
@Table -->为持久化类映射指定表(table)、目录(catalog)和schema的名称。默认值,持久化类名,不带包名
@UniqueConstraint -->定义表的唯一约束
@Lob -->表示属性将被持久化为Blob或者Clob类型
@Column -->将属性映射到列@Transient 忽略这些字段和属性,不用持久化到数据库(不生成列)
@OneToOne -->一对一
@OneToMany -->一对多
@ManyToOne -->多对一
@ManyToMany -->多对一
第一种是把注解@Column(name = "xx")放在field上,一种是把注解放在get方法上一般放在field上看起来比较集中、清晰;
第二种是把注解@Column(name = "xx")放在get方法上,这种方式看起来比较散漫、不怎么清楚。
但是第一种方式实际上破坏了java面向对象的封装性,原因是一般我们写javaBean,成员变量通常定义为private,目的就是不让别人来直接访问私有属性,而我们把注解放在私有成员的变量上,就是默认Hibernate可以直接访问我们的私有的成员变量,所以我们定义属性为private,实际就没有多大意义了,至于Hibernate为什么能访问,Hibernate采用java的反射机制完全可以访问私有成员变量!所以应该放在get方法上,第二种方式就显得更加合理。
// 查询单个属性
@Test
public void testQuery1() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
// 查询所有书名
/*Book(区分大小写)表示的是cn.hibernate.pojo.Book类name(区分大小写)表示的Book类中的属性名*/
String hql = "select name from cn.hibernate.pojo.Book";
// 创建Query对象
Query query = session.createQuery(hql);
// list()方法返回查询结果 返回结果的类型是根据查询的列决定的
List<String> list = query.list();
for (String bookName : list) {
System.out.println(bookName);
}
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
// 查询多个属性
@Test
public void testQuery02() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
// 查询所有书名,价格
// 编写hql
/*hql是面向对象的查询语言,所以区分大小写,sql关键词不区分name表示Book类的属性名,注意大小写一致Book表示实体类,注意大小写一致,可以写完全限定名*/
String hql = "select name, price from cn.hibernate.pojo.Book";
// 创建Query对象
Query query = session.createQuery(hql);
// 查询
List<Object[]> list = query.list();
for (Object[] obj: list) {
System.out.println(obj[0] + "---" + obj[1]);
}
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
// 将多个查询列封装为对象
@Test
public void testQuery03() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
// 查询所有书名,价格
// 编写hql
/*
hql是面向对象的查询语言,所以区分大小写,sql关键词不区分
name表示Book类的属性名,注意大小写一致
Book表示实体类,注意大小写一致,可以写完全限定名
*/
String hql = "select new Book(name, price) from
cn.hibernate.pojo.Book";
// 创建Query对象
Query query = session.createQuery(hql);
// 查询
List<Book> list = query.list();
for (Book book: list) {
System.out.println(book);
}
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
// 别名使用
@Test
public void testQuery04() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.getSession();
tx = session.beginTransaction();
// 查询所有书名,价格
// 编写hql
/*hql是面向对象的查询语言,所以区分大小写,sql关键词不区分name表示Book类的属性名,注意大小写一致Book表示实体类,注意大小写一致,可以写完全限定名*/
String hql = "select new Book(b.name, b.price) from Book as b";
// 创建Query对象
Query query = session.createQuery(hql);
// 查询
List<Book> list = query.list();
for (Book book: list) {
System.out.println(book);
}tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
HibernateUtil.closeSession();
}
}
原文:https://www.cnblogs.com/ruanjianwei/p/12133348.html