Hibernate的值类型集合用起来很方便,但在最近的使用中发现它有并发问题。如下:
有一个持久化类A需要包括n个有序的long型数。类A需要保存到数据库中。
类A如下:
public class Foo{
// some properties
List longNumbers=new ArrayList();
// some propertes' getter and setter
public List getLongNumbers(){
return this.longNumbers;
}
public void setLongNumber(List longNubmers){
this.longNumbers=longNumbers;
}
}
这里仅讨论值集合对应的hibernate配置如下:
<list
name="longNumbers"
table="itil_foolongnumbers"
lazy="false"
inverse="false"
cascade="all-delete-orphan"
>
<key
column="ifooid"
>
</key>
<index
column="iindex"
/>
<element
column="ilongnumber"
type="java.lang.Long"
not-null="false"
unique="false"
/>
</list>
配置好后,就可以直接向Foo对象里添加long型的值了,并通过hibernate的Session进行增删改查了。
但是,我遇到了一个问题。当同时有两个或两个以上线程执行如下代码时出现错误。(代码只表语意并不严格)
public void appdendLongNumber(Long fooId,Long num){
Transaction tr=session.beginTransaction();
Foo f=session.get(fooId,Foo.class);
f.getLongNumbers().add(num);
tr.commit();
...
}
出现的错误并不是hibernate报错,而是数据库报主键冲突异常。
经过分析发现:原来itil_foolongnumbers表是用ifooid和iindex做为复合主键的。当有两个线程同时向OID相同的Foo对象增加新的Long Number时,就使得在两个线程中的Foo对象分别拥有了具有相同下标的Long Number元素。然后,先被保存的Foo对象成功,第二个保存到数据库的,就引发主键冲突了。
这个问题在开发时是很难想到的。
这个问题,可以按如下方式解决。
两个方法:
1.代码级互斥。
2.重试。
分享到:
相关推荐
让我们详细了解一下`HibernateSessionFactory`类中的关键方法和其背后的原理。 1. **配置和初始化SessionFactory** `HibernateSessionFactory`类通过`cfg.configure(CONFIG_FILE_LOCATION)`来读取配置文件(默认为...
这个标题指出我们要讨论的是Hibernate框架在处理查询和数据库并发事务方面的内容。Hibernate是一个流行的Java对象关系映射(ORM)工具,它允许开发者使用面向对象的方式操作数据库,而无需过多关注底层SQL语言。在第...
- **扩展周期的 Session 和自动版本化**:Hibernate 使用扩展周期的 Session 来提供自动版本检查,可以在同步时检测并发修改并抛出异常。这种方式更为高效,减轻了开发者的负担。 #### 七、总结 Hibernate 的事务...
当我们在Hibernate中使用懒加载或集合查询时,如果在一次循环中对每个实体逐一触发关联对象的加载,就会产生N+1次数据库查询。例如,假设有一个`Order`实体,它有一对多的关联关系到`Product`实体,我们想要获取所有...
在Hibernate中,事务、并发控制和缓存管理是至关重要的概念,它们极大地影响了应用程序的性能和数据一致性。 一、Hibernate事务管理 在数据库操作中,事务确保了数据的一致性和完整性。Hibernate提供了四种事务隔离...
为了解决N+1问题,Hibernate推荐使用list()方法来替代iterator()方法。使用list()时,Hibernate会一次性发出一条SQL语句来获取所有的对象信息,而不是每获取一个对象就发一条SQL语句。这样可以有效地减少数据库的...
使用`List`查询时,Hibernate会一次性将所有数据加载到内存中,这可能导致内存不足的问题。而使用`Iterator`进行查询时,每次只加载一条数据,这样可以有效避免内存溢出的风险,同时也减少了数据库的压力。 #### 七...
10. 事务和并行:这部分内容将介绍如何使用Hibernate处理数据库事务,以及如何确保数据的一致性和并发控制。 11. Hibernate查询语言:Hibernate Query Language(HQL)是用于操作持久化数据的一种面向对象的查询...
第一部分 从Hibernate和EJB 3.0开始 第1章 理解对象/关系持久化 1.1 什么是持久化 1.1.1 关系数据库 1.1.2 理解SQL 1.1.3 在Java中使用SQL 1.1.4 面向对象应用程序中的持久化 1.2 范式不...
- **值类型**: 包括基本类型、复合类型、集合类型。 - **实体类型**: 映射实体类型的细节。 - **类型分类的意义**: 不同类型的区别及其用途。 - **定制类型**: - **使用org.hibernate.type.Type**: 创建自定义类型...
在关系数据库中,集合类型的数据(如Set、List、Map)不能直接存储,而Hibernate提供了将这些集合类型映射到数据库中的机制,如使用`Set`和`Map`映射关联关系,这使得Java对象的集合属性可以直接与数据库中的记录...
16. **更新和删除操作**:`update()`和`delete()`方法分别用于更新和删除数据库中的记录,但要注意事务的正确管理和并发问题。 17. **日志配置**:Hibernate允许配置日志输出,这对于调试和优化性能非常有帮助。 ...
1.3.4. 值类型的集合 1.3.5. 双向关联 1.3.6. 使双向连起来 1.4. 第三部分 - EventManager web应用程序 1.4.1. 编写基本的servlet 1.4.2. 处理与渲染 1.4.3. 部署与测试 1.5. 总结 2. 体系结构(Architecture...
- **类型映射**:Java 类型、SQL 类型和 Hibernate 映射类型的对应,例如使用 Hibernate 的用户类型实现自定义类型映射。 3. **Hibernate API 数据操作**: - 使用 `save()`、`update()`、`delete()` 方法对对象...
这本书涵盖了Hibernate的基本配置、持久化类、集合类的映射以及事务和并发管理等多个重要方面。 一、Hibernate入门 Hibernate是一个开源的Java ORM(对象关系映射)框架,它允许开发人员使用面向对象的方式来处理...
书中可能包含了一系列解决实际问题的代码示例和最佳实践,涉及的主题可能有: 1. 高级映射:复杂关系(如一对一、一对多、多对多)的映射,以及自定义类型映射。 2. 查询优化:包括 HQL 和 SQL 联合查询,子查询,...
本教程将深入探讨Hibernate的核心特性和使用方法,帮助开发者更好地理解和应用这个强大的工具。 **一、Hibernate概述** Hibernate是一个开源的ORM框架,它的主要作用是将Java类与数据库表进行映射,实现了对象与...
10.3.1 区分值(Value)类型和实体(Entity)类型 10.3.2 在应用程序中访问具有组成关系的持久化类 10.4 映射复合组成关系 10.5 小结 10.6 思考题 第11章 Hibernate的映射类型 11.1 Hibernate的内置映射...
Hibernate 支持事务处理和并发控制。事务处理可以是本身事务处理或与外部代码实务操作集成。并发控制可以使用乐观锁或悲观锁等方式。 拦截器和事件处理 Hibernate 支持拦截器和事件处理,可以在对象的生命周期中...
二级缓存可以通过设置不同的并发访问策略来解决并发问题,如事务型、读写型或非严格读写型,以适应不同场景下的需求。 持久化层的缓存范围决定了缓存的生命周期和访问权限。事务范围的缓存最安全,但只限于当前事务...