Skip to content

Add setReadOnly=false functionality on Connection class #6012

Description

@jeffrytyn

Is your feature request related to a problem? Please describe.
When working with Hibernate/Spring JPA, sometimes the connection is set to read-only since SimpleJpaRepository is readOnly=true by default. This leads to errors when later trying to do writes

o.s.j.d.DataSourceUtils [task-1] - Setting JDBC Connection [HikariProxyConnection@210385308 wrapping com.bloomberg.comdb2.jdbc.Comdb2Connection@794d28a3] read-only
...
DEBUG  o.s.j.d.DataSourceUtils [task-1] - Resetting read-only flag of JDBC Connection [HikariProxyConnection@210385308 wrapping com.bloomberg.comdb2.jdbc.Comdb2Connection@794d28a3]
...
2026-06-05 13:36:35.215 INFO   o.h.orm.jdbc.batch [task-1] - HHH100503: On release of batch it still contained JDBC statements
2026-06-05 13:36:35.215 DEBUG  o.h.e.j.s.SqlExceptionHelper [task-1] - could not execute batch [insert into attribute_hash_registry (attribute_data,attribute_source,created_at,created_by,source_id,attribute_hash) values (?,?,?,?,?,?)] java.sql.SQLNonTransientException: [RC = -21] connection/database in read-only mode 	at com.bloomberg.comdb2.jdbc.Comdb2Connection.createSQLException(Comdb2Connection.java:758) 	at com.bloomberg.comdb2.jdbc.Comdb2Statement.executeQuery(Comdb2Statement.java:141) 	at com.bloomberg.comdb2.jdbc.Comdb2Statement.executeQuery(Comdb2Statement.java:73) 	at com.bloomberg.comdb2.jdbc.Comdb2Statement.executeUpdate(Comdb2Statement.java:165) 	at com.bloomberg.comdb2.jdbc.Comdb2PreparedStatement.executeUpdate(Comdb2PreparedStatement.java:84) 	at com.bloomberg.comdb2.jdbc.Comdb2PreparedStatement.executeBatch(Comdb2PreparedStatement.java:380) 	at com.zaxxer.hikari.pool.ProxyStatement.executeBatch(ProxyStatement.java:128) 	at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeBatch(HikariProxyPreparedStatement.java) 	at org.hibernate.engine.jdbc.batch.internal.BatchImpl.lambda$performExecution$2(BatchImpl.java:279) 	at org.hibernate.engine.jdbc.mutation.internal.PreparedStatementGroupSingleTable.forEachStatement(PreparedStatementGroupSingleTable.java:67) 	at org.hibernate.engine.jdbc.batch.internal.BatchImpl.performExecution(BatchImpl.java:264) 	at org.hibernate.engine.jdbc.batch.internal.BatchImpl.execute(BatchImpl.java:242) 	at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.executeBatch(JdbcCoordinatorImpl.java:188) 	at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:674) 	at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:511) 	at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:414) 	at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:41) 	at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:127) 	at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1429) 	at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:491) 	at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2354) 	at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:1978) 	at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:439) 	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:169) 	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:267) 	at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101) 	at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:563) 	at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:795) 	at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:758) 	at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:698) 	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:416) 	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) 	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) 	at ...

The "resetting" log line shows that con.setReadOnly(false) is called, but the later write still fails because of this read-only error.

Describe the solution you'd like
Add functionality to support setReadOnly(false) i.e. enable writes on the connection as well.
Example from Postgres
https://github.com/pgjdbc/pgjdbc/blob/ffe5827abfcb538cb8651b484674ade936286bef/pgjdbc/src/main/java/org/postgresql/jdbc/PgConnection.java#L931

Describe alternatives you've considered
In Java applications, you could create a new base repository class with @Transactional(readOnly=false) instead of using SimpleJpaRepository, but this is just inconvenient compared to the Comdb2 connection supporting enabling writes on the connection. Also, you would only do that if you knew this issue existed. In this case, I didn't and had to investigate to come up with this workaround

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions