Hibernate-OGM JpaRepository: getSessionFactory() с несовместимыми типами возвращаемых данных

#mongodb #hibernate #hibernate-ogm

#mongodb #спящий режим #переход в спящий режим-ogm

Вопрос:

При попытке настроить Hibernate-ogm для MongoDB в проекте с весенней загрузкой приложение не запускается из-за того, что два метода getSessionFactory() имеют одинаковую подпись, но возвращают несовместимые типы:

 interface org.hibernate.ogm.OgmSessionFactory
interface org.hibernate.engine.spi.SessionFactoryImplementor
  

Это мои зависимости:

 <dependencyManagement>
    <dependencies>
        <!--This will make sure that you are using matching versions
        of the Hibernate OGM modules and their dependencies.-->
        <dependency>
            <groupId>org.hibernate.ogm</groupId>
            <artifactId>hibernate-ogm-bom</artifactId>
            <version>5.4.1.Final</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

        <!--Due to the different inception dates of individual Spring Data modules,
        most of them carry different major and minor version numbers.
        The easiest way to find compatible ones is to rely on the Spring Data Release
        Train BOM that we ship with the compatible versions defined.
        -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-releasetrain</artifactId>
            <version>${release-train}</version>
            <scope>import</scope>
            <type>pom</type>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <!--Spring-Boot-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

    <!--Lombok-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.4</version>
        <scope>provided</scope>
    </dependency>

    <!--Mail-->
    <dependency>
        <groupId>com.sun.mail</groupId>
        <artifactId>javax.mail</artifactId>
        <version>1.6.2</version>
    </dependency>

    <!--Hibernate-OGM-->
    <dependency>
        <groupId>org.hibernate.ogm</groupId>
        <artifactId>hibernate-ogm-mongodb</artifactId>
    </dependency>
    <dependency>
        <groupId>org.jboss.narayana.jta</groupId>
        <artifactId>narayana-jta</artifactId>
        <version>5.9.2.Final</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-jpa</artifactId>
        <version>2.1.6.RELEASE</version>
    </dependency>

</dependencies>
  

Единственным объектом, задействованным на данный момент, является:

 import lombok.Getter;
import lombok.Setter;
import org.springframework.stereotype.Indexed;

import javax.persistence.*;
import java.util.List;

@Entity
@Indexed
@Getter
@Setter
public class Email {
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    private Long id;
    @ElementCollection
    private List<String> from;
    @ElementCollection
    private List<String> to;
    private String object;
    private byte[] eml;
    @Column(unique = true)
    private byte[] digest;
}
  

в паре с этим репозиторием:

 import my.project.domain.Email;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface EmailRepository extends JpaRepository<Email, Long> {
}
  

Вся конфигурация сохранения выполняется с помощью следующего класса конфигурации:

 import com.mongodb.MongoClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import java.util.HashMap;
import java.util.Map;

@Configuration
@EnableJpaRepositories(basePackages = "my.project.repository")
@EnableTransactionManagement
public class DatabaseConfiguration extends AbstractMongoConfiguration {

    @Value("${spring.data.mongodb.database}")
    private String databaseName;

    @Value("${spring.data.mongodb.host}")
    private String host;

    @Value("${spring.data.mongodb.port}")
    private String port;

    @Override
    public MongoClient mongoClient() {
        System.out.println("Port: "   port);

        MongoClient client = new MongoClient(host, Integer.parseInt(port));

        return client;
    }

    @Override
    protected String getDatabaseName() {
        return databaseName;
    }

    @Bean(name = "entityManagerFactory")
    public LocalContainerEntityManagerFactoryBean emf() {
        Map<String, Object> properties = new HashMap<>();
        properties.put("javax.persistence.transactionType", "resource_local");
        properties.put("javax.persistence.provider", "org.hibernate.ogm.jpa.HibernateOgmPersistence");

        properties.put("hibernate.ogm.datastore.provider", "mongodb");
        properties.put("hibernate.ogm.datastore.host", "localhost");
        properties.put("hibernate.ogm.datastore.port", "27017");
        properties.put("hibernate.ogm.datastore.database", "myproject");
        properties.put("hibernate.ogm.datastore.create_database", "true");

        LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
        emf.setPersistenceProviderClass(org.hibernate.ogm.jpa.HibernateOgmPersistence.class); //If your using eclipse or change it to whatever you're using
        emf.setPackagesToScan("my.project.domain"); //The packages to search for Entities, line required to avoid looking into the _persistence.xml
        emf.setPersistenceUnitName("primary");
        emf.setJpaPropertyMap(properties);
        //emf.setLoadTimeWeaver(new ReflectiveLoadTimeWeaver()); //required unless you know what your doing
        return emf;
    }

    @Bean(name = "mongoTransactionManager")
    public PlatformTransactionManager transactionManager() throws Throwable {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(emf().getNativeEntityManagerFactory());
        return transactionManager;
    }
}
  

Когда я пытаюсь внедрить вышеупомянутый репозиторий, я получаю ошибку, указанную в названии; это весь его журнал:

 2019-04-03 10:06:29.101  INFO 9439 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'primary'
2019-04-03 10:06:29.249  WARN 9439 --- [           main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'emailController': Unsatisfied dependency expressed through field 'emailRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'emailRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: methods with same signature getSessionFactory() but incompatible return types: [interface org.hibernate.ogm.OgmSessionFactory, interface org.hibernate.engine.spi.SessionFactoryImplementor]
2019-04-03 10:06:29.249  INFO 9439 --- [           main] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'primary'
2019-04-03 10:06:29.250  INFO 9439 --- [           main] o.h.o.d.m.impl.MongoDBDatastoreProvider  : OGM001202: Closing connection to MongoDB
2019-04-03 10:06:29.252  INFO 9439 --- [           main] org.mongodb.driver.connection            : Closed connection [connectionId{localValue:3, serverValue:24}] to localhost:27017 because the pool has been closed.
2019-04-03 10:06:29.257  INFO 9439 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
2019-04-03 10:06:29.263  WARN 9439 --- [           main] o.a.c.loader.WebappClassLoaderBase       : The web application [ROOT] appears to have started a thread named [cluster-ClusterId{value='5ca46983fa224724df0fc9b0', description='null'}-localhost:27017] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 sun.misc.Unsafe.park(Native Method)
 java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
 com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.waitForSignalOrTimeout(DefaultServerMonitor.java:229)
 com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.waitForNext(DefaultServerMonitor.java:210)
 com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:157)
 java.lang.Thread.run(Thread.java:748)
2019-04-03 10:06:29.264  WARN 9439 --- [           main] o.a.c.loader.WebappClassLoaderBase       : The web application [ROOT] appears to have started a thread named [CleanCursors-1-thread-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 sun.misc.Unsafe.park(Native Method)
 java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
 java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
 java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
 java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
 java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
 java.lang.Thread.run(Thread.java:748)
2019-04-03 10:06:29.283  INFO 9439 --- [           main] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2019-04-03 10:06:29.301 ERROR 9439 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'emailController': Unsatisfied dependency expressed through field 'emailRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'emailRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: methods with same signature getSessionFactory() but incompatible return types: [interface org.hibernate.ogm.OgmSessionFactory, interface org.hibernate.engine.spi.SessionFactoryImplementor]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:596) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1395) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:849) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142) ~[spring-boot-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775) [spring-boot-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) [spring-boot-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260) [spring-boot-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248) [spring-boot-2.1.3.RELEASE.jar:2.1.3.RELEASE]
    at my.project.MyProjectApplication.main(MyProjectApplication.java:19) [classes/:na]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'emailRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: methods with same signature getSessionFactory() but incompatible return types: [interface org.hibernate.ogm.OgmSessionFactory, interface org.hibernate.engine.spi.SessionFactoryImplementor]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1762) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:277) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1247) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1167) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    ... 19 common frames omitted
Caused by: java.lang.IllegalArgumentException: methods with same signature getSessionFactory() but incompatible return types: [interface org.hibernate.ogm.OgmSessionFactory, interface org.hibernate.engine.spi.SessionFactoryImplementor]
    at sun.misc.ProxyGenerator.checkReturnTypes(ProxyGenerator.java:712) ~[na:1.8.0_201]
    at sun.misc.ProxyGenerator.generateClassFile(ProxyGenerator.java:461) ~[na:1.8.0_201]
    at sun.misc.ProxyGenerator.generateProxyClass(ProxyGenerator.java:339) ~[na:1.8.0_201]
    at java.lang.reflect.Proxy$ProxyClassFactory.apply(Proxy.java:639) ~[na:1.8.0_201]
    at java.lang.reflect.Proxy$ProxyClassFactory.apply(Proxy.java:557) ~[na:1.8.0_201]
    at java.lang.reflect.WeakCache$Factory.get(WeakCache.java:230) ~[na:1.8.0_201]
    at java.lang.reflect.WeakCache.get(WeakCache.java:127) ~[na:1.8.0_201]
    at java.lang.reflect.Proxy.getProxyClass0(Proxy.java:419) ~[na:1.8.0_201]
    at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:719) ~[na:1.8.0_201]
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator.createProxy(ExtendedEntityManagerCreator.java:233) ~[spring-orm-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator.createProxy(ExtendedEntityManagerCreator.java:200) ~[spring-orm-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator.createApplicationManagedEntityManager(ExtendedEntityManagerCreator.java:104) ~[spring-orm-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.invokeProxyMethod(AbstractEntityManagerFactoryBean.java:500) ~[spring-orm-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean$ManagedEntityManagerFactoryInvocationHandler.invoke(AbstractEntityManagerFactoryBean.java:679) ~[spring-orm-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at com.sun.proxy.$Proxy102.createEntityManager(Unknown Source) ~[na:na]
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:302) ~[spring-orm-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at com.sun.proxy.$Proxy105.getDelegate(Unknown Source) ~[na:na]
    at org.springframework.data.jpa.provider.PersistenceProvider.fromEntityManager(PersistenceProvider.java:250) ~[spring-data-jpa-2.1.6.RELEASE.jar:2.1.6.RELEASE]
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.<init>(JpaRepositoryFactory.java:84) ~[spring-data-jpa-2.1.6.RELEASE.jar:2.1.6.RELEASE]
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.createRepositoryFactory(JpaRepositoryFactoryBean.java:106) ~[spring-data-jpa-2.1.6.RELEASE.jar:2.1.6.RELEASE]
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.doCreateRepositoryFactory(JpaRepositoryFactoryBean.java:98) ~[spring-data-jpa-2.1.6.RELEASE.jar:2.1.6.RELEASE]
    at org.springframework.data.repository.core.support.TransactionalRepositoryFactoryBeanSupport.createRepositoryFactory(TransactionalRepositoryFactoryBeanSupport.java:80) ~[spring-data-commons-2.1.6.RELEASE.jar:2.1.6.RELEASE]
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:270) ~[spring-data-commons-2.1.6.RELEASE.jar:2.1.6.RELEASE]
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:121) ~[spring-data-jpa-2.1.6.RELEASE.jar:2.1.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1821) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1758) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    ... 29 common frames omitted
  

Как следует из ошибки, может быть какой-то конфликт зависимостей, но я не смог найти неправильный. Любая мысль об этом?

ОБНОВЛЕНИЕ, добавляющее другую информацию к проблеме; возможно, правильный тип действительно должен быть:

 Interface org.hibernate.ogm.engine.spi.OgmSessionFactoryImplementor
  

Ответ №1:

Я думаю, что Spring Boot и Hibernate OGM включают в ваш проект две разные версии Hibernate ORM, и это вызывает конфликты. Вам нужно проверить, что они оба работают с одной и той же версией, это означает, вероятно, понижение одной из двух.

Кстати, OGM создает свой собственный MongoClient, если у вас возникнут какие-либо проблемы во время подключения, вам может потребоваться обновить конфигурацию или переопределить метод MongoDBDatastoreProvider#createMongoClient на пользовательском диалекте. Затем вы можете использовать пользовательский диалект вместо стандартного со свойством: hibernate.ogm.datastore.provider .