Java 9: progress on compatibility
by Sanne Grinovero
Hi all,
please try to have a look at this page when you have a moment:
- http://ci.hibernate.org/view/JDK9/
Hibernate Search is working, and it shouldn't be too hard to get the
others "green" as well.
I've disabled some integration tests to get there, notably:
- OSGi tests: Karaf is not ready for it.
- Documentation build: Asciidoc will probably need an update.
- WildFly integration tests: the WildFly team is aware, will need a
minor upgrade.
I don't believe these issues are relevant, so I'm satisfied that all
other tests working fine mean that the project will pretty much work
out of the box for end users - at worst their container won't work,
but that's not our responsibility to test for.
Could you all contribute a bit to get all projects show "green" on this page?
Some "workarounds" you might want to apply:
- the Logger interfaces won't compile because of a known issue, this
can be worked around for now by having the compilation phase also
explicitly depend on this artifact:
https://github.com/hibernate/hibernate-search/blob/master/pom.xml#L878-L883
- you'll have a ClassNotFoundException on JAXB usage unless you set
this JVM flag: https://github.com/hibernate/hibernate-search/blob/master/pom.xml#L1429
(This one is not a bug but will be required to be set by end users as
well - or we provide our own XML parser, that might be more user
friendly).
As far as I know, other issues with the build tools have been solved
already - including Gradle.
Thanks,
Sanne
8 years, 8 months
Cleaning up non final versions from download pages
by Emmanuel Bernard
I've cleaned up the non final versions of OGM 5.0 from the website
download pages.
There is a displayed: false flag on the yml release document.
I could not find any reason why the alpha, beta and cr were shown in the
list.
Emmanuel
8 years, 8 months
Handling connections properly during testing with Java 1.8
by Vlad Mihalcea
Hi,
Now that we moved to Java 1.8, would you like to add a task so that we
manage the Session/Transaction automatically using a test utility like the
ones I added in the documentation tests:
doInHibernate( this::sessionFactory, session -> {
Person person = new Person();
person.id = 1L;
session.persist( person );
person.phones.add( "027-123-4567" );
person.phones.add( "028-234-9876" );
session.flush();
person.getPhones().remove( 0 );
} );
Or for JPA:
doInJPA( this::entityManagerFactory, entityManager -> {
Person person = new Person( 1L );
entityManager.persist( person );
person.addPhone( new Phone( 1L, "landline", "028-234-9876" ) );
person.addPhone( new Phone( 2L, "mobile", "072-122-9876" ) );
entityManager.flush();
person.removePhone( person.getPhones().get( 0 ) );
} );
1. The tests will be less verbose.
2. There are times when a test fails on MySQL and then the suite stops
because the connection is not closed properly and the DROP command hangs.
What do you think?
Vlad
8 years, 8 months
Revert API change in org.hibernate.Query
by Sanne Grinovero
I just noticed that the org.hibernate.Query interface was deprecated
in 5.2, with the suggestion to use org.hibernate.query.Query now.
That's ok, but it seems the "deprecation process" also forced some API
changes already on the deprecated interface which seem might have been
unintentional.
The builder methods on org.hibernate.Query used to allow returning
"this" to chain methods,
although this seems no longer possible as the API now declares the
return type should be the new one, org.hibernate.query.Query.
Could we fix this by relaxing the return to the older deprecated method?
in practice:
org.hibernate.query.Query<R> setFirstResult(int startPosition);
should be:
org.hibernate.Query<R> setFirstResult(int startPosition);
Thanks,
Sanne
8 years, 8 months
5.2 or 6.0
by Steve Ebersole
Currently we are still working on 6.0 "on top" of 5.2, meaning that all of
the changes we are proposing to ORM for 6.0 are kept in a separate
repo/project using ORM 5.2 as a dependency.
As I work on 6.0 I have come across a change that I would like to make that
requires that I change something in ORM proper. The specific change is
that I would like to remove static access
to org.hibernate.type.descriptor.sql.SqlTypeDescriptorRegistry
and org.hibernate.type.descriptor.java.JavaTypeDescriptorRegistry and have
these scoped as part of the SessionFactory instead (technically as part of
the org.hibernate.metamodel.internal.MetamodelImpl associated with a
SessionFactory).
There are 2 ways I can go about this:
1. branch 5.2 and start 6.0 dev on master
2. make this change in master for inclusion in both 5.2 and 6.0
(2) is certainly the more convenient approach. But even beyond convenient,
I have seen some bugs from the fact that these are statically typed -
theoretically they should be scoped to the SF since the SF can mutate them.
However making that change in 5.2 has some risks depending upon whether
apps/integrations use it. Anyone aware of any integration(s) accessing
these 2 registries?
8 years, 8 months
Collection was not processed by flush()
by Petar Tahchiev
Hello,
I'm using hibernate version 5.1.0.Final and spring-data-rest and I have a
StockRepository which is exposed via rest and when I try to create a new
stock entry I get the following exception:
2016-06-05 17:02:43,917 org.hibernate.AssertionFailure
[http-nio-127.0.0.1-8112-exec-2] ERROR: HHH000099: an assertion failure
occured (this may indicate a bug in Hibernate, but is more likely due to
unsafe use of the session): org.hibernate.AssertionFailure: collection [
com.nemesis.platform.module.commerce.core.entity.i18n.CurrencyEntity.name]
was not processed by flush()
2016-06-05 17:02:43,920
org.apache.catalina.core.ContainerBase.[Tomcat].[localhost].[/storefront].[repositoryRestDispatcherServlet]
[http-nio-127.0.0.1-8112-exec-2] ERROR: Servlet.service() for servlet
[repositoryRestDispatcherServlet] in context with path [/storefront] threw
exception [Request processing failed; nested exception is
org.springframework.transaction.TransactionSystemException: Could not
commit JPA transaction; nested exception is
javax.persistence.RollbackException: Error while committing the
transaction] with root cause
org.hibernate.AssertionFailure: collection [
com.nemesis.platform.module.commerce.core.entity.i18n.CurrencyEntity.name]
was not processed by flush()
at
org.hibernate.engine.spi.CollectionEntry.postFlush(CollectionEntry.java:214)
at
org.hibernate.event.internal.AbstractFlushingEventListener.postFlush(AbstractFlushingEventListener.java:369)
at
org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:40)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1295)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:468)
at
org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3135)
at
org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2352)
at
org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:485)
at
org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:147)
at
org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(JdbcResourceLocalTransactionCoordinatorImpl.java:38)
at
org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231)
at
org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65)
at
org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:61)
at
org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517)
at
org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:761)
at
org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
at sun.reflect.GeneratedMethodAccessor191.invoke(Unknown Source)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at
org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at
org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
at com.sun.proxy.$Proxy349.commit(Unknown Source)
at
org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:485)
at
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:291)
at
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at
org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at
org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:131)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at
org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
at com.sun.proxy.$Proxy304.save(Unknown Source)
at
org.springframework.data.repository.support.CrudRepositoryInvoker.invokeSave(CrudRepositoryInvoker.java:100)
at
org.springframework.data.rest.core.support.UnwrappingRepositoryInvokerFactory$UnwrappingRepositoryInvoker.invokeSave(UnwrappingRepositoryInvokerFactory.java:225)
at
org.springframework.data.querydsl.QuerydslRepositoryInvokerAdapter.invokeSave(QuerydslRepositoryInvokerAdapter.java:158)
at
org.springframework.data.rest.webmvc.RepositoryEntityController.createAndReturn(RepositoryEntityController.java:514)
at
org.springframework.data.rest.webmvc.RepositoryEntityController.postCollectionResource(RepositoryEntityController.java:276)
at sun.reflect.GeneratedMethodAccessor325.invoke(Unknown Source)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
at
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
at
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:832)
at
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:743)
at
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:961)
at
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:895)
at
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)
at
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:869)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
at
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at
org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration$ApplicationContextHeaderFilter.doFilterInternal(EndpointWebMvcAutoConfiguration.java:261)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at
org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:92)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at
org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:115)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:316)
at
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)
at
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at
org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:122)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at
org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:169)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at
org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:48)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at
org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:158)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at
com.nemesis.platform.core.filter.RestAuthenticationFilter.doFilterInternal(RestAuthenticationFilter.java:70)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:120)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
at
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
at
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at
org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:87)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at
org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at
com.nemesis.platform.module.cms.storefront.filter.PathLocaleFilter.doFilterInternal(PathLocaleFilter.java:87)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at
org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at
org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:126)
at
org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:65)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at
org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:92)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at
org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:103)
at
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
at
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at
org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:676)
at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
at
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522)
at
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095)
at
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672)
at
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1502)
at
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1458)
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
I'm writing here because the message says this might indicate a bug in
hibernate.
--
Regards, Petar!
Karlovo, Bulgaria.
---
Public PGP Key at:
http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x19658550C3110611
Key Fingerprint: A369 A7EE 61BC 93A3 CDFF 55A5 1965 8550 C311 0611
8 years, 8 months
Follow on locking usability enhancement for Oracle
by Vlad Mihalcea
Hi,
After reviewing the PR for https://hibernate.atlassian.net/browse/HHH-9486,
I realized we could indeed improve the follow on locking for Oracle.
The issue with Oracle is partly explained in the Oracle docs:
https://docs.oracle.com/database/121/SQLRF/statements_10002.htm#sthref7465
The basic idea is that FOR UPDATE does not work with GROUP BY, DISTINCT,
and also nested selects which is what we use for pagination.
For those, the setMaxResults works, but not setFirstResult. Also, ORDER BY
causes some issues too.
This way, we could do something like this:
1. In Dialect, we deprecate useFollowOnLocking and add a new method to take
QueryParameters
@Deprecated
public boolean useFollowOnLocking() {
return useFollowOnLocking( null );
}
public boolean useFollowOnLocking(QueryParameters parameters) {
return false;
}
2. In Oracle82Dialect:
@Override
public boolean useFollowOnLocking(QueryParameters parameters) {
String lowerCaseSQL = parameters.getFilteredSQL().toLowerCase();
return parameters.hasRowSelection() && (
parameters.getRowSelection().getFirstRow() != null ||
lowerCaseSQL.contains( "distinct" ) ||
lowerCaseSQL.contains( "group by" ) ||
lowerCaseSQL.contains( "order by" )
);
}
3. We could also add a way for the user to override this behavior in
Dialect if he knows that the underlying statement works.
Although we include all those safety checks, we might miss some use case,
and this way the user can have a better control on the follow on locking
approach.
For this we could add a setFollowOnLocking on LockOptions.
List<Product> products = session.createQuery(
"select p from Product p order by p.id", Product.class )
.setLockOptions( new LockOptions( LockMode.PESSIMISTIC_WRITE
).setFollowOnLocking( true ) )
.setMaxResults( 10 )
.getResultList();
If the user specified an explicit setFollowOnLocking, then we ignore the
Dialect logic and just go with his option even if that means that he might
get an exception.
What do you think fo this?
Vlad
8 years, 8 months
Re: [hibernate-dev] Relations are not loaded when using Fetch Profiles
by Vladimir Martinek
Steve,
thank you very much. The test is extremely simple and as a programmer I
thought those few lines of code would clear up any confusion.
It's perfectly OK to postpone the discussion and I will be very happy to
continue once the problem is reproduced and understood.
Once again thank you for all your effort.
Vladimir
On 8.6.2016 16:08, Steve Ebersole wrote:
> Will do. Was hoping to discuss. But if I have to dig through your
> test instead I certainly will, as soon as I get time.
>
> On Wed, Jun 8, 2016 at 2:29 AM Vladimir Martinek <vm(a)sykora.cz
> <mailto:vm@sykora.cz>> wrote:
>
> MetamodelGraphWalker line 144. My relation is in
> MetamodelGraphWalker.visitedAssociationKeys, so it gets skipped
> and thus not make it in the final big SQL SELECT.
>
> Why don't you take a look at the test case I provided - just run
> it and see the LazyInitializationException error, it will all be
> instantly clear. I am talking about LAZY relations in combination
> with FetchProfile using FetchMode.JOIN. Please disregard EAGER
> (for now, we may come to that later once we agree on what is the
> problem :)
>
> We prefer to have all relations LAZY on our project (performance
> reasons) and use FetchProfiles. The actual FetchMode (whether it
> is JOIN, SELECT) does not matter to us, all we need is the
> relations to be loaded in single EntityManager.find call.
> Unfortunately the only FetchMode implemented now is JOIN and that
> one has this unpleasant bug in it.
>
> Thank you
>
>
> Vladimir
>
>
> On 06/07/2016 04:01 PM, Steve Ebersole wrote:
>> MetamodelGraphWalker does not consider them cycles. Where do you
>> see MetamodelGraphWalker making that decision?
>> MetamodelGraphWalker simply walks your model mappings. It
>> delegates to pluggable strategies. So I assume you really mean
>> one of the AssociationVisitationStrategy implementations is
>> considering them cycles. And even then I am not so sure that is
>> what happens...
>>
>> So to be clear we are talking about 2 different EAGER fetch
>> strategies here: join and select.
>>
>> For join, we'd build one big SQL SELECT joining the relations
>> together. You can see this by switching your associations from
>> lazy to all being eager and specifying join fetching.
>>
>> For select, we'd build one SQL SELECT for the root entity being
>> loaded (and any join fetched relations). From there, any
>> select-fetched relations would be loaded individually by separate
>> select (that's kind of the definition of N+1).
>>
>>
>>
>> On Tue, Jun 7, 2016 at 8:50 AM Vladimir Martinek <vm(a)sykora.cz
>> <mailto:vm@sykora.cz>> wrote:
>>
>> Hello,
>>
>> actually I would like to learn how the FetchMode.JOIN is
>> supposed to work in case of cycles (not really cycles but
>> MetamodelGraphWalker considers them cycles).
>>
>> Check the test case please - it gets
>> LazyInitializationException on a relation despite that
>> relation being marked as JOIN FETCH in the fetch profile.
>>
>> How is this intended to work? Is it a problem of
>> MetamodelGraphWalker and its cycle detection? Or is it
>> planned limitation of FetchMode.JOIN?
>>
>> I can help to fix this, but in order to do that I need to
>> know how this is expected to work.
>>
>> Please disregard EAGER. I only mentioned FetchType.EAGER
>> because I noticed it can cope with the same cyclic relations
>> - and yes, you are right, those are fetched in subsequent
>> selects. But we can't use EAGER (performance reasons).
>>
>> Thank you
>>
>> Vladimir
>>
>>
>>
>>
>>
>> On 06/07/2016 03:05 PM, Steve Ebersole wrote:
>>> There is a huge difference in join-fetch and what we detail
>>> for "EAGER". Join-fetch is also an eager fetch. There are 2
>>> pieces of information in regards to fetching: when, how?
>>>
>>> EAGER merely describes when: now.
>>>
>>> What you describe as "EAGER" is really a N+1 fetch. So the
>>> relation is fetched immediately, but as "subsequent
>>> select". A join-fetch is still EAGER, but now the relation
>>> is fetch via join in the initial query. Very different
>>> behavior.
>>>
>>> On Tue, Jun 7, 2016 at 4:38 AM Vladimir Martinek
>>> <vm(a)sykora.cz <mailto:vm@sykora.cz>> wrote:
>>>
>>> HHH-10745, runnable test case attached to that issue
>>> (org.hibernate.test.fetchprofiles.cycle.tar.gz).
>>>
>>> Thank you
>>>
>>> Vladimir
>>>
>>>
>>>
>>> On 06/07/2016 06:00 AM, Gail Badner wrote:
>>> > Please create a Jira issue and attach a runnable test
>>> case.
>>> > Thanks,
>>> > Gail
>>> >
>>> > On Thu, Jun 2, 2016 at 5:45 AM, Vladimir Martinek
>>> <vm(a)sykora.cz <mailto:vm@sykora.cz>
>>> > <mailto:vm@sykora.cz <mailto:vm@sykora.cz>>> wrote:
>>> >
>>> > Fetch profiles fail to load certain relations
>>> because of invalid cycle
>>> > detection in MetamodelGraphWalker. Below is an
>>> example.
>>> >
>>> > I have compared the behaviour of Fetch Profiles
>>> and standard EAGER
>>> > relations (EAGER does not suffer from this
>>> problem). The
>>> > MetamodelGraphWalker graph walker produces the
>>> same results, the
>>> > SQL is
>>> > the same (missing relation).
>>> >
>>> > With EAGER the relation is loaded in second pass, via
>>> > SessionImpl.internalLoad(). There it is decided
>>> what LoadType is
>>> > used -
>>> > for eager it uses INTERNAL_LOAD_EAGER, for lazy
>>> INTERNAL_LOAD_LAZY. It
>>> > does not take into account the fetch profiles here!
>>> >
>>> > The last place I can get hold of fetch profiles in in
>>> > AbstractLoadPlanBasedEntityLoader line 82. After
>>> that the fetch
>>> > profile
>>> > information is lost, never making it anywhere near to
>>> > SessionImpl.internalLoad().
>>> >
>>> > I would like to implement this, but to do that, I
>>> need someone to
>>> > point
>>> > me in the right direction. Most of all I need
>>> answers to following
>>> > questions:
>>> >
>>> > 1) Is it right to assume the fetch profiles should
>>> be evaluated in
>>> > SessionImpl.internalLoad() and appropriate
>>> LoadType used when
>>> > detected a
>>> > relation affected by a fetch profile?
>>> > 2) If so, what is the intended way of getting the
>>> fetch profile
>>> > information to SessionImpl.internalLoad()?
>>> >
>>> > Also, a colleague of mine attempted to implement
>>> FetchType.SELECT
>>> > fetch
>>> > strategy and ended up with precisely the same
>>> problem. I believe
>>> > solving
>>> > my issue would pave way for quick FetchType.SELECT
>>> implementation
>>> > (which
>>> > we could also use on our project).
>>> >
>>> >
>>> > Thank you
>>> >
>>> > Vladimir Martinek
>>> >
>>> >
>>> > Example:
>>> >
>>> > Have 5 entities - Start, Via1, Via2, Mid and
>>> Finish with following
>>> > relations (all LAZY):
>>> >
>>> > Start n:1 Via1 n:1 Mid n:1 Finish
>>> > Start n:1 Via2 n:1 Mid n:1 Finish
>>> >
>>> > Now, trying to use Fetch Profiles to load Start
>>> entity and all of its
>>> > relations. I would expect Hibernate to execute
>>> following SQL select:
>>> >
>>> > SELECT * FROM Start s
>>> > LEFT OUTER JOIN Via1 v1 (path Start-Via1)
>>> > LEFT OUTER JOIN Mid
>>> > JOIN Finish
>>> >
>>> > LEFT OUTER JOIN Via2 (path Start-Via2)
>>> > LEFT OUTER JOIN Mid
>>> > JOIN Finish
>>> >
>>> > Unfortunately, ii ompletely omits the second join
>>> from Mid to Finish,
>>> > what I am getting is:
>>> >
>>> > SELECT * FROM Start s
>>> > LEFT OUTER JOIN Via1 v1 (path Start-Via1)
>>> > LEFT OUTER JOIN Mid
>>> > JOIN Finish
>>> >
>>> > LEFT OUTER JOIN Via2 (path Start-Via2)
>>> > LEFT OUTER JOIN Mid
>>> >
>>> > I dug deeper into this and found cycle detection in
>>> > MetamodelGraphWalker, line 144. Basically, when
>>> MetamodelGraphWalker
>>> > detects a relation that has already been visited,
>>> it considers it a
>>> > cycle. But in my case it is not a cycle - I just
>>> came to the same
>>> > relation twice using two different paths.
>>> >
>>> >
>>> > _______________________________________________
>>> > hibernate-dev mailing list
>>> > hibernate-dev(a)lists.jboss.org
>>> <mailto:hibernate-dev@lists.jboss.org>
>>> <mailto:hibernate-dev@lists.jboss.org
>>> <mailto:hibernate-dev@lists.jboss.org>>
>>> > https://lists.jboss.org/mailman/listinfo/hibernate-dev
>>> >
>>> >
>>>
>>>
>>> --
>>>
>>> *Ing. Vladimír Martinek*
>>> Programmer
>>>
>>> T: +420 723 908 968
>>> @: vm(a)sykora.cz <mailto:vm@sykora.cz>
>>>
>>> Sykora Data Center s.r.o.
>>> 28. října 1512/123, 702 00 Ostrava
>>> www.sykora.cz <http://www.sykora.cz>
>>>
>>> _______________________________________________
>>> hibernate-dev mailing list
>>> hibernate-dev(a)lists.jboss.org
>>> <mailto:hibernate-dev@lists.jboss.org>
>>> https://lists.jboss.org/mailman/listinfo/hibernate-dev
>>>
>>
>>
>> --
>>
>> *Ing. Vladimír Martinek*
>> Programmer
>>
>> T: +420 723 908 968
>> @: vm(a)sykora.cz <mailto:vm@sykora.cz>
>>
>> Sykora Data Center s.r.o.
>> 28. října 1512/123, 702 00 Ostrava
>> www.sykora.cz <http://www.sykora.cz>
>>
>
>
> --
>
> *Ing. Vladimír Martinek*
> Programmer
>
> T: +420 723 908 968
> @: vm(a)sykora.cz <mailto:vm@sykora.cz>
>
> Sykora Data Center s.r.o.
> 28. října 1512/123, 702 00 Ostrava
> www.sykora.cz <http://www.sykora.cz>
>
--
*Ing. Vladimír Martinek*
Programmer
T: +420 723 908 968
@: vm(a)sykora.cz
Sykora Data Center s.r.o.
28. října 1512/123, 702 00 Ostrava
www.sykora.cz
8 years, 8 months