Hibernate基础版

基础

一、Hibernate简单案例实现
1、Hirbernate项目及四要素**
实体类(POJO类):持久化javaBean类
对象-关系映射文件(*_hbm.xml)
主配置文件(hibernate.cfg.xml)
编写Hibernate提供的API执行程序

实现过程
(1)创建应用工程
1)下载Hibernate5的jar包:点击获取
在这里插入图片描述
随便选一个安装包下载

2)导入jar包
注意:此处的项目为普通的java项目
在这里插入图片描述手动创建lib文件夹(lib是导入jar 包的存放位置)
在这里插入图片描述
具体jar包:(还有Mysql的驱动jar包)
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
hibernate项目成功的目录
在这里插入图片描述
(2)、编写*.hbm.xml对象关系映射文件(重点)
1)在src下新建实体类(POJO,javaBean,unity,domain等)
在这里插入图片描述
Animal.java(com.test.domain)

package com.test.domain;

public class Animal {
	private Integer aid;
	private String aname;
	private Integer age;

	public Integer getAid() {
		return aid;
	}

	public void setAid(Integer aid) {
		this.aid = aid;
	}

	public String getAname() {
		return aname;
	}

	public void setAname(String aname) {
		this.aname = aname;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}
	
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "animal message:"+aid+aname+age;
	}
}

2)编写*.hbm.xml对象关系映射文件
在这里插入图片描述在这里插入图片描述在这里插入图片描述
进入Animal.hbm.xml修改
在这里插入图片描述
(3)、编写hibernate.cfg.xml文件
建议放在src目录下
在这里插入图片描述一路next

注意:最后可能因为版本兼容问题,finish不了,建议更换版本尝试。
在这里插入图片描述修改hibernate.cfg.xml配置
在这里插入图片描述

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述hibernate.cfg.xml添加

 <mapping resource="com/test/domain/Animal.hbm.xml"/>

在这里插入图片描述
(4)、编写Hibernate测试代码
1)创建一个SessionFactory工厂类
2)通过工厂开启Session对象
3)开始事务
4)执行数据库的操作
5)提交事务
6)关闭Session
7)关闭工厂类

HibernateTest.java
具体代码:
在这里插入图片描述

package com.test.domain;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

public class HibernateTest {
	@Test
	public void test() {
		Animal animal = new Animal();
		animal.setAid(1);
		animal.setAname("猴子");
		animal.setAge(12);

		// 创建Configuration实例,读取默认hibernate配置文件
		Configuration cfg = new Configuration().configure();

		// 通过cfg创建一个SessionFactory工厂类,维护着2级缓存,不需要关闭
		SessionFactory sessionFactory = cfg.buildSessionFactory();

		// 通过工厂类开启Session对象
		Session session = sessionFactory.openSession();

		// 开始事务
		Transaction transaction = session.beginTransaction();

		// 执行数据库操作,session维护着1级缓存
		session.save(animal);

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

		// 回滚,以免产生脏数据
		// transaction.rollback();

		// 关闭Session
		session.close();

		// 关闭工厂类,在web程序中不用关闭,整个应用程序对应一个sessionFactory
		// sessionFactory.close();
	}
}

(5)运行测试类
在这里插入图片描述
在这里插入图片描述


2、简单案例分析
(1)hibernate.cfg.xml

hibernate.dialect:数据库方言
hibernate.show_sql:控制台打印输出sql
hibernate.format_sql:格式化sql

hibernate.hbm2ddl.auto

create:
每次创建sessionFactory时都会删除以前的数据库表,重新
创建,不推荐使用。
create-drop:
每次关闭sessionFactory时都会删除所有的表。
update:
常用,第一次加载会自动创建,以后创建都会根据POJO更新表
结构,不会删除数据和表。
validate:每次加载时会验证数据库的表结构,如果POJO和数
据库结构不匹配则会报错,不会创建新表。

(2)POJP
javaBean对象

(3)映射文件 POJO.hbm.xml
该文件充当Hibernate框架与数据库持久化桥梁的作用

一个class描述一个类和一个表的对应关系
id:主键设置,generator标记主键的生成策略,一般采用native,方便数据库移植
property:描述属性和数据库关系
若column不写,则和name相同


3、主键策略
在这里插入图片描述在这里插入图片描述


4、常用API解析
(1)Configuration读取配置文件
configuration类负责管理Hibernate的配置信息,包括核心配置和.hbm.xml配置

(2)、SessionFactory工厂类
1)由Configuration对象创建
2)SessionFactory保存着当前数据库配置信息和所有映射关系预定义的SQL语句,同时还负责Hibernate的二级缓存,一个SessionFactory实例对应一个数据库,应用从该对象中获得Session实例
3)SessionFactory是重量级的,意味着不能随意创建和销毁它的实例。如果只访问一个数据库,只需要创建一个SessionFactory实例,且在应用初始化的时候完成。
4)SessionFactory需要一个较大的缓存,用来存放预定义的SQL语句及实体的映射信息。另外可以配置一个缓存插件,这个插件被称为Hibernate的二级缓存,被多线程所共享。

(3)Session对象
Session是在Hibernate中使用最频繁的接口。也被称为持久化管理器。它提供了和持久化有关的操作。比如添加、修改、删除、加载和查询实体对象。
不是线程安全的,应避免多个线程使用同一个Session实例,Session是轻量级的,它的创建和销毁不会消耗太多资源,成为每次客户请求分配的Session实例,Session有一个缓存,被称为Hibernate的一级缓存,每个Session实例都有自己的缓存。

(4)开始事务
Transaction代表一次原子操作,它具有数据库事务的概念,所有持久化都应该在事务管理器下进行,即使是只读操作。如果没有开启事务,那么每一个Session的操作,都相当于一个独立的事务。

(5)执行数据库的操作

(6)事务提交和回滚

(7)关闭资源


5、简单的CRUD操作

save
update
saveOrUpdate
delete
load
get

目录
在这里插入图片描述
Person.java
在这里插入图片描述

package com.hliedu.domain;

/*POJO类,javabean,Domain,Enity*/
public class Person {
	private Integer pid;

	private String pname;

	private Integer age;

	public Integer getPid() {
		return pid;
	}

	public void setPid(Integer pid) {
		this.pid = pid;
	}

	public String getPname() {
		return pname;
	}

	public void setPname(String pname) {
		this.pname = pname;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}
	
	@Override
		public String toString() {
			// TODO Auto-generated method stub
			return pid+" "+pname+":"+age;
		}
}

HibernateTest1.java测试类
在这里插入图片描述

package com.hliedu.domain;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

public class HibernateTest1 {

	// 新增和修改
	@Test
	public void save() {
		Person person = new Person();
		person.setPname("张三");
		person.setAge(18);

		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction transaction = session.beginTransaction();
		session.save(person);
		transaction.commit();
		session.close();

	}

	@Test
	public void update() {
		Person person = new Person();
		person.setPid(1);
		// 更新时没有传入ID org.hibernate.TransientObjectException: The given object has a null
		// identifier: com.hliedu.domain.Person
		// 更新时没有传入对应的ID Row was updated or deleted by another transaction (or
		// unsaved-value mapping was incorrect) : [com.hliedu.domain.Person#4]

		person.setPname("李四");
		person.setAge(30);

		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction transaction = session.beginTransaction();
		session.update(person);
		transaction.commit();
		session.close();

	}

	@Test
	public void saveOrUpdate() {
		Person person = new Person();
		person.setPid(1);
		person.setPname("王五");
		person.setAge(24);

		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction transaction = session.beginTransaction();
		session.saveOrUpdate(person);
		transaction.commit();
		session.close();

	}

	// 删除
	@Test
	public void delete() {
		Person person = new Person();
		person.setPid(1);
		// 删除时没有匹配到删除的数据 No tests found matching Method
		// delete(com.hliedu.domain.HibernateTest) from
		// org.junit.vintage.engine.descriptor.RunnerRequest@527740a2

		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction transaction = session.beginTransaction();
		session.delete(person);
		transaction.commit();
		session.close();
	}

	// 查询
	// 1、 别名查询
	@Test
	public void get() {
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction transaction = session.beginTransaction();
		Person person = session.get(Person.class, 1);
		// 当没有匹配到数据 返回null
		System.out.println(person);
		transaction.commit();
		session.close();
	}

	// 2
	@Test
	public void load() {
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction transaction = session.beginTransaction();
		Person person = session.load(Person.class, 1);
		// 当没有匹配到数据 No row with the given identifier exists:
		// [com.hliedu.domain.Person#2]

		System.out.println(person);
		transaction.commit();
		session.close();
	}

}

Person.hbm.xml
在这里插入图片描述

<?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 2020-3-28 22:01:30 by Hibernate Tools 3.5.0.Final 对象关系映射文件,映射数据库和实体类之间的关系 -->
<hibernate-mapping default-lazy="false">
	<class name="com.hliedu.domain.Person" table="PERSON">
		<!-- 主键 -->
		<id name="pid" type="java.lang.Integer">
			<column name="PID" />
			<generator class="native" />
			<!-- 将ID生成规则交由数据库完成 -->
		</id>
		<property generated="never" lazy="false" name="pname"
			type="java.lang.String">
			<column name="PNAME" />
		</property>
		<property generated="never" lazy="false" name="age"
			type="java.lang.Integer">
			<column name="AGE" />
		</property>
	</class>
</hibernate-mapping>

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 name="">
		<!-- 数据库连接配置 -->
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate5</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password">admin</property>
		<!-- 数据库方言 ,limit是mysql独有的,top是sqlserve独有的 -->
		<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
		<!-- 附属配置,ddl是数据库定义语言 -->
		<property name="hibernate.show_sql">true</property>
		<property name="hibernate.format_sql">true</property>
		<property name="hibernate.hbm2ddl.auto">update</property>
		<mapping resource="com/hliedu/domain/Person.hbm.xml" />
	</session-factory>
</hibernate-configuration>

6、测试类代码优化
(1)简单封装(提高复用率)
HibernateUtil.java
(包装Configuration配置和SessionFactory工程类)
在这里插入图片描述

package com.hliedu.domain;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

/*Hibernate调用程序*/

public class HibernateUtil {
	// Junit测试,单元测试

	private static Configuration cfg = null;
	private static SessionFactory sessionFactory = null;

	static {
		// 创建Configuration实例,读取默认hibernate配置文件
		cfg = new Configuration().configure();

		// 通过cfg创建一个SessionFactory工厂类,维护着2级缓存,不需要关闭
		sessionFactory = cfg.buildSessionFactory();
	}

	public static SessionFactory getSessionFactory() {
		return sessionFactory;
	}

}

HibernateTest2.java
在这里插入图片描述
(内含多个错误异常说明)

顺序:
@Before
测试方法
@After
package com.hliedu.domain;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class HibernateTest2 {

	Configuration cfg = null;
	SessionFactory sessionFactory = null;
	Session session = null;
	Transaction transaction = null;

	@Before
	public void init() {
		// TODO Auto-generated method stub
		System.out.println("初始化加载");
		cfg = new Configuration().configure();
		sessionFactory = cfg.buildSessionFactory();
		session = sessionFactory.openSession();
		transaction = session.beginTransaction();
	}

	@After
	public void after() {// 销毁
		// TODO Auto-generated method stub
		transaction.commit();
		session.close();
		sessionFactory.close();
	}

	// 新增和修改
	@Test
	public void save() {
		Person person = new Person();
		person.setPname("张三");
		person.setAge(18);

		session.save(person);
	}

	@Test
	public void update() {
		Person person = new Person();
		person.setPid(1);
		// 更新时没有传入ID org.hibernate.TransientObjectException: The given object has a null
		// identifier: com.hliedu.domain.Person
		// 更新时没有传入对应的ID Row was updated or deleted by another transaction (or
		// unsaved-value mapping was incorrect) : [com.hliedu.domain.Person#4]

		person.setPname("李四");
		person.setAge(30);

		session.update(person);
	}

	@Test
	public void saveOrUpdate() {
		Person person = new Person();
		person.setPid(1);
		person.setPname("王五");
		person.setAge(24);

		session.saveOrUpdate(person);
	}

	// 删除
	@Test
	public void delete() {
		Person person = new Person();
		person.setPid(1);
		// 删除时没有匹配到删除的数据 No tests found matching Method
		// delete(com.hliedu.domain.HibernateTest) from
		// org.junit.vintage.engine.descriptor.RunnerRequest@527740a2

		session.delete(person);
	}

	// 查询
	// 1、 别名查询
	@Test
	public void get() {
		Person person = session.get(Person.class, 1);
		// 当没有匹配到数据 返回null
		System.out.println(person);
	}

	// 2
	@Test
	public void load() {
		Person person = session.load(Person.class, 1);
		// 当没有匹配到数据 No row with the given identifier exists:
		// [com.hliedu.domain.Person#2]

		System.out.println(person);
	}

}

基础加深

一、Session一级缓存操作
DefaultLoadEventListener 444行从缓存中取出已经存在的对象id

由get()方法效果可以得出以下结论:
Session中存在缓存,这种缓存我们称为一级缓存,存在哪个Session的生命周期中,缓存里的对象,不会随着引用变量消失而清空,只要缓存中存在该对象,在查询的时候Hibernate优先从缓存中取出数据,而不会再次访问数据库,只有缓存中不存在的数据,才会发起SQL语句查询数据库,所以缓存极大减少了访问数据库的频率。

Session缓存的作用:
1)减少访问数据库的频率
2)保证缓存中的数据与数据库保持同步,当缓存的对象改变后,session不会立即执行sql,而是将多个sql语句合并成一条sql进行执行,提高效率。

如果对于一个属性修改了多次,其实Hibernate的session缓存并不是执行多个update语句,而是以最后一个更新为准发送一条更新的sql。
在这里插入图片描述
二、缓存相关方法
Hibernate提供了一下2个方法来保证缓存中的数据与数据库记录保持一致。

1、flush
强制让数据库中的记录与session中的对象数据保持一致,不一致则发起update这条sql修改数据让其一致。

在这里插入图片描述

注意:
事务的commit()中已经自动调用了flush方法,所以若存在commit()可以省略flush方法,若缓存数据发生变化,flush()会执行update语句,但是最终不会提交事务,提交事务意味着持久化到数据库。

2、refresh
强制发出select语句,保证session缓存中的数据与数据库的记录是一致的,如果发现不一致它会修改缓存中的对象让其一致。
在这里插入图片描述在这里插入图片描述
clear
清理session缓存,会重新发起sql语句。

三、sanHibernate对象状态
1、状态分类
Hibernate为了管理持久化类:将持久化类分成了三个状态。
瞬时态:Transient Object,没有持久化标识OID,没有纳入到Session对象的管理。
持久态:Persient Object
有持久化标识OID,已经纳入到Session对象的管理。
脱管态(游离态):Detached Object
有持久化标识OID,没有纳入Session对象的管理。
在这里插入图片描述

2、详细描述
瞬时态:对象由new操作符创建,且尚未与Hibernate Session关联的对象被认为处于瞬态,瞬态对象不会被持久化到数据库中,也不会被赋予持久化标识,如果程序失去了瞬态对象的引用,瞬态对象将被垃圾回收机制销毁,使用Hibernate Session可以将其变为持久态状态。

持久态:持久化实例在数据库中有对应的记录,并拥有一个持久化标识(identifer)。持久化的实例可以是刚刚保存的,也可以是被加载的,无论哪一种,持久化对象都必须与指定的Hibernate Session关联。Hibernate会检测到处持久化状态对象的改动,在当前操作完成时将对象数据写回数据库。

脱管态:某个实例曾经处于持久化状态,但随着与之关联Session被关闭,该对象就变成了脱管状态,脱管状态的引用依然有效,对象可继续被修改。如果重新让脱管对象与某个Session关联,这个脱管对象会重新转换为持久化对象。

在这里插入图片描述
在这里插入图片描述

3、三种形态代码解析
1)对象瞬时态解析
(1)
在这里插入图片描述
(2)
在这里插入图片描述
(3)
在这里插入图片描述
(4)
在这里插入图片描述
2)对象持久态解析
(1)

在这里插入图片描述(2)
在这里插入图片描述
3)游离态解析
(1)
在这里插入图片描述
(2)
在这里插入图片描述
4、Session中的核心方法
概念1
在这里插入图片描述
代码解析:

在这里插入图片描述
概念2
在这里插入图片描述
代码解析:
save()
在这里插入图片描述
persist()
在这里插入图片描述
update()
在这里插入图片描述
概念3
在这里插入图片描述
代码解析
saveOrUpdate()
在这里插入图片描述
delete()

在这里插入图片描述
evict()
在这里插入图片描述
dowork()(代码漏了@Test)
在这里插入图片描述

四、Hibernate连接池C3P0配置
C3P0支持的jar包:(解压Hibernate jar包后)
hibernate-release-5.3.16.Final\hibernate-release-5.3.16.Final\lib\optional\c3p0

配置过程:
在这里插入图片描述在这里插入图片描述
测试配置是否成功:
在这里插入图片描述成功
在这里插入图片描述
配置文档:
在这里插入图片描述在这里插入图片描述在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值