There is an exception org.postgresql.util.PSQLException
with This statement has been closed.
this exception only appear in our APM, and all http requests are succeessfull with status code 200,
it occurs after the execution of @Transactional
method
foo.getBars().clear();
foo.getBars().addAll(bars);
with the mapping defined like this
@Fetch(FetchMode.SUBSELECT)
@OneToMany(
cascade = {CascadeType.ALL},
fetch = FetchType.EAGER,
orphanRemoval = true)
@JoinColumn(name = "foo_id", nullable = false)
private List<Bars> bars= new ArrayList<>();
the Bars are successfully inserted,
I just want to know why this behaviour, is it perfectly normal or I have to change something in the way i persist Bars
?
the statement that has been close is the insert
statement of Bars
when I check the code I notice that the exception is thrown but it is handled correctly with a debug message Exception clearing maxRows/queryTimeout ...
org.hibernate.resource.jdbc.internal.ResourceRegistryStandardImpl.close(ResourceRegistryStandardImpl.java:193)
Stacktrace:
org.postgresql.jdbc.PgStatement.checkClosed(PgStatement.java:745)
org.postgresql.jdbc.PgStatement.getMaxRows(PgStatement.java:548)
com.zaxxer.hikari.pool.HikariProxyPreparedStatement.getMaxRows(HikariProxyPreparedStatement.java)
org.hibernate.resource.jdbc.internal.ResourceRegistryStandardImpl.close(ResourceRegistryStandardImpl.java:193)
org.hibernate.resource.jdbc.internal.ResourceRegistryStandardImpl.release(ResourceRegistryStandardImpl.java:108)
org.hibernate.engine.jdbc.mutation.internal.PreparedStatementDetailsStandard.releaseStatement(PreparedStatementDetailsStandard.java:69)
org.hibernate.engine.jdbc.mutation.internal.MutationExecutorPostInsertSingleTable.release(MutationExecutorPostInsertSingleTable.java:115)
org.hibernate.persister.entity.mutation.InsertCoordinator.doStaticInserts(InsertCoordinator.java:186)
org.hibernate.persister.entity.mutation.InsertCoordinator.coordinateInsert(InsertCoordinator.java:111)
org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2779)
org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:81)
org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:676)
org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:291)
org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:272)
org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:322)
org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:363)
org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:277)
org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:180)
org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:140)
org.hibernate.event.internal.DefaultMergeEventListener.saveTransientEntity(DefaultMergeEventListener.java:314)
org.hibernate.event.internal.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:233)
org.hibernate.event.internal.DefaultMergeEventListener.merge(DefaultMergeEventListener.java:152)
org.hibernate.event.internal.DefaultMergeEventListener.doMerge(DefaultMergeEventListener.java:142)
org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:126)
org.hibernate.internal.SessionImpl$$Lambda$.applyEventToListener
org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:138)
org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:869)
org.hibernate.internal.SessionImpl.merge(SessionImpl.java:840)
org.hibernate.engine.spi.CascadingActions$6.cascade(CascadingActions.java:253)
org.hibernate.engine.spi.CascadingActions$6.cascade(CascadingActions.java:243)
org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:513)
org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:434)
org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:220)
org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:547)
org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:477)
org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:437)
org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:220)
org.hibernate.engine.internal.Cascade.cascade(Cascade.java:153)
org.hibernate.event.internal.DefaultMergeEventListener.cascadeOnMerge(DefaultMergeEventListener.java:571)
org.hibernate.event.internal.DefaultMergeEventListener.entityIsPersistent(DefaultMergeEventListener.java:212)
org.hibernate.event.internal.DefaultMergeEventListener.merge(DefaultMergeEventListener.java:155)
org.hibernate.event.internal.DefaultMergeEventListener.doMerge(DefaultMergeEventListener.java:142)
is it perfectly normal or I have to change something in the way i persist Bars ?
It is, you don't. Reading into the code you're showing, it looks like some logic on best effort basis:
try{}
.try{}
failed, it's assumed to be closed already.Either way, this code reaches its desired goal of making sure the statement is in closed state, even if along the way it realizes it's not the one that ended up actually closing it. It's trying to get it closed, it "fails" because it's already closed - so it catches that and reports a success, which makes sense.
I'd be worried if you were seeing anything else than This statement has been closed.
in the org.postgresql.util.PSQLException
raised there because the try{}catch(){}
doesn't do anything to make sure that's really the case - it'll catch and ignore anything database complains about. The question you could ask instead is what other SQL exceptions than This statement has been closed
you can possibly get in there: given that it's only manipulating statement config, except for the "it's already closed" you won't get anything that's worth handling there and/or won't manifest anywhere else.
You could also just check statement.isClosed()
, but it's already included in the behaviour of the four getters/setters:
Throws:
SQLException
- if a database access error occurs, this method is called on a closed Statement