DuplicateKeys的JPA 2.0共享缓存问题

时间:2014-04-07 16:35:19

标签: jpa eclipselink weblogic12c toplink shared-cache

这篇文章是关于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

  1. 在编写第一个插入事务(具有pk FIRST_USER_SESSION 01的实体)之前,它已检入L2缓存,因为它不在缓存中,所以它已成功保存到数据库。

  2. 写完第一个事务后,它在L2缓存中更新。(缓存了FIRST_USER_SESSION 01键的实体)

  3. 现在对于第二个插入事务(具有密钥FIRST_USER_SESSION 02的实体),在持久化之前检查L2缓存,并且我猜测第二个事务的实体被认为与L2缓存中已有的实体相同。即使pk不同(FIRST_USER_SESSION02),我认为框架将其标识为重复对象。(基于equals()和hashcode()覆盖)

  4. 因此,尝试插入相同的重复对象,并抛出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发送足够的消息

0 个答案:

没有答案