关于EclipseLink 2.5.0 HashPartition小BUG的关注

项目中使用了JPA Partition的方式进行分库,并没有采用阿里的那套读写分离(太繁琐、太繁琐...)。当下,最好的provider应该是hibernate,只可惜这项功能官方说是到5.0版本才能支持,碰巧eclipselink 2.5.0中实现了此功能,因此就选择了eclipse link。

其中的HashPartition说来也简单,就是把数据中涉及到分库字段的相关查询、持久化的操作指向到连接池的制定数据库上。说来应用起来也是比较简单。

@HashPartitioning(name="HashPartitionBySubId", [email protected](name="subId"), connectionPools={"default","node1"})

@Partitioned("HashPartitionBySubId")

public class SubEntity{

}

可能是使用正值数值做索引的缘故吧,2.5.0并没有注意到在做hash值得时候有可能出现负值的问题,因而会造成 ArrrayIndexBoundException 的错误。贴上代码一览:

org.eclipse.persistence.core-2.5.0.jar 包中 org.eclipse.persistence.descriptors.partitioning.HashPartitioningPolicy中:

/**

* INTERNAL:

* Get a connection from one of the pools in a round robin rotation fashion.

*/

public List<Accessor> getConnectionsForQuery(AbstractSession session, DatabaseQuery query, AbstractRecord arguments) {

Object value = arguments.get(this.partitionField);

if (value == null) {

if (this.unionUnpartitionableQueries) {

// Use all connections.

List<Accessor> accessors = new ArrayList<Accessor>(this.connectionPools.size());

for (String poolName : this.connectionPools) {

accessors.add(getAccessor(poolName, session, query, false));

}

return accessors;

} else {

// Use default behavior.

return null;

}

}

int index = value.hashCode() % this.connectionPools.size();

if (session.getPlatform().hasPartitioningCallback()) {

// UCP support.

session.getPlatform().getPartitioningCallback().setPartitionId(index);

return null;

}

// Use the mapped connection pool.

List<Accessor> accessors = new ArrayList<Accessor>(1);

String poolName = this.connectionPools.get(index);

accessors.add(getAccessor(poolName, session, query, false));

return accessors;

}

其中问题出在 varlue.hashCode()上,该内容可能为负值,通过mod计算后,出来的index成为负值,直接造成connectionPools.get(index)越界。

当下,好在2.5.2对这一BUG进行了修正。

/**

* INTERNAL:

* Get a connection from one of the pools in a round robin rotation fashion.

*/

public List<Accessor> getConnectionsForQuery(AbstractSession session, DatabaseQuery query, AbstractRecord arguments) {

Object value = arguments.get(this.partitionField);

if (value == null) {

if (this.unionUnpartitionableQueries) {

// Use all connections.

List<Accessor> accessors = new ArrayList<Accessor>(this.connectionPools.size());

for (String poolName : this.connectionPools) {

accessors.add(getAccessor(poolName, session, query, false));

}

return accessors;

} else {

// Use default behavior.

return null;

}

}

int index = Math.abs(value.hashCode()) % this.connectionPools.size();

if (session.getPlatform().hasPartitioningCallback()) {

// UCP support.

session.getPlatform().getPartitioningCallback().setPartitionId(index);

return null;

}

// Use the mapped connection pool.

List<Accessor> accessors = new ArrayList<Accessor>(1);

String poolName = this.connectionPools.get(index);

accessors.add(getAccessor(poolName, session, query, false));

return accessors;

}

所以如果使用JPA PARTITION功能的朋友,最好把版本提升到2.5.2.

时间: 2024-11-07 13:16:35

关于EclipseLink 2.5.0 HashPartition小BUG的关注的相关文章

【ASP.net控件】DropDownList数据绑定一个小bug

绑定数据出现这种情况,明明在第一项插入了一条数据,却始终在DropDownList中没有显示出来. 代码如下: if (!IsPostBack) { //绑定城市 DataTable dtCity = new HighSearch().GetCitySelect(); DropDownList1.DataSource = dtCity; DropDownList1.DataValueField = "citycode"; DropDownList1.DataTextField = &q

ShardedJedisPool 中可用连接数的小bug

ShardedJedisPool中,returnBrokenResource() 及 returnResource() ,为施放资源.关闭连接的方法,若重复调用,导致 _numActive 当前活动数一直递减,会出现负数的情况. 假如在一个方法中设置了三个jedis连接,在获取第一或第二个连接时出现异常,在抛出异常或者finally中总是施放这三个资源,会导致池中的连接连续施放三次,从而变成负数. 这样会出现连接池最大连接数配置无效的情况. 以下片段代码: public class RedisU

vue示例之transition-另外发现一个vue(可能的)小bug

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link href="//cdn.bootcss.com/animate.css/3.5.2/animate.css" rel="stylesheet"> <style&

Win10 UWP系列:关于错误 0x80073CF9及一个小bug的解决

原文:Win10 UWP系列:关于错误 0x80073CF9及一个小bug的解决 最近一直在开发XX的uwp版本,也是边摸索边做,最近遇到几个比较奇怪的问题,记录于此. 1.项目可用部署到PC,但无法部署到手机,提示以下错误: 错误 : DEP0001 : 意外错误: Install failed. Please contact your software vendor. (Exception from HRESULT: 0x80073CF9 为了方便开发,我将常用的类库引用好.默认的几个页面做

js动画--一个小bug处理下

对于上面的课程我们很好的处理了一个小bug,那么我们现在讲程序进行优化一下,前一节的程序中,我们处理处理的属性都是写死了的.为了我们能够很好的对某个属性进行操作的话.我们这样来设置. js文件 window.onload=function(){ var ls=document.getElementsByTagName("li"); for(var i=0,l=ls.length;i<l;i++){ ls[i].timer=null; ls[i].onmouseover=funct

关于一个小bug的修正

python初学者,非常喜欢虫师的文章. 练习时发现一个小bug,http://www.cnblogs.com/fnng/p/3782515.html 验证邮箱格式一题中,第三个x不允许有数字,但是测试发现[email protected] 仍显示验证邮箱地址正确 发现 re.match() 匹配的只是开头,故想到了分组的方法,代码如下: 1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 #Myemails.py 4 5 6 import r

base_convert()函数探秘及小bug记录

php base_convert函数原型: string base_convert ( string $number , int $frombase , int $tobase ) base_convert — 在任意进制之间转换数字返回一字符串,包含 number 以 tobase 进制的表示.number 本身的进制由 frombase 指定.frombase 和 tobase 都只能在 2 和 36 之间(包括 2 和 36).高于十进制的数字用字母 a-z 表示,例如 a 表示 10,b

一个短路求值引起的一个小bug

今天在写一个判断字符串是否回文时因为短路求值问题导致了一个bug,记录如下: 代码如下 bool isPal(char str[],int len) { int begin=0; int end=len-1; bool result=true; cout<<str<<endl; while(begin<end) { result=result&&(str[begin++]==str[end--]); } cout<<"after &quo

Fundebug前端JavaScript插件更新至1.8.2,修复2个小BUG

摘要: 修复2个BUG,请大家及时更新. Fundebug前端异常监控服务 Fundebug是专业的程序异常监控平台,我们JavaScript插件可以提供全方位的异常监控,可以帮助开发者第一时间定位各种前端异常,包括: JavaScript执行错误 资源加载错误 HTTP请求错误 unhandledrejection WebSockect连接错误 并且,我们可以记录用户行为."录制"用户操作视频,帮助开发者快速复现BUG,提高Debug效率. Fundebug前端异常监控插件更新至1.