blaze-persistence icon indicating copy to clipboard operation
blaze-persistence copied to clipboard

@UpdateableEntityView not working with Hibernate discriminator based multi-tenancy

Open kuhnroyal opened this issue 2 years ago • 1 comments

Description

My project uses Hibernate discriminator based multi-tenancy and reading/listing entity views works correctly, filtered by tenant. I added my first @UpdateableEntityView and I am getting parameter count errors when trying to save them.

The problem happens here https://github.com/Blazebit/blaze-persistence/blob/main/integration/hibernate6-base/src/main/java/com/blazebit/persistence/integration/hibernate/base/HibernateExtendedQuerySupport.java#L798 There are 3 participating queries and a total of 3 parameterBinders - but the finalSql only has 2 parameters. After checking the binders, it seems that the tenant ID filter from Hibernate is applied to more than on participating query and then added twice.

I assume this happens only when the entity view has an updatable relation but I still need to verify this. The same update works fine when running this without multi-tenancy enabled.

The updateable view is a user with its roles.

Expected behavior

I expect @UpdateableEntityView to work in combination with Hibernate discriminator based multi-tenancy.

Actual behavior

The following exception is thrown:

Caused by: org.hibernate.exception.DataException: JDBC exception executing SQL [delete from user_roles using users_local l1_0 join users l1_1 on l1_0.id=l1_1.id left join user_roles r1_0 on l1_1.id=r1_0.user_id where l1_1.tenant_id = ? and user_roles.user_id=? and user_roles.user_id = r1_0.user_id] [Der Spaltenindex 3 ist außerhalb des gültigen Bereichs. Anzahl Spalten: 2.] [n/a]
	at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:101)
	at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:56)
	at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:108)
	at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:94)
	at org.hibernate.sql.exec.internal.StandardJdbcMutationExecutor.execute(StandardJdbcMutationExecutor.java:96)
	at com.blazebit.persistence.integration.hibernate.base.HibernateExtendedQuerySupport.executeUpdate(HibernateExtendedQuerySupport.java:866)
	at com.blazebit.persistence.impl.plan.CustomModificationQueryPlan.executeUpdate(CustomModificationQueryPlan.java:52)
	at com.blazebit.persistence.impl.query.CustomSQLQuery.executeUpdate(CustomSQLQuery.java:62)
	at com.blazebit.persistence.view.impl.update.flush.CollectionAttributeFlusher.deleteElements(CollectionAttributeFlusher.java:457)
	at com.blazebit.persistence.view.impl.update.flush.CollectionAttributeFlusher.replaceCollection(CollectionAttributeFlusher.java:1036)
	at com.blazebit.persistence.view.impl.update.flush.CollectionAttributeFlusher.replaceCollection(CollectionAttributeFlusher.java:64)
	at com.blazebit.persistence.view.impl.update.flush.AbstractPluralAttributeFlusher.invokeFlushOperation(AbstractPluralAttributeFlusher.java:291)
	at com.blazebit.persistence.view.impl.update.flush.CollectionAttributeFlusher.flushQuery(CollectionAttributeFlusher.java:286)
	at com.blazebit.persistence.view.impl.update.flush.CollectionAttributeFlusher.flushQuery(CollectionAttributeFlusher.java:64)
	at com.blazebit.persistence.view.impl.update.flush.CompositeAttributeFlusher.flushQuery(CompositeAttributeFlusher.java:448)
	at com.blazebit.persistence.view.impl.update.EntityViewUpdaterImpl.update(EntityViewUpdaterImpl.java:711)
	at com.blazebit.persistence.view.impl.update.EntityViewUpdaterImpl.executeUpdate(EntityViewUpdaterImpl.java:637)
	at com.blazebit.persistence.view.impl.EntityViewManagerImpl.update(EntityViewManagerImpl.java:1193)
	at com.blazebit.persistence.view.impl.EntityViewManagerImpl.update(EntityViewManagerImpl.java:1153)
	at com.blazebit.persistence.view.impl.EntityViewManagerImpl.save(EntityViewManagerImpl.java:1070)
	at com.blazebit.persistence.spring.data.base.repository.AbstractEntityViewAwareRepository.save(AbstractEntityViewAwareRepository.java:170)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
	at java.base/java.lang.reflect.Method.invoke(Method.java:578)
	at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:288)
	at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:136)
	at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:120)
	at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:516)
	at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:285)
	at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:628)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
	at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:168)
	at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:143)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
	at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:72)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
	at com.blazebit.persistence.spring.data.repository.EntityViewReplacingMethodInterceptor.invoke(EntityViewReplacingMethodInterceptor.java:52)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
	at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:391)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
	at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
	... 219 common frames omitted
Caused by: org.postgresql.util.PSQLException: Der Spaltenindex 3 ist außerhalb des gültigen Bereichs. Anzahl Spalten: 2.
	at org.postgresql.core.v3.SimpleParameterList.bind(SimpleParameterList.java:70)
	at org.postgresql.core.v3.SimpleParameterList.setBinaryParameter(SimpleParameterList.java:137)
	at org.postgresql.jdbc.PgPreparedStatement.bindBytes(PgPreparedStatement.java:1087)
	at org.postgresql.jdbc.PgPreparedStatement.setUuid(PgPreparedStatement.java:1662)
	at org.postgresql.jdbc.PgPreparedStatement.setObject(PgPreparedStatement.java:986)
	at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.setObject(HikariProxyPreparedStatement.java)
	at org.hibernate.type.descriptor.jdbc.UUIDJdbcType$1.doBind(UUIDJdbcType.java:65)
	at org.hibernate.type.descriptor.jdbc.BasicBinder.bind(BasicBinder.java:61)
	at org.hibernate.internal.FilterJdbcParameter.bindParameterValue(FilterJdbcParameter.java:39)
	at org.hibernate.sql.exec.internal.StandardJdbcMutationExecutor.execute(StandardJdbcMutationExecutor.java:73)
	... 256 common frames omitted

Steps to reproduce

Will try to create a sample later somehow.

Environment

Version: 1.6.9 JPA-Provider: Hibernate 6.2.13.Final DBMS: PostgreSQL Application Server: Java/Spring 6

kuhnroyal avatar Nov 02 '23 17:11 kuhnroyal

Hi there, like I posted on the other issue you created, please create a reproducer for this based on the quickstart:

mvn archetype:generate "-DarchetypeGroupId=com.blazebit" "-DarchetypeArtifactId=blaze-persistence-archetype-entity-view-sample-jakarta" "-DarchetypeVersion=1.6.9"

beikov avatar Nov 03 '23 08:11 beikov