Проблема с общим кэшем в 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-й транзакции вставки (сущность с pk FIRST_USER_SESSION 01) она проверяется в кеше L2 и, поскольку она не в кеше, успешно сохраняется в БД.
После записи первой транзакции она обновляется в кеше L2 (объект с ключом FIRST_USER_SESSION 01 кэшируется)
Теперь для второй транзакции вставки (сущность с ключом 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