Проблема с общим кэшем в JPA 2.0 для DuplicateKeys

Этот пост касается проблемы с JPA. В качестве поставщика JPA используется Oracle Toplink, предоставляемый weblogic 12c и построенный с использованием EclipseLink.

Пользователь выполняет n взаимодействий / транзакций, а приложение записывает каждую транзакцию в БД. При большой нагрузке при записи транзакций приложение сталкивается с дублированием исключений ключей.

1-я транзакция успешно записывается в БД, но последующая транзакция иногда отклоняется с исключением с дубликатом ключа.

Как я уже сказал, приложение использует JPA 2.0, в котором общий кэш включен по умолчанию, и я думаю, что это как-то связано с общим кешем.

Я говорю это потому, что то же приложение прекрасно работает в Weblogic 10, который использует JPA 1.0, и в нем нет концепции общего кэша.

Теперь вернемся к вопросу: каждая сущность, участвующая в транзакции вставки, уникальным образом идентифицируется встроенным классом первичного ключа с переопределенным хэш-кодом /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;
    }
}

Первичный ключ является комбинацией идентификатора сеанса (FIRST_USER_SESSION) и номера транзакции (01 для первой вставки, 02 для второй вставки....) Например, для: FIRST_USER_SESSION и 01

1-я транзакция, ПК: FIRST_USER_SESSION01 2-я транзакция, ПК: FIRST_USER_SESSION02

  1. Перед записью 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()).

В результате один и тот же дубликат объекта предпринимается для вставки, и генерируется исключение ключа дуликата.

Вопрос 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 ответов

Другие вопросы по тегам