2017-02-14 64 views
5

Mam prostą aplikację Spring Spring z repozytoriami JPA i Hibernate. pom.xml wygląda następująco:NoSuchMethodError podczas uruchamiania Spring Boot Application z Hibernate JPA

... 
<properties> 
    <springframework.version>1.5.1.RELEASE</springframework.version> 
    <validation-api.version>1.1.0.Final</validation-api.version> 
    <dbunit.version>2.5.3</dbunit.version> 
    <usertype.core.version>6.0.1.GA</usertype.core.version> 
    <validate.version>2.2.0</validate.version> 
    <strman.version>0.2.0</strman.version> 
    <reflections.version>0.9.10</reflections.version> 
    <javax.servlet.jsp-api.version>2.3.1</javax.servlet.jsp-api.version> 
    <rest-assured.version>3.0.1</rest-assured.version> 
</properties> 

<dependencyManagement> 
    <dependencies> 
     <dependency> 
      <!-- Import dependency management from Spring Boot --> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-dependencies</artifactId> 
      <version>${springframework.version}</version> 
      <type>pom</type> 
      <scope>import</scope> 
     </dependency> 
    </dependencies> 
</dependencyManagement> 

<repositories> 
    <repository> 
     <id>spring-milestone</id> 
     <url>https://repo.spring.io/libs-release</url> 
    </repository> 
</repositories> 

<pluginRepositories> 
    <pluginRepository> 
     <id>spring-milestone</id> 
     <url>https://repo.spring.io/libs-release</url> 
    </pluginRepository> 
</pluginRepositories> 

<dependencies> 
    <!-- Spring --> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-web</artifactId> 
     <exclusions> 
      <exclusion> 
       <!-- We use Logback for logging. --> 
       <groupId>org.springframework.boot</groupId> 
       <artifactId>spring-boot-starter-logging</artifactId> 
      </exclusion> 
      <exclusion> 
       <!-- We use Jetty because it is cooler ;) --> 
       <groupId>org.springframework.boot</groupId> 
       <artifactId>spring-boot-starter-tomcat</artifactId> 
      </exclusion> 
     </exclusions> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-data-jpa</artifactId> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-freemarker</artifactId> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-jetty</artifactId> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-websocket</artifactId> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-messaging</artifactId> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-devtools</artifactId> 
     <optional>true</optional> 
    </dependency> 

    <!-- JSON --> 
    <dependency> 
     <groupId>com.fasterxml.jackson.core</groupId> 
     <artifactId>jackson-databind</artifactId> 
    </dependency> 
    <dependency> 
     <groupId>com.fasterxml.jackson.datatype</groupId> 
     <artifactId>jackson-datatype-jdk8</artifactId> 
    </dependency> 
    <dependency> 
     <groupId>com.fasterxml.jackson.datatype</groupId> 
     <artifactId>jackson-datatype-joda</artifactId> 
    </dependency> 

    <!-- Logging --> 
    <dependency> 
     <groupId>org.slf4j</groupId> 
     <artifactId>jcl-over-slf4j</artifactId> 
    </dependency> 
    <dependency> 
     <groupId>ch.qos.logback</groupId> 
     <artifactId>logback-classic</artifactId> 
    </dependency> 

    <!-- Hibernate --> 
    <dependency> 
     <groupId>org.hibernate</groupId> 
     <artifactId>hibernate-core</artifactId> 
    </dependency> 

    <!-- jsr303 validation --> 
    <dependency> 
     <groupId>javax.validation</groupId> 
     <artifactId>validation-api</artifactId> 
     <version>${validation-api.version}</version> 
    </dependency> 
    <dependency> 
     <groupId>org.hibernate</groupId> 
     <artifactId>hibernate-validator</artifactId> 
    </dependency> 

    <!-- Joda-Time --> 
    <dependency> 
     <groupId>joda-time</groupId> 
     <artifactId>joda-time</artifactId> 
    </dependency> 

    <!-- To map JodaTime with database type --> 
    <dependency> 
     <groupId>org.jadira.usertype</groupId> 
     <artifactId>usertype.core</artifactId> 
     <version>${usertype.core.version}</version> 
    </dependency> 

    <!-- MySQL --> 
    <dependency> 
     <groupId>mysql</groupId> 
     <artifactId>mysql-connector-java</artifactId> 
    </dependency> 

    <dependency> 
     <groupId>de.weltraumschaf.commons</groupId> 
     <artifactId>validate</artifactId> 
     <version>${validate.version}</version> 
    </dependency> 

    <!-- String utility --> 
    <dependency> 
     <groupId>com.shekhargulati</groupId> 
     <artifactId>strman</artifactId> 
     <version>${strman.version}</version> 
    </dependency> 

    <dependency> 
     <groupId>org.reflections</groupId> 
     <artifactId>reflections</artifactId> 
     <version>${reflections.version}</version> 
    </dependency> 

    <!-- Provided from container --> 
    <dependency> 
     <groupId>javax.servlet</groupId> 
     <artifactId>javax.servlet-api</artifactId> 
     <scope>provided</scope> 
    </dependency> 
    <dependency> 
     <groupId>javax.servlet.jsp</groupId> 
     <artifactId>javax.servlet.jsp-api</artifactId> 
     <version>${javax.servlet.jsp-api.version}</version> 
     <scope>provided</scope> 
    </dependency> 
    <dependency> 
     <groupId>javax.servlet</groupId> 
     <artifactId>jstl</artifactId> 
     <scope>provided</scope> 
    </dependency> 
</dependnecies> 
... 

konfiguracja Baza jest dość prosty plik właściwości:

spring.datasource.driver-class-name = com.mysql.jdbc.Driver 
spring.datasource.url    = jdbc:mysql://localhost:3306/snafu?autoReconnect=true&useSSL=false&useUnicode=true&characterEncoding=utf8 
spring.datasource.username   = snafu 
spring.datasource.password   = *** 

spring.jpa.show-sql    = false 
spring.jpa.hibernate.format_sql = true 
spring.jpa.hibernate.ddl-auto = update 
spring.jpa.database-platform = org.hibernate.dialect.MySQLInnoDBDialect 

A DB configclass:

package org.snafu; 

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.jdbc.datasource.DriverManagerDataSource; 
import org.springframework.orm.jpa.JpaVendorAdapter; 
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; 
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; 

import javax.sql.DataSource; 
import java.util.Properties; 

@Configuration 
@EnableJpaRepositories(basePackages = { "org.snafu.repo" }) 
public class DatabaseConfiguration { 
    @Value("${spring.datasource.driverClassName}") 
    private String driver = ""; 

    @Value("${spring.datasource.url}") 
    private String url = ""; 

    @Value("${spring.datasource.username}") 
    private String user = ""; 

    @Value("${spring.datasource.password}") 
    private String password = ""; 

    @Value("${spring.jpa.show-sql}") 
    private String showSql = ""; 

    @Value("${spring.jpa.hibernate.format_sql}") 
    private String formatSql = ""; 

    @Value(value = "${spring.jpa.hibernate.ddl-auto}") 
    private String ddlAuto; 

    @Value(value = "${spring.jpa.database-platform}") 
    private String dialect; 

    @Bean 
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() { 
     final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); 
     em.setDataSource(dataSource()); 
     em.setPackagesToScan("de.iteratec.str.iteratweet.model"); 

     final JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); 
     em.setJpaVendorAdapter(vendorAdapter); 
     em.setJpaProperties(additionalProperties()); 

     return em; 
    } 

    @Bean 
    public DataSource dataSource() { 
     final DriverManagerDataSource dataSource = new DriverManagerDataSource(); 
     dataSource.setDriverClassName(driver); 
     dataSource.setUrl(url); 
     dataSource.setUsername(user); 
     dataSource.setPassword(password); 
     return dataSource; 
    } 

    private Properties additionalProperties() { 
     final Properties properties = new Properties(); 
     properties.setProperty("hibernate.hbm2ddl.auto", ddlAuto); 
     properties.setProperty("hibernate.dialect", dialect); 
     properties.setProperty("hibernate.naming_strategy", "org.hibernate.cfg.EJB3NamingStrategy"); 
     return properties; 
    } 
} 

To działało w porządku dla wydania 1.3.x wiosny. Ale z każdym 1.4.x lub 1.5.x wersji autokonfiguracji Hibernate nie:

java.lang.IllegalStateException: Failed to load ApplicationContext 
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' 
defined in class path resource [org/snafu/DatabaseConfiguration.class]: Invocation of init method failed; 
nested exception is java.lang.NoSuchMethodError: org.hibernate.engine.spi.SessionFactoryImplementor.getProperties()Ljava/util/Map; 
Caused by: java.lang.NoSuchMethodError: org.hibernate.engine.spi.SessionFactoryImplementor.getProperties()Ljava/util/Map; 

Oczywiście nie ma takiej metody. Wersja Hibernate skonfigurowana przez Spring Boot to:

mvn dependency:tree | grep -i hibernate 
[INFO] | +- org.hibernate:hibernate-entitymanager:jar:5.0.11.Final:compile 
[INFO] +- org.hibernate:hibernate-core:jar:5.0.11.Final:compile 
[INFO] | +- org.hibernate.javax.persistence:hibernate-jpa-2.1-api:jar:1.0.0.Final:compile 
[INFO] | \- org.hibernate.common:hibernate-commons-annotations:jar:5.0.1.Final:compile 
[INFO] +- org.hibernate:hibernate-validator:jar:5.3.4.Final:compile 

Znalazłem kilka problemów ze Źródłem, które rozwiązują ten problem. Twierdzą, że jest naprawiony. Czy ta poprawka nie jest dostępna w Spring Boot w wersji ? Czy muszę ręcznie zmieniać wersję Hibernate? Jestem bardzo nowy w Spring Boot, ale pomyślałem, że to jest powód używania Spring Boot, że dostaję predifiend set od dependins, które będą działać do góry. Czego mi brakuje lub robię źle?

Odpowiedz

4

Biorąc pod uwagę, że używasz Spring-Boot 1.5.1.RELEASE i masz zależność spring-boot-starter-data-jpa w pliku pom.xml, Spring-Boot pobierze wszystkie słoiki związane z Hibernacja. Proszę usunąć zależność hibernate-core z pliku pom.xml, ponieważ Spring-Boot pobierze hibernate-core-5.0.11.jar wraz z innymi słojami hibernacji.

Błąd, który otrzymujesz, wynika z Jadira wersji 6.0.1.GA w twoim pom.xml. Ta wersja nie jest zgodna z Hibernate w wersji 5.0. Użyj Jadira wersja 5.0.0.GA w swoim pom.xml jak poniżej.

<dependency> 
     <groupId>org.jadira.usertype</groupId> 
     <artifactId>usertype.core</artifactId> 
     <version>5.0.0.GA</version> 
</dependency>