Giter VIP home page Giter VIP logo

hibernate-types-projection-example's Introduction

hibernate-types-projection-example

Repository for providing a problem based on the following article:
https://vladmihalcea.com/dto-projection-jpa-query/ (Bootstrapping JPA declaratively section)

Article says that for Spring boot users who bootstraps JPA declaratively if they would like to use the DTO projections with only the class name in their JPQL queries, their job is that only to do one of the following stuff:

Copied from the article:
"Since Hibernate ORM 5.4.9, you can pass the hibernate.integrator_provider declaratively, either via the JPA persistence.xml configuration file:

<property
    name="hibernate.integrator_provider"
    value="com.vladmihalcea.hibernate.integrator.ClassImportIntegrator">
</property>

or, using the application.properties Spring Boot configuration file:

hibernate.integrator_provider=com.vladmihalcea.hibernate.integrator.ClassImportIntegrator

"

In my case I use application.yml but that does not change a lot on the scenario, and with the version I'm using of the hibernate-types the class moved to another package to the fully qualified name is:

com.vladmihalcea.hibernate.type.util.ClassImportIntegrator

My application.yml content in this scenario:

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/example
    username: example
    password: example
  jpa:
    properties:
      hibernate.integrator_provider: com.vladmihalcea.hibernate.type.util.ClassImportIntegrator
    hibernate:
      ddl-auto: create-drop

When I start the application the following exception comes up:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: The IntegratorProvider class [class com.vladmihalcea.hibernate.type.util.ClassImportIntegrator] could not be instantiated!
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1796) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1108) ~[spring-context-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:868) ~[spring-context-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) ~[spring-boot-2.2.3.RELEASE.jar:2.2.3.RELEASE]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) ~[spring-boot-2.2.3.RELEASE.jar:2.2.3.RELEASE]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.2.3.RELEASE.jar:2.2.3.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.2.3.RELEASE.jar:2.2.3.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.2.3.RELEASE.jar:2.2.3.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) ~[spring-boot-2.2.3.RELEASE.jar:2.2.3.RELEASE]
	at co.rodnan.example.HibernateProjectionExampleApplication.main(HibernateProjectionExampleApplication.java:10) ~[classes/:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.2.3.RELEASE.jar:2.2.3.RELEASE]
Caused by: java.lang.IllegalArgumentException: The IntegratorProvider class [class com.vladmihalcea.hibernate.type.util.ClassImportIntegrator] could not be instantiated!
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.loadSettingInstance(EntityManagerFactoryBuilderImpl.java:1424) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.applyIntegrationProvider(EntityManagerFactoryBuilderImpl.java:441) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.buildBootstrapServiceRegistry(EntityManagerFactoryBuilderImpl.java:371) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.<init>(EntityManagerFactoryBuilderImpl.java:200) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.<init>(EntityManagerFactoryBuilderImpl.java:168) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
	at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:52) ~[spring-orm-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:391) ~[spring-orm-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:378) ~[spring-orm-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1855) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1792) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	... 21 common frames omitted
Caused by: java.lang.InstantiationException: com.vladmihalcea.hibernate.type.util.ClassImportIntegrator
	at java.base/java.lang.Class.newInstance(Class.java:571) ~[na:na]
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.loadSettingInstance(EntityManagerFactoryBuilderImpl.java:1420) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
	... 32 common frames omitted
Caused by: java.lang.NoSuchMethodException: com.vladmihalcea.hibernate.type.util.ClassImportIntegrator.<init>()
	at java.base/java.lang.Class.getConstructor0(Class.java:3350) ~[na:na]
	at java.base/java.lang.Class.newInstance(Class.java:556) ~[na:na]
	... 33 common frames omitted

It says that there is no empty constructor for the ClassImportIntegrator class, there is only one which accepts a list of classes.

One workaround could be your own implementation of the Integrator interface:

public class ClassImportIntegrator implements Integrator {

    private final List<? extends Class> classImportList;

    public ClassImportIntegrator() {
        this.classImportList = List.of(PostDTO.class);
    }

    @Override
    public void integrate(
            Metadata metadata,
            SessionFactoryImplementor sessionFactory,
            SessionFactoryServiceRegistry serviceRegistry) {
        for (Class classImport : classImportList) {
            metadata.getImports().put(
                    classImport.getSimpleName(),
                    classImport.getName()
            );
        }
    }

    @Override
    public void disintegrate(
            SessionFactoryImplementor sessionFactory,
            SessionFactoryServiceRegistry serviceRegistry) {
    }
}

It provides an empty constructor which will initiate the list with fix classes (this could be reworked to do it by reflection but the bootstrap process would be a bit slower) Then we set the hibernate.integrator_provider: property to the following: co.rodnan.example.ClassImportIntegrator
We think that we are ready to go but not unfortunately...

We are getting the following exception:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is java.lang.ClassCastException: class co.rodnan.example.ClassImportIntegrator cannot be cast to class org.hibernate.jpa.boot.spi.IntegratorProvider (co.rodnan.example.ClassImportIntegrator and org.hibernate.jpa.boot.spi.IntegratorProvider are in unnamed module of loader 'app')
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1796) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1108) ~[spring-context-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:868) ~[spring-context-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) ~[spring-boot-2.2.3.RELEASE.jar:2.2.3.RELEASE]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) ~[spring-boot-2.2.3.RELEASE.jar:2.2.3.RELEASE]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.2.3.RELEASE.jar:2.2.3.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.2.3.RELEASE.jar:2.2.3.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.2.3.RELEASE.jar:2.2.3.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) ~[spring-boot-2.2.3.RELEASE.jar:2.2.3.RELEASE]
	at co.rodnan.example.HibernateProjectionExampleApplication.main(HibernateProjectionExampleApplication.java:10) ~[classes/:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.2.3.RELEASE.jar:2.2.3.RELEASE]
Caused by: java.lang.ClassCastException: class co.rodnan.example.ClassImportIntegrator cannot be cast to class org.hibernate.jpa.boot.spi.IntegratorProvider (co.rodnan.example.ClassImportIntegrator and org.hibernate.jpa.boot.spi.IntegratorProvider are in unnamed module of loader 'app')
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.applyIntegrationProvider(EntityManagerFactoryBuilderImpl.java:441) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.buildBootstrapServiceRegistry(EntityManagerFactoryBuilderImpl.java:371) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.<init>(EntityManagerFactoryBuilderImpl.java:200) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.<init>(EntityManagerFactoryBuilderImpl.java:168) ~[hibernate-core-5.4.10.Final.jar:5.4.10.Final]
	at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:52) ~[spring-orm-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:391) ~[spring-orm-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:378) ~[spring-orm-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1855) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1792) ~[spring-beans-5.2.3.RELEASE.jar:5.2.3.RELEASE]
	... 21 common frames omitted

A ClassCastException, interesting, now after knowing this we just could make an implementation of the IntegratorProvider interface like this:

public class ClassImportIntegratorProvider implements IntegratorProvider {
    
    @Override
    public List<Integrator> getIntegrators() {
        return List.of(new ClassImportIntegrator());
    }
}

And then in the application.yml we just have to change the hibernate.integrator_provider property to the following: co.rodnan.example.ClassImportIntegratorProvider and then everything would work flawlessly.

Another IntegratorProvider could be implemented to get the required DTO classes dynamically or by just putting them here.

hibernate-types-projection-example's People

Contributors

nandorholozsnyak avatar

Stargazers

 avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.