`
aa87963014
  • 浏览: 154425 次
  • 性别: Icon_minigender_1
  • 来自: 布尼塔尼亚
社区版块
存档分类
最新评论

hibernate进阶改造

阅读更多

 

 

原帖内容已删除,对描述部分做新的修改,将不针对hibernate这一个orm框架:

 

我将会致力于从根本上解决脏数据读取问题。

 

对于我们现在的大多数框架来说,任何操作都是基于数据库的。相当于把sql语言转换形式进行实现:

 

"update User set level = level +1;" 等价于 "User user= get(User); user.setlevel(user.getLevel+1);" ?

 

我们的应用都是基于数据库的数据操作,前者是告诉数据库自行修改数据操作,而后者着是直接替换数据库中的值!

 

有严重的并发修改问题。所谓并发修改不仅仅是同一时间修改同一条记录的时候的问题,这种情况数据库有锁等方式解决。

但是对于后者这种方式,数据库将无能为力,因为orm框架每次update到数据库中的值全部都是全新的!全部都是替换操作。

 

在并发修改的情况下(从 User user= get(User);把user信息取出来到update(user);这个过程中,任何一个其他线程的 get(User) update(user) ;操作都会照成潜在的并发问题。第一个取出的user的对象是可靠的,其他的非指向user引用的对象全部都为不可靠数据!)user的信息会被任意的覆盖,因为所有的user信息都是取得保存在内存中,数据库中uid为1的user记录在数据库中永远只有一个,并且有锁机制保证修改顺序。

 

但是在orm框架中会存在多个user对象,只不过这些user对象的uid为1,而且可怕的是这些user互不相关!在你update(user);的时候实质上是在不停的插入全新的user信息,内存中的user值和数据库中的值没有任何关系。但是,从业务逻辑上来说,你对user对象属性操作仅仅是代替数据库操作。

 

本质上user的属性在整个内存中应当只有1个,因为你只是代替数据库去修改某个属性。你不应该具有多个存储能力,每个实体实质上都存储了一条记录的信息。

 

举例:

 

	@Transactional
	public void a(){
		User user1=baseDAO.get(User.class,1);		
		user1.setLevel(user1.getLevel()+1);
		
		User user2=baseDAO.get(User.class,1);		
		user2.setLevel(user2.getLevel()+1);
		
		baseDAO.update(user1);
		baseDAO.update(user2);
	}

 在这个方法里面,任意对user的操作都是可靠的,因为hibernate的一级缓存将后面取出来的user2指向的是user1的引用,user1、user2的修改实质上仅仅修改内存中的唯一user对象。在update之后没有任何问题,因为从始至终只修改的是一个记录。

 

典型的并发修改例子:

 

@Transactional
	public void b(){
		User user1=baseDAO.get(User.class,1);		
		user1.setLevel(user1.getLevel()+1);
		
		User user2=baseDAO.get(User.class,1);		
		user2.setLevel(user2.getLevel()+1);

		baseDAO.update(user1);
		baseDAO.update(user2);
	}

	@Transactional
	public void c(){
		User user3=baseDAO.get(User.class,1);		
		user3.setLevel(user3.getLevel()+1);	
		
		try {
			Thread.sleep(5000);//模拟业务操作需要5秒时间
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		baseDAO.update(user3);
	}
 

 

b方法比c方法晚一秒钟调用,假设user的leve原本的值为1;在method b,method c执行完毕之后 数据库中实际值为2,而不是3。

因为b方法修改的数据库记录被c方法的修改结果覆盖了。

 

这类问题根本原因不是用加锁或者修改业务逻辑去解决的。而是为什么在内存中会有多个不一样的user。数据应该都是唯一的,数据库中找不到id为1的2条记录,内存中也不应该出现id为1的2个对象。

 

既然我们是orm框架用面向对象的方式去修改数据,操作数据的本质应该不能改变:既永远只操作一条记录。可以参照method a是如何实现的,无论你update(user);多少次,最终修改的只有一条记录。只不过hibernate这种方式仅仅在一个事物中是这样做的,没有做到整个内存中只存在一个user对象。

 

 

针对,hibernate这个orm框架来说。他可以用一级缓存保证同一个事物内数据的一致性,但是处理不了不同事物的一致。那么还有一个二级缓存可能让内存中的user指向同一个对象(应该是有的),具体有没有这么做,还需要测试、研究下才能最终确认。

 

如果我的推断是正确的,那么在hibernate开启二级缓存之后,才能算是一个完整的orm框架。否则将是一个错误设计,简单的说:数据中只有一条记录,那么内存中只能有一个实体,update操作只能由这个实体操作,其他的任意实体都不可取。你以为你按照产品说明书上一步步操作没有问题,实际上问题一直存在!只不过你没有碰。

 

------

ps:

1、我是在接触游戏开发才有这个想法,至于一些设计可能你觉得有问题,这个不想多争论,除非你指出我设计上的错误。

2、并发问题、并发压力之类的,一般都说的是数据库底层操作的问题,但是实际在业务方法上你可能悄无声息的制造了并发问题。

3、这里请不要说xx不适合开发xx之类的,这里说的和开发什么东西没太大关系,任何一个使用hibernate的应用都会有这样的问题,除非你从业务上就避免了多个地方修改同一条记录的逻辑。一旦有,你就应该有这个思考。

4、如果错,请狂喷。在下洗耳恭听、虚心学习。

分享到:
评论

相关推荐

    Hibernate 进阶教程

    《Hibernate 进阶教程》是一本专为对Hibernate有初步了解并希望深入学习的开发者准备的手册。Hibernate作为Java领域中最流行的持久化框架之一,它极大地简化了数据库操作,使得开发者能够更专注于业务逻辑,而非繁琐...

    基于Spring与Hibernate的数据库操作进阶

    本主题“基于Spring与Hibernate的数据库操作进阶”将深入探讨如何利用这两个框架进行高级的数据库交互。 首先,Spring是一个开源的Java平台,它简化了应用程序的开发,并提供了全面的框架支持,包括依赖注入(DI)...

    北大青鸟Hibernate学习资料

    而《Hibernate—Java对象持久化技术-Hibernate进阶.ppt》则深入讲解了高级特性和最佳实践,如缓存机制、事务管理和性能优化。 5. **上课笔记** 提供的三份上课笔记《上课笔记t1.txt》、《上课笔记.txt》和《上课...

    Struts2.3.30升级2.5.12+spring4.2.2升级4.3.9+hibernate5.0.9升级5.2.11注意

    主要内容: 提供了一步一步的操作指南来将Struts2从2.3.30版本平滑过渡至2.5.12版本,Spring由4.2.2更新至4.3.9以及Hibernate进阶提升到5.2.11版本的具体路径和技术要点阐述。详细讲述了每个阶段所需更改的内容,比如...

    spring+struts2+hibernate完整项目初学者进阶练习

    【标题】"spring+struts2+hibernate完整项目初学者进阶练习"是一个针对Java初学者设计的进阶项目,旨在帮助他们熟练掌握三大主流Java Web开发框架——Spring、Struts2和Hibernate的集成应用。这个项目是基于MySQL...

    hiberanate进阶之路jar

    《Hibernate进阶之路:深入解析相关jar包》 在Java世界中,Hibernate作为一个优秀的对象关系映射(ORM)框架,极大地简化了数据库操作。本文将深入探讨与Hibernate进阶之路相关的jar包,帮助开发者理解这些核心组件...

    Hibernate映射配置入门进阶详解

    1)根元素映射<hibernate-mapping/> 2)类映射 3)属性映射 4)主键的配置 5)主键生成策略 复合主键策略 史上最详细

    hibernate相关书籍

    2. **Hibernate进阶**: - **懒加载和立即加载**:Hibernate支持对象的懒加载策略,仅在需要时加载关联的对象,以提高性能。 - **缓存机制**:一级缓存是SessionFactory级别的,二级缓存可配置为应用或集群级别,...

    HibernateApi.zip

    四、Hibernate进阶特性 4.1 第二级缓存:提高性能,将数据缓存在内存中,减少数据库访问。 4.2 异步操作:使用Future和ExecutorService实现并发处理,提升系统响应速度。 4.3 联接查询:支持JOIN操作,实现对象...

    Hibernate实战

    总之,《Hibernate实战》这本书全面覆盖了Hibernate的基础和进阶内容,对于想要掌握和提升Hibernate使用技能的Java开发者来说,是一本不可多得的参考书。通过学习,读者不仅可以了解到Hibernate的工作原理,还能掌握...

    Hibernate 配置各种数据库

    Hibernate 配置各种数据库 Hibernate 是一个基于 Java 的持久层框架,提供了一个抽象的数据访问层,能够与多种数据库进行集成。在 Hibernate 的配置文件中,我们可以配置不同的数据库连接,包括驱动程序、URL 等...

    hibernate第一个hibernate

    10. 扩展与进阶: Hibernate支持多种数据库,且与Spring框架结合使用可以实现更高级的功能,如事务的声明式管理、DAO模式的实现等。学习完基础后,可深入研究Hibernate的高级特性,如 Criteria API、Hibernate ...

    Hibernate入门到精通

    "Hibernate入门到精通" Hibernate 是一个基于Java的ORM(Object-Relational Mapping,对象关系映射)框架,它提供了一种简洁高效的方式来访问和操作关系数据库。下面是 Hibernate 的主要知识点: Hibernate 简介 ...

    hibernate jar包:hibernate-commons-annotations-4.0.1.Final.jar等

    Hibernate.jar包,Hibernate可以应用在任何使用JDBC的场合,包含 hibernate-commons-annotations-4.0.1.Final.jar hibernate-core-4.1.12.Final.jar hibernate-ehcache-4.1.12.Final.jar hibernate-entitymanager-...

    Hibernate中文文档+hibernate annotation +distribution

    首先,Hibernate中文文档是理解框架基础和进阶功能的关键。文档涵盖了Hibernate的基本配置、实体映射、会话管理、查询语言(HQL)和 Criteria API等多个方面。对于初学者,它能帮助快速理解和掌握ORM的核心思想,而...

    hibernate_reference中文版和Hibernate中文手册

    以上只是Hibernate基本概念和关键知识点的概述,具体到《Hibernate参考指南中文版》和《Hibernate中文手册》中,会包含更多详细的配置示例、代码片段和最佳实践,对于初学者和进阶者来说,都是宝贵的参考资料。...

    kingbaseV8 hibernate jdbc 驱动

    在Java开发环境中,与KingbaseV8数据库进行交互通常会用到Hibernate框架和JDBC驱动。 Hibernate是一个优秀的对象关系映射(ORM)框架,它简化了Java应用程序对数据库的操作,通过将Java对象与数据库表进行映射,...

    hibernate3全部jar包:hibernate3.jar.zip 下载

    Hibernate3 是一个强大的Java持久化框架,它允许开发者将数据库操作与业务逻辑解耦,使得应用程序的开发更为简便。这个“hibernate3全部jar包:hibernate3.jar.zip”包含了所有必要的库文件,方便用户一次性下载并...

    hibernate--1.什么是 Hibernate ?

    至于`hibernate_2`,这个可能是某个教程文档、源代码示例或者其他的资源,具体内容无法直接给出,但可以推测可能涉及Hibernate的进阶话题,如多对一、一对多、多对多的关系映射,懒加载和立即加载的概念,或者是...

Global site tag (gtag.js) - Google Analytics