Проблема кеширования заключается в том, что Hibernate по умолчанию использует диалект Oracle, который выполняет две функции.Он создает последовательность, общую для всех таблиц, для генерации первичного ключа, и последовательность кэширует по 20 чисел за раз, которые, если они не используются в течение определенного периода времени, Oracle отбросит остаток.
Следующее решение Oracleвзято из поста Берта Беквита с твиком по предотвращению кэширования чисел в последовательности Oracle.Таким образом, этот диалект сделает для вас две вещи:
- Он создаст одну последовательность для каждой таблицы, поэтому последовательность не будет общей, а номера первичных ключей не распределены по таблицам.
- Это отключит кеширование чисел в Oracle, поэтому вы не потеряете порядковые номера в просроченном кеше.Это задается в свойстве
PARAMETERS
с помощью команды NOCACHE
.
Поскольку вы определяете последовательность своей таблицы в отображении, вы, вероятно, можете удалить последовательность для каждой логики таблицы и оставить вNOCACHE
определение последовательности для достижения желаемых результатов.
Кроме того, вам нужно будет удалить последовательность из существующего табличного пространства, поскольку Grails не создаст ее заново, за исключением create
и create-drop
сценарии.При этом вам также может понадобиться увеличить начальное значение новой последовательности, чтобы предотвратить конфликтующие проблемы первичных ключей с ключами, уже используемыми базой данных.
Чтобы использовать диалект, добавьте dialect = SequencePerTableOracleDialect
к вашему DataSource.groovy
файл в закрытии определения источника данных.
import java.util.Properties;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.Oracle10gDialect;
import org.hibernate.id.PersistentIdentifierGenerator;
import org.hibernate.id.SequenceGenerator;
import org.hibernate.type.Type;
public class SequencePerTableOracleDialect extends Oracle10gDialect {
public static final String PARAMETERS = "MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 NOCACHE NOCYCLE";
/**
* Get the native identifier generator class.
*
* @return TableNameSequenceGenerator.
*/
@Override
public Class<?> getNativeIdentifierGeneratorClass() {
return TableNameSequenceGenerator.class;
}
/**
* Creates a sequence per table instead of the default behavior of one
* sequence.
*/
public static class TableNameSequenceGenerator extends SequenceGenerator {
/**
* {@inheritDoc} If the parameters do not contain a
* {@link SequenceGenerator#SEQUENCE} name, we assign one based on the
* table name.
*/
@Override
public void configure(final Type type, final Properties params,
final Dialect dialect) {
if (params.getProperty(SEQUENCE) == null
|| params.getProperty(SEQUENCE).length() == 0) {
/* Sequence per table */
String tableName = params
.getProperty(PersistentIdentifierGenerator.TABLE);
if (tableName != null) {
params.setProperty(SEQUENCE, createSequenceName(tableName));
}
/* Non-Caching Sequence */
params.setProperty(PARAMETERS, SequencePerTableOracleDialect.PARAMETERS);
}
super.configure(type, params, dialect);
}
/**
* Construct a sequence name from a table name.
*
* @param tableName
* the table name
* @return the sequence name
*/
String createSequenceName(final String tableName) {
return "seq_" + tableName;
}
}
}
Эта ссылка имеет некоторую историю по этому вопросу со ссылкой на оригинальный код Берта и ответом для PostGreSql: Hibernate & postgreSQL с Grails