J'ai récemment mis à jour hibernate dans mon application vers 5.4.4.Final. Et maintenant, j'ai rencontré l'exception suivante lors du déploiement.
ERROR [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentImpl|[STANDBY] ExecuteThread: '5' for queue: 'weblogic.kernel.Default (self-tuning)']
Could not fetch the SequenceInformation from the database
Java.sql.SQLException: Numeric Overflow
at Oracle.jdbc.driver.NumberCommonAccessor.throwOverflow(NumberCommonAccessor.Java:4136)
at Oracle.jdbc.driver.NumberCommonAccessor.getLong(NumberCommonAccessor.Java:634)
at Oracle.jdbc.driver.GeneratedStatement.getLong(GeneratedStatement.Java:206)
at Oracle.jdbc.driver.GeneratedScrollableResultSet.getLong(GeneratedScrollableResultSet.Java:259)
at Oracle.jdbc.driver.GeneratedResultSet.getLong(GeneratedResultSet.Java:558)
at weblogic.jdbc.wrapper.ResultSet_Oracle_jdbc_driver_ForwardOnlyResultSet.getLong(Unknown Source)
at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.resultSetMaxValue(SequenceInformationExtractorLegacyImpl.Java:139)
at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.extractMetadata(SequenceInformationExtractorLegacyImpl.Java:61)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentImpl.sequenceInformationList(JdbcEnvironmentImpl.Java:403)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentImpl.<init>(JdbcEnvironmentImpl.Java:268)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.Java:114)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.Java:35)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.Java:101)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.Java:263)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.Java:237)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.Java:214)
at org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory.injectServices(DefaultIdentifierGeneratorFactory.Java:152)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.injectDependencies(AbstractServiceRegistryImpl.Java:286)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.Java:243)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.Java:214)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.<init>(InFlightMetadataCollectorImpl.Java:175)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.Java:118)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.Java:900)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.Java:931)
at org.hibernate.jpa.HibernatePersistenceProvider.createContainerEntityManagerFactory(HibernatePersistenceProvider.Java:141)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.Java:343)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.Java:318)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.Java:1633)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.Java:1570)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.Java:539)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.Java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.Java:303)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.Java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.Java:299)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.Java:194)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.Java:956)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.Java:747)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.Java:480)
at com.sternkn.app.services.web.AppContextLoaderListener.<clinit>(AppContextLoaderListener.Java:30)
J'utilise le persistence.xml suivant.
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd"
version="2.2">
<persistence-unit name="appPersistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle12cDialect" />
<property name="hibernate.id.new_generator_mappings" value="true"/>
<property name="hibernate.cache.use_second_level_cache" value = "true"/>
<property name="hibernate.cache.use_query_cache" value="false" />
<property name="hibernate.cache.region.factory_class" value="ehcache"/>
<property name="hibernate.cache.ehcache.missing_cache_strategy" value="create" />
<property name="hibernate.cache.region_prefix" value="app_cache" />
<property name="net.sf.ehcache.configurationResourceName" value="/META-INF/app-ehcache.xml" />
<property name="hibernate.bytecode.provider" value="bytebuddy" />
</properties>
</persistence-unit>
</persistence>
Après une enquête plus approfondie, j'ai découvert que la cause première est la suivante: hibernate utilise l'interface SequenceInformation pour les manipulations de métadonnées de séquences
public interface SequenceInformation {
Long getMinValue();
Long getMaxValue();
Long getIncrementValue();
...
}
Cependant, mon application utilise les séquences comme suit:
SQL> CREATE SEQUENCE SEQ_TEST START WITH 1 INCREMENT BY 1 NOCYCLE;
SQL> select MIN_VALUE, MAX_VALUE, INCREMENT_BY
from USER_SEQUENCES
where SEQUENCE_NAME = 'SEQ_TEST';
MIN_VALUE MAX_VALUE INCREMENT_BY
--------- ---------------------------- ------------
1 9999999999999999999999999999 1
Le Long.MAX_VALUE est égal à 9223372036854775807, donc j'ai eu l'exception de dépassement numérique.
Alors, mes questions:
Maintenant, je vois les façons suivantes:
public class Oracle8iDialect extends Dialect {
...
public String getQuerySequencesString() {
return "select * from all_sequences";
}
public SequenceInformationExtractor getSequenceInformationExtractor() {
return SequenceInformationExtractorOracleDatabaseImpl.INSTANCE;
}
}
Je peux basculer SequenceInformationExtractor sur SequenceInformationExtractorNoOpImpl.INSTANCE et hibernate ne lira pas les séquences métadonnées. Quel impact cette décision aura-t-elle? Hibernate essaie de valider allocationSize de @SequenceGenerator () par INCREMENT_BY. Y a-t-il d'autres raisons?
Toute suggestion sera appréciée.
[~ # ~] mise à jour [~ # ~] : c'est HHH-13694
J'ai résolu le problème comme suit. Création d'une extension pour Oracle12cDialect. Limité la valeur maximale/minimale des colonnes à SQL
package ru.mvawork.hibernate;
import org.hibernate.dialect.Oracle12cDialect;
@SuppressWarnings("unused")
public class CustomOracleDialect extends Oracle12cDialect {
@Override
public String getQuerySequencesString() {
return "select SEQUENCE_OWNER, SEQUENCE_NAME, greatest(MIN_VALUE, -9223372036854775807) MIN_VALUE,\n"+
"Least(MAX_VALUE, 9223372036854775808) MAX_VALUE, INCREMENT_BY, CYCLE_FLAG, ORDER_FLAG, CACHE_SIZE,\n"+
"Least(greatest(LAST_NUMBER, -9223372036854775807), 9223372036854775808) LAST_NUMBER,\n"+
"PARTITION_COUNT, SESSION_FLAG, KEEP_VALUE\n"+
"from all_sequences";
}
}
Dans le fichier application.properties fait référence à une implémentation de dialecte
spring.jpa.properties.hibernate.dialect=ru.mvawork.hibernate.CustomOracleDialect
Vous pouvez recréer des séquences en limitant les valeurs minimales et maximales. Dans mon cas, je ne peux pas le faire. Les clés primaires que j'utilise ont le numéro de dimension (12), qui se situe dans la limite de plage de -9223372036854775807 à 9223372036854775808 avec une grande marge