首页 > Web开发 > 详细

剑指Hibernate

时间:2020-01-02 16:39:41      阅读:77      评论:0      收藏:0      [点我收藏+]

 什么是Hibernate

1. hibernate的简介

Hibernate是一款优秀的持久化ORM框架;解决持久化操作,使得程序员可以从编写繁复的JDBC工作中解放出来,专注于业务,提高程序员开发效率;并且具有可靠的移植性,降低了系统耦合度;

2. 什么是持久化和ORM

2.1 持久(Persistence),即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。

持久化的主要应用是将内存中的数据存储在关系型的数据库中,当然也可以存储在磁盘文件中、XML数据文件中等等。Hibernate当中叫做加载。

1. 狭义概念:数据存储在物理介质不会丢失

2. 广义概念:对数据的CRUD操作都叫做持久化

3. 加载:Hibernate的概念是数据从数据库加载到session

2.2 ORM

O-Object,R-Relation,M-Mapping,顾名思义就是对象(JavaBean)关系(关系型数据库)映射。它的作用是在关系型数据库和对象之间作一个映射,这样,我们在具体的操作数据库的时候,就不需要再去和复杂的SQL语句打交道,只要像平时操作对象一样操作它就可以了 。

hibernate的简单使用

1. 简单测试

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测试结果在数据库中显示

 

hibernate五大关键接口

  1. Configuration接口:负责Hibernate配置工作,创建SessionFactory对象,在Hibernate启动过程中,Configuration类的实例首先定位在映射文件位置,读取配置,然后创建SessionFactory对象。

@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()

  1. SessionFactroy接口负责初始化Hibernate。它充当数据存储源的代理,使用工厂模式创建Session对象。需要注意的是SessionFactory并不是轻量级的,一般情况下,一个项目通常只需要一个SessionFactory就够,当需要操作多个数据库时,可以为每个数据库指定一个SessionFactory。

@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();

}

  1. Session

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()

  1. Transaction

负责事务相关的操作,它代表的是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()

  1. Query

负责执行各种数据查询功能,它可以使用Hibernate特有的HQL语言和SQL语言两种方式。

Hibernate对象生命周期

1.对象状态及生命周期:

瞬时状态:刚刚使用new语句创建,还没有被持久化,不处于Session的缓存中。处于临时状态的Java对象被称为临时对象。Session中没有,数据库中没有。

持久化状态:已经被持久化,加入到Session的缓存中。处于持久化状态的Java对象被称为持久化对象。Session中有,数据库中有。

游离状态:已经被持久化,但不处于Session的缓存中。处于游离状态的Java对象被称为游离对象。Session中没有,数据库中有.

  1. 对象状态转换相关方法

 瞬时状态转为持久状态使用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找不到对象时抛异常.

HibernateSchemaExport的使用

  1. hibernate的方言

Hibernate方言是用来告诉Hibernte如何对指定的数据库生成相应的SQL语句。

尽管做了很多尝试去使SQL语句标准化,但是不同的数据库支持的SQL语句还是有很多不同的地方。所以Hibernate使用方言来辅助生成正确的SQL语句.

  1. MySQL5Dialect与MySQL5InnoDBDialect的区别:他们最大的区别是,在使用Hibernate创建表时MySQL5InnoDBDialect会在生成的建表SQL语句最后加上"engine=InnoDB"。InnoDB是一种MySQL数据库引擎,MySQL5.5及之后使用它做为默认引擎。它提供了ACID兼容的事务(Transaction)功能,并提供外键支持。

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. Hibernate基本映射-大对象映射

1.1 BLOB,CLOB数据的处理

1.1.1 编写实体类

1.1.2 编写配置文件

1.1.3 进行测试

  1. 组件映射

2.1 什么是组件映射:组件映射实际上就是将组合关系的数据映射成一张表,组件类和被包含的组件类映射成一张表。有的时候,两个类的关系明显不是继承关系,但两个类的亲密程度很高,在一个类里边需要用到另外一个类,那么就在类中定义一个变量来维护另一个类的关系,这种就叫组合关系。

2.2 实现组件类

2.2.1 编写组件类

2.2.2 在主类中引用对应的组件类

2.2.3 编写配置文件

2.2.4 编写测试类并运行

  1. 组件映射-复合主键映射

3.1 什么是复合主键映射:当一个字段无法确定唯一性的时候,需要其他字段来一起形成唯一性。就是用2个或2个以上的字段组成主键。多个字段组成的这个组合在数据表中是唯一,且加了主键索引。

3.2 实现复合主键映射

3.2.1 编写复合主键类

3.2.2 在主类中引用对应的复合主键类

3.2.3 编写配置文件

3.2.4 编写测试类并运行

四. Hibernate注解-annotation

  1. 常用注解

@Entity -->将一个类声明为一个持久化类

@Id -->声明了持久化类的标识属性(相当于数据表的主键)

@GeneratedValue -->定义标识属性值的生成策略

@Table -->为持久化类映射指定表(table)、目录(catalog)和schema的名称。默认值,持久化类名,不带包名

@UniqueConstraint -->定义表的唯一约束

@Lob -->表示属性将被持久化为Blob或者Clob类型

@Column -->将属性映射到列@Transient 忽略这些字段和属性,不用持久化到数据库(不生成列)

@OneToOne -->一对一

@OneToMany -->一对多

@ManyToOne -->多对一

@ManyToMany -->多对一

  1. 注解编写的位置

第一种是把注解@Column(name = "xx")放在field上,一种是把注解放在get方法上一般放在field上看起来比较集中、清晰;

第二种是把注解@Column(name = "xx")放在get方法上,这种方式看起来比较散漫、不怎么清楚。

但是第一种方式实际上破坏了java面向对象的封装性,原因是一般我们写javaBean,成员变量通常定义为private,目的就是不让别人来直接访问私有属性,而我们把注解放在私有成员的变量上,就是默认Hibernate可以直接访问我们的私有的成员变量,所以我们定义属性为private,实际就没有多大意义了,至于Hibernate为什么能访问,Hibernate采用java的反射机制完全可以访问私有成员变量!所以应该放在get方法上,第二种方式就显得更加合理。

五. Hibernate-HQL

  1. 什么是HQL:HQL(Hibernate Query Language) 是面向对象的查询语言,它和 SQL 查询语言有些相似。 在 Hibernate 提供的各种检索方式中,HQL 是使用最广的一种检索方式。Hibernate负责解析HQL查询语句,然后根据对象-关系映射文件中的映射信息,把HQL查询语句根据方言翻译成相应的SQL语句。HQL查询语句中的主体是域模型(真实世界的实体的软件抽象)中的类及类的属性。由于面向对象的原因,HQL区分大小写,但是对应SQL关键字(select, from, where)不区分。
  2. 查询单个属性

// 查询单个属性

@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();

}

}

  1. 查询多个属性

// 查询多个属性

@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();

}

}

  1. 将查询多个封装成对象

// 将多个查询列封装为对象

@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();

}

}

  1. 使用别名

// 别名使用

@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();

}

}

剑指Hibernate

原文:https://www.cnblogs.com/ruanjianwei/p/12133348.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!