Reputation: 428
I have a simple Hello-World Spring Boot Application with JPA repositories and Hibernate. The pom.xml
looks like:
...
<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>
...
The database configuration is quite simple properties file:
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
And 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;
}
}
This worked fine with 1.3.x Releases of Spring. But with any 1.4.x or 1.5.x Version the autoconfiguration of Hibernate fails:
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;
Obviously there is no such method. The Hibernate version which is configured by Spring Boot is:
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
I found some Spring issues which addresses this problem. They claim it is fixed. Is this fix not available in Spring Boot? Do I have to change the Hibernate version by hand? I'm very new to Spring Boot, but I thought this is the reason for using Spring Boot that I get a predefined set of dependencies which will work together. What do I miss or do wrong?
Upvotes: 5
Views: 3445
Reputation: 15317
Considering you are using Spring-Boot 1.5.1.RELEASE
and have spring-boot-starter-data-jpa
dependency in pom.xml file, Spring-Boot will fetch all the Hibernate related jars. Please remove hibernate-core
dependency from your pom.xml as Spring-Boot will fetch hibernate-core-5.0.11.jar
along with other hibernate jars.
The error you are getting is because of Jadira
version 6.0.1.GA
in your pom.xml. This version is not compatible with Hibernate version 5.0. Use Jadira
version 5.0.0.GA
in your pom.xml like below.
<dependency>
<groupId>org.jadira.usertype</groupId>
<artifactId>usertype.core</artifactId>
<version>5.0.0.GA</version>
</dependency>
Upvotes: 5