Hibernate的学习笔记

一、Hibernate说明:

首先说一下Hibernate吧,Hibernate是Java持久层框架之一,是一个开放源码的ORM框架,它在ORM框架中级别最高,是完全面向对象的。

那么什么是ORM框架呢?O--Object(对象)、R--Relation(关系)、M--Mapping(映射),简单的说就是在实体类和数据库表建立对应关系,避免去和复杂的sql语句打交道,通过映射关系,可以直接操作对象型的数据来代替操作数据库中的关系型数据,再着重说一下,Hibernate是完全面向对象的,在操作数据库的层面上,我们只需要用对象来操作数据库即可,与数据库中的表、字段就完全脱离开来。

二、Hibernate对象的三种状态

进入正题,Hibernate的对象共有三种状态:瞬时态持久态游离态(托管态)

瞬时态:新new出来的对象,就属于瞬时态,此时session和数据库中都不存在该对象。

持久态:对象做持久化操作的时候,比如调用session.save()方法时,对象由瞬时态变为持久态,此时session和数据库中都存在。

游离态:对象与session脱离关联,比如调用session.close()方法时,此时只有数据库中存在该对象。

上个图(来源于网络--侵删)

代码:

package com.sinosoft.objectTest;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.sinosoft.model.User;

@RunWith(SpringJUnit4ClassRunner.class)  //spring整合了junit测试
@ContextConfiguration("classpath:applicationContext.xml")  //用于加载spring的配置文件,初始化容器
public class TransientTest {
	
	@Autowired
	//spring容器为我们提供了工厂对象,这里使用注解的方式去容器中拿到该对象
	private SessionFactory factory; 
	
	 @Test
	public void testMethod01(){
		 //从session工厂中拿到session对象
		 Session session = factory.openSession();
		 //开启事物
		 Transaction tx = session.beginTransaction();
		 //新建一个对象,此时session还没有对user对象管理,所以处于瞬时态
		 User user = new User();
		 user.setUserName("Transient");
		 user.setUserPassword("123");
		 //执行完save方法之后,该对象的状态由瞬时态变为持久态
		 session.save(user);
		 
		 //提交事务
		 tx.commit();  
		 //关闭session
		 session.close();   
	 }
}

提一句,关于Hibernate的sql打印,下面这段代码,在调用完save()方法之后,user对象就变为了持久态,并且被加入了一级缓存中,提交事物时,会发送一条sql语句:Hibernate: insert into user_test(user_name, user_password) values(?, ?)此时,如果我们更改了user对象的属性,它会拿当前的user对象去和一级缓存中的user对象进行比较,如果相同,则无需发送新的sql语句,如果不同,则会发送一条更新的sql语句。这里的测试用例会发送一条sql语句:Hibernate: update user_test setuser_name=?,user_password=? where user_id=?。这里只是做了一点简单的说明,关于具体sql打印的规则。略

@Test
public void testMethod02(){
	Session session = factory.openSession();
	Transaction tx = session.beginTransaction();
	User user = new User();
	user.setUserName("Transient01");
	user.setUserPassword("123");
	//此时user对象由瞬时态变为持久态,同时对象被session管理,放入一级缓存
	session.save(user);
	//更改对象的属性??
	user.setUserPassword("234");
	
	tx.commit();
	session.close();
}

三、HIbernate的一二级缓存

Hibernate的一级缓存也叫做session级别的缓存也叫做事物级别的缓存,它的生命周期和session的生命周期一样,当session关闭,一级缓存也就消失了。支持的方法,get()、load()。session缓存是一块内存空间,用来存放相互管理的java对象,Hibernate查询对象的时候,首先会使用对象的属性OID值在hibernate得一级缓存中进行查找,如果找到匹配OID值得对象,就直接将该对象从一级缓存中取出使用,不再查询数据库;如果没有找到相同的OID的值得对象,则会去数据库中查找相应数据。当从数据库查询数据的时候,该数据信息也会放置到一级缓存中。Hibernated的一级缓存的作用就是减少对数据库的访问次数。

Hibernate的二级缓存是SessionFactory级别的缓存,它的二级缓存策略的一般过程如下:

(1) 条件查询的时候,总是发出一条select * from table_name where …. (选择所有字段)这样的SQL语句查询数据库,一次获得所有的数据对象。

(2) 把获得的所有数据对象根据ID放入到第二级缓存中。

(3) 当Hibernate根据ID访问数据对象的时候,首先从Session一级缓存中查;查不到,如果配置了二级缓存,那么从二级缓存中查;查不到,再查询数据库,把结果按照ID放入到缓存。

(4) 删除、更新、增加数据的时候,同时更新缓存。

什么样的数据适合存放到第二级缓存中? 很少被修改的数据、不是很重要的数据

四、HIbernate的主键策略

代理主键(没有任何业务意义的主键):

increment:先查最大值,加1,有线程安全问题,只是用测试

identity:数据库逐渐自增

sequence:使用数据库中的序列生成主键(oracle才有)

hilo:由Hibernate自己封装主键自增算法

native:自动三选一(increment,identity,hilo)

uuid:随机生成字符串作为uuid

自然主键: 

assigned:id值需要手动指定,一个个去设置。

五、Hibernate的Get和load方法的区别

(1)get()方法直接返回实体类,如果查不到数据则返回null。load()会返回一个实体代理对象(当前这个对象可以自动转化为实体对象),但当代理对象被调用时,如果没有数据不存在,就会抛出个org.hibernate.ObjectNotFoundException异常

(2)load先到缓存(session缓存/二级缓存)中去查,如果没有则返回一个代理对象(不马上到DB中去找),等后面使用这个代理对象操作的时候,才到DB中查询,这就是我们常说的 load在默认情况下支持延迟加载(lazy);get先到缓存(session缓存/二级缓存)中去查,如果没有就到DB中去查(即马上发出sql)。总之,如果你确定DB中有这个对象就用load(),不确定就用get()(这样效率高),具体看代码?:

@Test
public void testMethod03(){
	Session session = factory.openSession();
	Transaction tx = session.beginTransaction();
	
	User user = new User();
	user.setUserName("Transient03");
	user.setUserPassword("sdsdf");
	
	//"7"这个userID对应的user对象还没有加入库中,缓存中也没有
	//user = (User)session.load(User.class, 7);
	user = (User)session.get(User.class, 7);
	System.out.println(user);
	tx.commit();
	session.close();
}

问题:查询不到的时候会返回什么?

我们将新建一个user对象,该user对象即没有入库,也没有加入缓存,当我们使用load()方法加载这个还没有入库的对象时,它在缓存和数据库中都没有找到该对象,此时会抛出一个ObjectNotFoundException的异常。把load()方法注释掉以后,使用get方法加载并且打印对象,只是返回一个null.

异常信息:

org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.sinosoft.model.User#7]
	at org.hibernate.boot.internal.StandardEntityNotFoundDelegate.handleEntityNotFound(StandardEntityNotFoundDelegate.java:28)
	at org.hibernate.proxy.AbstractLazyInitializer.checkTargetState(AbstractLazyInitializer.java:242)
	at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:159)
	at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:266)
	at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:68)
	at com.sinosoft.model.User_$$_jvste44_0.setUserPassword(User_$$_jvste44_0.java)
	at com.sinosoft.objectTest.TransientTest.testMethod03(TransientTest.java:32)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:254)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring是一个开源的Java框架,用于构建企业级应用程序。它提供了一种轻量级的、非侵入式的开发方式,通过依赖注入和面向切面编程等特性,简化了Java应用程序的开发过程。 以下是关于Spring学习的一些笔记: 1. IoC(控制反转):Spring通过IoC容器管理对象的创建和依赖关系的注入。通过配置文件或注解,将对象的创建和依赖关系的维护交给Spring容器来管理,降低了组件之间的耦合度。 2. DI(依赖注入):Spring通过依赖注入将对象之间的依赖关系解耦。通过构造函数、Setter方法或注解,将依赖的对象注入到目标对象中,使得对象之间的关系更加灵活和可维护。 3. AOP(面向切面编程):Spring提供了AOP的支持,可以将与业务逻辑无关的横切关注点(如日志、事务管理等)从业务逻辑中分离出来,提高了代码的可重用性和可维护性。 4. MVC(模型-视图-控制器):Spring提供了一个MVC框架,用于构建Web应用程序。通过DispatcherServlet、Controller、ViewResolver等组件,实现了请求的分发和处理,将业务逻辑和视图展示进行了分离。 5. JDBC和ORM支持:Spring提供了对JDBC和ORM框架(如Hibernate、MyBatis)的集成支持,简化了数据库访问的操作,提高了开发效率。 6. 事务管理:Spring提供了对事务的支持,通过声明式事务管理和编程式事务管理,实现了对数据库事务的控制和管理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值