hibernate映射异常,oracle 表名和字段名有么有大小写区分的问题。

本文解决了一个关于Oracle数据库中字段大小写敏感导致的Hibernate同步异常问题。通过调整表定义方式,确保字段名称与映射文件一致,避免了大小写引起的错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题源于这样一个异常:
Could not synchronize database state with session
org.hibernate.exception.SQLGrammarException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:90)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:167)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
at com.feosa.common.dao.BaseDao.flush(BaseDao.java:340)
at com.feosa.common.service.BaseService.flush(BaseService.java:311)
at com.feosa.framework.workflow.blservice.FlowFormBLServiceTest.initData(FlowFormBLServiceTest.java:57)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59)
at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:98)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:79)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:87)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42)
at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:88)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.sql.BatchUpdateException: ORA-00904: "INPUTCODE": 标识符无效

at oracle.jdbc.driver.DatabaseError.throwBatchUpdateException(DatabaseError.java:343)
at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:10720)
at org.apache.commons.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:297)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
... 30 more


我仔细核对了hibernate的映射文件和表名(不考虑大小写的情况下)。保证一致了,但还是报这个错。
我创建表的语句是:
CREATE TABLE "RISK"."FE_FIELD_INPUT"  (
"ID" INTEGER NOT NULL,
"inputname" VARCHAR2(100),
"inputcode" VARCHAR2(100),
CONSTRAINT PK_FE_FIELD_INPUT PRIMARY KEY ("ID")
);


注意看,字段名是加了引号的,查看一下创建后的表,在数据库中显示确实是小写的。
所以会报上面的异常。hibernate会自动将字段名改成大写。而我数据库中是小写。

但是如果我创建语句字段名没有引号的话,oracle是不区分大小写的,会自动转换成大写。所以之前没有遇到过这种问题。
正确的创建表的语句是:
CREATE TABLE RISK.FE_FIELD_INPUT  (
ID INTEGER NOT NULL,
inputname VARCHAR2(100),
inputcode VARCHAR2(100),
CONSTRAINT PK_FE_FIELD_INPUT PRIMARY KEY ("ID")
);
### 后端运行数据库大小写不兼容的解决方案 对于不同类型的数据库,在处理SQL语句以及对象称(如字段名存在显著差异。具体到MySQL、OraclePostgreSQL,这些数据库对待标识符大小写的策略有所不同。 #### MySQL中的大小写敏感性 在MySQL中,默认情况下,Linux上的区分大小写的,而Windows上则不是[^1]。这意味着在同一操作系统环境下创建的两个仅大小写字母不同的会被视为同一个实体;但在另一些环境中可能会被当作完全独立的对象来处理。因此当应用程序从一种环境迁移到另一种就可能出现访问不到预期格的情况。 为了确保跨平台的一致性稳定性,建议采用统一的小写命约定,并通过配置文件设置`lower_case_table_names=1`参数使得服务器忽略中的大写字母。 #### Oracle与PostgreSQL中的大小写规则 相比之下,Oracle默认会将未加双引号包裹的字转换成全大写形式存储并识别它们。如果使用了双引号,则严格遵循所指定的形式保存下来,无论是小写还是混合大小写都会保持原样不变。 PostgreSQL也有类似的机制——无特殊字符修饰的情况下自动变为小写,一旦加上双引号就会按照输入的样子记录下来。 针对上述特性,在涉及多数据库支持的应用程序设计阶段就应该充分考虑到这一点: - **代码层面** - 使用ORM框架可以有效减少直接书写原始SQL带来的风险。例如JPA/Hibernate能够自动生成符合目标DBMS语法习惯的查询语句; ```java @Entity(name="users") // 将逻辑模型映射至物理结构强制规定为特定格式 public class User { } ``` - **部署方面** - 如果无法更改现有架构或迁移数据源的话,那么可以在连接字符串里加入必要的选项让驱动程序帮助调整行为模式。比如某些版本的JDBC URL允许附加属性控制这一过程。 ```properties spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC&useInformationSchema=true&autoReconnect=true&failOverReadOnly=false&maxReconnects=10&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&useUnicode=yes&rewriteBatchedStatements=true&tinyInt1isBit=false&nullNamePatternMatchesAll=true&allowPublicKeyRetrieval=true&useLegacyDatetimeCode=false&cachePrepStmts=true&prepStmtCacheSize=250&prepStmtCacheSqlLimit=2048&elideSetAutoCommits=true&maintainTimeStats=false&sessionVariables=time_zone='+00:00'&useAffectedRows=true&noAccessToProcedureBodies=true&transformedBitIsBoolean=true&dontTrackOpenResources=true&defaultFetchSize=1000&alwaysSendSetIsolation=false&disableStatementPooling=true&reportMetricsIntervalMillis=-1&logger=com.mysql.cj.log.StandardLogger&profileSQL=false&enablePacketDebug=false&slowQueryThresholdNanos=0&traceProtocol=false&dumpQueriesOnException=false&loadBalanceBlacklistTimeout=5000&tcpKeepAlive=true&tcpRcvBuf=0&tcpSndBuf=0&socketTimeout=0&connectTimeout=0&interactiveClient=false&clientCertificateKeyStoreUrl=&clientCertificateKeyStorePassword=&trustServerCertificate=false&verifyServerCertificate=true&useSSL=true&requireSSL=false&useDefaultTimeZone=false&createDatabaseIfNotExist=false&includeInnodbStatusInDeadlockErrors=false&paranoid=false&pinGlobalTxToPhysicalConnection=false&retriesAllDown=false&roundRobinLoadBalance=false&secondsBeforeRetryMaster=30&initialTimeout=2&clearContextInfo=true&resetSession=false&overrideSupportsIntegrityEnhancementFacility=false&emulateUnsupportedPstmts=true&padCharsWithSpace=false&distinguishIdentifiersCase=false&ignoreNonTransactionTables=false&readOnlyPropagatesToServer=false&readFromPrimaryWhenFromSlaveFails=false&replicationEnableJMX=false&statementInterceptors=&queryInterceptors=&jdbcCompliantTruncation=true&yearIsDateType=true&noDatetimeStringSync=false&nullCatalogMeansCurrent=false&functionsNeverReturnStrings=false&tinyInt1isBit=true&strictFloatingPoint=false&emptyStringsConvertToZero=false&elideSetAutoCommits=false&useLocalTransactionState=false&rollbackOnPooledClose=false&netTimeoutForStreamingResults=0&getProceduresReturnsFunctions=false&metadataUseInfoSchema=false&metadataCapableOfDuplicateColumnName=false&includeInvisibleColumns=false&includeConfigurationProperties=false&includeThreadDumpInDeadlockExceptions=false&includeThreadNamesAsStatementComment=false&includeHostPortPairInToString=false&includeLastInsertIDInResultSet=false&includeRowIDInResultSet=false&includeTabledefsInMetadataSpooling=false&includeTimestampLabelInProfile=false&includeXidInCommitRollback=false&largeFileUploadBufferSize=0&localSocketAddress=&logSlowQueries=false&loginTimeout=0&lobBufferLength=1MB&lobStreamChunkSize=1KB&longStackTrace=true&manuallySpecifyMaxAllowedPacket=false&maxAllowedPacket=1GB&multiHostFailoverAttempts=0&numTriesBeforeBreak=3&packetDebugContents=FULL&passwordCharacterEncoding=UTF-8&pedantic=false&preferPrepare=false&processEscapeCodesForPrepStmts=true&propertyCycle=200&queriesBeforeRetryMaster=50&quickServerLossDetection=false&relaxAutoCommit=false&removeSTGfrom consideration=false&reportMetricsIntervalMillis=-1&resultSetSizeThreshold=0&sendFractionalSeconds=false&serverPreparedStatementCacheAccesses=0&serverPreparedStatementCacheMisses=0&serverPreparedStatementCacheSize=0&setCollationcharsetAtConnect=false&skipCheckForLatestVersion=false&smallResultSetsFirstFromSecondary=false&socketFactory=defaultSocketFactory&sslMode=PREFERRED&stripComments=false&tcpNoDelay=true&tinyInt1isBit=false&ultraDevHack=false&useAnsiQuotedIdentifier=false&useBlobToStoreUTF8OutsideBMP=false&useCompression=false&useCursorFetch=false&useDirectRowUnpack=false&useDynamicCharsetInfo=true&useFastIntParsing=true&useFastLongParsing=true&useFast prepared statement=true&useFullColumnNames=false&useHostsInPrivileges=false&useInformationSchema=false&useJDBCCompliantTimezoneShift=false&useJvmCharsetConverters=false&useLocalSessionState=false&useNanosForElapsedTime=false&useOldAliasMetadataBehavior=false&useOnlyServerErrorMessages=false&useReadAheadInput=false&useSSPSCompatibleTimezone=false&useServerPreparedStmts=false&useServerPreparedStmtsWithoutLimits=false&useSSL=false&useStreamLengthsInPrepStmts=true&useTimezone=false&useUltraDevWorkAround=false&useUnbufferedInputStream=false&useUsageAdvisor=false&verbose=false&waitTimeout=28800&writeTimeout=0 ``` 此URL片段展示了如何利用额外参数影响客户端的行为方式,其中部分选项可能有助于缓解由于大小写引起的兼容性难题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值