这篇文章是关于JPA的持久性问题。使用的JPA提供程序是由weblogic 12c提供的Oracle Toplink,它是使用EclipseLink构建的。
用户制作' n'交互/事务的数量,应用程序将每个事务写入数据库。在负载很重的情况下,在编写事务时,应用程序面临重复的密钥异常。
第一个事务成功写入数据库但后续事务有时会被拒绝 重复的关键异常。
正如我所说,该应用程序使用JPA 2.0,默认情况下启用共享缓存,我认为这与共享缓存有关。
我这样说是因为同样的应用程序在使用JPA 1.0的Weblogic 10中运行良好,并且没有共享缓存的概念。
现在回到问题,参与插入事务的每个实体由嵌入式主键类唯一标识,并带有重写的hashcode / equals() (请参阅下面的课程定义)。
@EmbeddedId
private CallerEntityPK pk;
//@Column attributes
}
@Embeddable
public class CallerEntityPK implements Serializable {
@Column(name="SESSION_ID")
private String sessionId; //FIRST_USER_SESSION,SECOND_USER_SESSION
@Column(name="TRANSACTION_NBR")
private String transNo; //01 , 02 etc...
//Getter setters
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if ( ! (o instanceof CallerEntity )) {
return false;
}
CallerEntity other = (CallerEntity ) o;
return this.sessionId.equals(other.sessionId)
&& this.transNo.equals(other.transNo;);
}
@Override
public int hashCode() {
final int prime = 31;
int hash = 17;
hash = hash * prime + this.sessionId.hashCode();
hash = hash * prime + this.transNo.hashCode();
return hash;
}
}
主键是sessionid(FIRST_USER_SESSION)和事务编号的组合(第一次插入为01,第二次插入为02)。 例如:FIRST_USER_SESSION和01
第一笔交易pk:FIRST_USER_SESSION01 第二笔交易pk:FIRST_USER_SESSION02
在编写第一个插入事务(具有pk FIRST_USER_SESSION 01的实体)之前,它已检入L2缓存,因为它不在缓存中,所以它已成功保存到数据库。
写完第一个事务后,它在L2缓存中更新。(缓存了FIRST_USER_SESSION 01键的实体)
现在对于第二个插入事务(具有密钥FIRST_USER_SESSION 02的实体),在持久化之前检查L2缓存,并且我猜测第二个事务的实体被认为与L2缓存中已有的实体相同。即使pk不同(FIRST_USER_SESSION02),我认为框架将其标识为重复对象。(基于equals()和hashcode()覆盖)
因此,尝试插入相同的重复对象,并抛出dulicate键异常。
问题1) 我的理解是否正确?问我这个问题的原因是每个实体都有唯一的密钥,这种情况只发生在高容量时。可能是某些其他事务(实体)返回相同的哈希码并使对象相同。
问题2)
如果是这种情况,我可以让实体使用隔离缓存并始终刷新并立即过期(如下面的代码所示)。
我只想为此实体禁用缓存,请让我知道您的意见
@Entity
@Table(name="T_CALLER_TRANS")
@Cache(isolation=CacheIsolationType.ISOLATED, expiry=0, alwaysRefresh=true)
public class CallerEntity implements Serializable {
}
问题3) 在我进行此更改后,我需要加载测试应用程序。应用程序的用户通过MQ和HTTP进行交互。我需要向MQ发送足够的消息