java.lang.NoSuchMethodError: 'java.sql.Connection org.hibernate.engine.spi.SharedSessionContractImplementor.connection()'

Всем привет! Создаю веб-приложение на основе Spring-MVC, Hibernate, MySQL.

Проблема:

В DAO (репозиториях) у были написаны вручную транзакции с помощью Hibernate, но при переходе на @Transactional, начало кидать следующую ошибку: java.lang.NoSuchMethodError: 'java.sql.Connection org.hibernate.engine.spi.SharedSessionContractImplementor.connection()'.

Error Logs:

java.lang.NoSuchMethodError: 'java.sql.Connection org.hibernate.engine.spi.SharedSessionContractImplementor.connection()'
        at org.springframework.orm.hibernate5.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:565)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.startTransaction(AbstractPlatformTransactionManager.java:400)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:595)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:382)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)
        at jdk.proxy5/jdk.proxy5.$Proxy271.create(Unknown Source)
        at com.senla.hotel.controllers.ClientController.create(ClientController.java:44)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1070)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
        at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:764)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
        at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360)
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399)
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1789)
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
        at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
        at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.base/java.lang.Thread.run(Thread.java:833) 

Service Layer:

package com.senla.hotel.services;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.senla.hotel.dto.ServiceDto;
import com.senla.hotel.entities.Service;
import com.senla.hotel.repos.interfaces.IServiceRepository;
import com.senla.hotel.services.interfaces.IServiceService;
import com.senla.hotel.utils.comparators.ServiceComparatorsMap;
import com.senla.hotel.utils.enums.entities.SortMethods;
import com.senla.hotel.utils.mappers.EntityDtoMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.IOException;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;


@org.springframework.stereotype.Service
public class ServiceService implements IServiceService {

    @Autowired
    private IServiceRepository serviceRepository;
    @Autowired
    private EntityDtoMapper mapper;

    @Override
    @Transactional
    public ServiceDto create(ServiceDto serviceDto) {
        return mapper.entity2dto(serviceRepository.create(mapper.dto2entity(serviceDto)));
    }


    @Override
    @Transactional(readOnly = true)
    public List<ServiceDto> getList(SortMethods sortMethod) {
        List<Service> services = serviceRepository.getList();

        if (sortMethod != SortMethods.NULL) {
            Comparator<Service> comparator = ServiceComparatorsMap.getComparatorBySorting(sortMethod);
            services.sort(comparator);
        }

        return services.stream().map(service -> mapper.entity2dto(service)).toList();
    }


    @Override
    @Transactional
    public List<ServiceDto> insert(List<ServiceDto> services) {
        return serviceRepository.insert(services.stream().map(serviceDto -> mapper.dto2entity(serviceDto)).toList()).
                stream().map(service -> mapper.entity2dto(service)).toList();
    }


    @Override
    @Transactional(readOnly = true)
    public ServiceDto findById(int serviceId) {
        return mapper.entity2dto(serviceRepository.findById(serviceId));
    }


    @Override
    @Transactional
    public boolean importEntities(String filePath) {
        ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule());

        try {
            List<Service> services = mapper.readValue(new File(filePath), new TypeReference<List<Service>>() {
            });
            this.serviceRepository.insert(services);
            return true;
        } catch (IOException exc) {
            exc.printStackTrace();
            return false;
        }
    }


    @Override
    @Transactional(readOnly = true)
    public Map<ServiceDto, Float> getServicesCosts(SortMethods sortMethod) {
        Map<ServiceDto, Float> serviceCostMap = new LinkedHashMap<>();
        List<Service> list = serviceRepository.getList();

        if (sortMethod != SortMethods.NULL) {
            Comparator<Service> comparator = ServiceComparatorsMap.getComparatorBySorting(sortMethod);
            list.sort(comparator);
        }

        for (Service service : list) {
            serviceCostMap.put(mapper.entity2dto(service), (float) (service.getCost() / 100.0));
        }

        return serviceCostMap;
    }


    @Override
    @Transactional(readOnly = true)
    public void exportEntities(String filePath) {
        List<Service> servicesList = this.serviceRepository.getList();

        ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule());

        try {
            mapper.writeValue(new File(filePath), servicesList);
        } catch (IOException exc) {
            exc.printStackTrace();
        }
    }
}

DAO (Repository) Layer:

package com.senla.hotel.repos;

import com.senla.hotel.entities.Service;
import com.senla.hotel.repos.interfaces.IServiceRepository;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Root;
import lombok.Setter;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.List;

@Setter
@Repository
public class ServiceRepository implements IServiceRepository {

    @Autowired
    SessionFactory sessionFactory;

    @Override
    public Service create(Service service) {
        getCurrentSession().persist(service);
        return service;
    }


    @Override
    public Service updateById(int serviceId, Service service) {
        service.setId(serviceId);
        return getCurrentSession().merge(service);
    }


    @Override
    public Service findById(Integer serviceId) {
        return getCurrentSession().byId(Service.class).load(serviceId);
    }


    @Override
    public boolean deleteById(int serviceId) {
        Service service = findById(serviceId);
        getCurrentSession().remove(service);
        return true;
    }


    @Override
    public List<Service> insert(List<Service> list) {
        int batch_size = sessionFactory.getSessionFactoryOptions().getJdbcBatchSize();
        Session session = getCurrentSession();
        int i = 0;

        for (Service service : list) {
            if (i % batch_size == 0 && i > 0) {
                session.flush();
                session.clear();
            }
            session.persist(service);
            i++;
        }

        return list;
    }


    @Override
    public List<Service> getList() {
        Session session = getCurrentSession();

        CriteriaBuilder cb = session.getCriteriaBuilder();
        CriteriaQuery<Service> cq = cb.createQuery(Service.class);
        Root<Service> root = cq.from(Service.class);

        cq.select(root);

        Query<Service> query = session.createQuery(cq);

        return query.getResultList();
    }

    private Session getCurrentSession() {
        return sessionFactory.getCurrentSession();
    }
}

CONFIG Layer:

package com.senla.hotel.config;

import com.senla.hotel.entities.Client;
import com.senla.hotel.entities.ReleaseDate;
import com.senla.hotel.entities.Room;
import com.senla.hotel.entities.Service;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.InjectionPoint;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.Scope;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import java.util.Properties;

@Configuration
@EnableTransactionManagement
@ComponentScan("com.senla.hotel")
@PropertySource("classpath:/app.properties")
public class JavaConfig {

    @Bean
    public DriverManagerDataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource(
                "jdbc:mysql://localhost/hoteldb?createDatabaseIfNotExist=true",
                "root",
                "poker88"
        );
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        return dataSource;
    }

    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());

//        hibernate properties
        Properties properties = new Properties();
        properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
        properties.setProperty("hibernate.show_sql", "false");
        properties.setProperty("hibernate.hbm2ddl.auto", "update");
        properties.setProperty("hibernate.jdbc.batch_size", "25");

        sessionFactory.setHibernateProperties(properties);

        sessionFactory.setAnnotatedClasses(Client.class, Room.class, Service.class, ReleaseDate.class);

        return sessionFactory;
    }

    @Bean
    public HibernateTransactionManager txManager() {
        return new HibernateTransactionManager(sessionFactory().getObject());
    }

    @Bean
    @Scope("prototype")
    public Logger logger(final InjectionPoint ip) {
        final Class<?> lClass;
        if (null != ip.getMethodParameter()) {
            lClass = ip.getMethodParameter().getContainingClass();
        } else {
            lClass = ip.getField().getDeclaringClass();
        }
        return LogManager.getLogger(lClass);
    }
}

POM.XML:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.senla</groupId>
    <artifactId>hotel</artifactId>
    <version>1.0</version>
    <packaging>war</packaging>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-checkstyle-plugin</artifactId>
                <version>${checkstyle.version}</version>
                <configuration>
                    <configLocation>${resources.path}/checkstyle.xml</configLocation>
                    <suppressionsLocation>${resources.path}/suppressions.xml</suppressionsLocation>
                    <encoding>UTF-8</encoding>
                    <consoleOutput>true</consoleOutput>
                    <failsOnError>true</failsOnError>
                    <linkXRef>false</linkXRef>
                </configuration>
                <executions>
                    <execution>
                        <id>verify</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>check</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <!-- https://mvnrepository.com/artifact/org.apache.tomcat.maven/tomcat7-maven-plugin -->
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <url>http://localhost:8080/manager/text</url>
                    <server>maven-tomcat-war-deployment-server</server>
                    <path>/hotel</path>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.3.2</version>
            </plugin>
        </plugins>
    </build>

    <properties>
        <com.fasterxml.jackson.core.version>2.13.3</com.fasterxml.jackson.core.version>
        <slf4j.version>1.7.36</slf4j.version>
        <checkstyle.version>3.1.2</checkstyle.version>
        <resources.path>src/main/resources</resources.path>
        <spring.version>5.3.22</spring.version>
    </properties>

    <dependencies>
<!--        jackson-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${com.fasterxml.jackson.core.version}</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>${com.fasterxml.jackson.core.version}</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>${com.fasterxml.jackson.core.version}</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-jsr310</artifactId>
            <version>${com.fasterxml.jackson.core.version}</version>
        </dependency>

<!--        javassist-->
        <dependency>
            <groupId>javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.12.1.GA</version>
        </dependency>

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

<!--        reflections-->
        <dependency>
            <groupId>org.reflections</groupId>
            <artifactId>reflections</artifactId>
            <version>0.10.2</version>
        </dependency>

<!--        log4j2-->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.17.2</version>
        </dependency>

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.17.2</version>
        </dependency>

<!--        slf4j-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>${slf4j.version}</version>
        </dependency>

<!--        checkstyle plugin-->
        <dependency>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-checkstyle-plugin</artifactId>
            <version>${checkstyle.version}</version>
            <type>maven-plugin</type>
        </dependency>


<!--        JDBC Driver MySQL-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.29</version>
        </dependency>

<!--        Javax Persistence-->
        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>javax.persistence-api</artifactId>
            <version>2.2</version>
        </dependency>

<!--        Hibernate-->

        <dependency>
            <groupId>org.hibernate.orm</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>6.1.1.Final</version>
        </dependency>

        <!--        Servlet API-->
<!--        https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api-->
        <dependency>
            <groupId>jakarta.servlet</groupId>
            <artifactId>jakarta.servlet-api</artifactId>
            <version>6.0.0</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
        </dependency>

<!--        Spring-->
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-orm -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>

    </dependencies>
</project>

Дополнительно:

Как я понимаю, проблема в несовпадении зависимостей. У версии Hibernate, что я использую, в классе SharedSessionContractImplementor нет метода connection(), который пытается вызвать Spring в методе doBegin() Transaction Manager'а. Я смотрел зависимости hibernate-core и нашел этот метод connection() в версии 5.6.9 Final, но это уж слишком старая версия, где используются старые методы hibernate. Сомневаюсь, что переходить на нее - хорошая идея.

Я не нашел ни одного топика на эту тему (именно с SharedSessionContractImplementor.connection()), что ставит меня в затруднительное положение.

Помогите пж, я не знаю, что делать.


Ответы (0 шт):