Class SpringHibernateJpaPersistenceProvider does not implement the requested interface PersistenceProvider
Asked Answered
S

3

15

I'm stumped - I haven't used Hibernate in several years and then, never with Spring Boot. Spring Boot but never with Hibernate or JPA. So i'm trying to figure out how to get this to work for my job - I'm supposed to demo something Monday and if I can get 'this' to work, I'll copy it over to my work laptop and change the details of course. Btw - here's the message I get - I had to shorten it in the title:

"Class org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider does not implement the requested interface javax.persistence.spi.PersistenceProvider"

I have the "main" class - TestWebApplication:

package net.draconia.testWeb;

import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp2.BasicDataSource;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.context.annotation.Bean;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;

@SpringBootApplication(scanBasePackages = {"com.draconia.testWeb.controller"})
public class TestWebApplication
{
    
    @Bean
    public DataSource getDatasource()
    {
        BasicDataSource objDatasource = new BasicDataSource();
        
        objDatasource.setDriverClassName("com.mysql.jdbc.Driver");
        objDatasource.setUrl("jdbc:mysql://localhost:3306/Test");
        objDatasource.setUsername("root");
        objDatasource.setPassword("R3g1n@ M1lL$ 1$ My Qu3eN!");
        
        return(objDatasource);
    }
    
    @Bean
    public LocalContainerEntityManagerFactoryBean getEntityManagerFactory()
    {
          LocalContainerEntityManagerFactoryBean objEntityManager = new LocalContainerEntityManagerFactoryBean();
          
          objEntityManager.setDataSource(getDatasource());
          objEntityManager.setPackagesToScan(new String[] { "net.draconia.testWeb.beans" });

          JpaVendorAdapter objVendorAdapter = new HibernateJpaVendorAdapter();
          objEntityManager.setJpaVendorAdapter(objVendorAdapter);
          objEntityManager.setJpaProperties(getHibernateProperties());

          return(objEntityManager);
   }
    
    protected Properties getHibernateProperties()
    {
        Properties objHibernateProperties = new Properties();
        
        objHibernateProperties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
        objHibernateProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
        
        return(objHibernateProperties);
    }
    
    @Bean
    public JpaTransactionManager getHibernateTransactionManager()
    {
        JpaTransactionManager objTransactionManager = new JpaTransactionManager();
        
        objTransactionManager.setEntityManagerFactory(getEntityManagerFactory().getObject());
        
        return(objTransactionManager);
    }
    
    public static void main(String[] args)
    {
        SpringApplication.run(TestWebApplication.class, args);
    }
}

, the entity bean:

package net.draconia.testWeb.beans;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity(name = "Books")
public class Book
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer miId;
    
    @Column(columnDefinition = "varchar(200) not null", insertable = true, length = 200, name = "BookName", nullable = false, table = "Books", unique = false, updatable = true)
    private String msBookName;
    
    @Column(columnDefinition = "varchar(100) not null", insertable = true, length = 100, name="Author", nullable = false, table = "Books", unique = false, updatable = true)
    private String msAuthor;
    
    public String getAuthor()
    {
        if(msAuthor == null)
            msAuthor = "";
        
        return(msAuthor);
    }
    
    public String getBookName()
    {
        if(msBookName == null)
            msBookName = "";
        
        return(msBookName);
    }
    
    public int getId()
    {
        if(miId == null)
            miId = 0;
        
        return(miId);
    }
    
    public void setAuthor(final String sAuthor)
    {
        if(sAuthor == null)
            msAuthor = "";
        else
            msAuthor = sAuthor;
    }
    
    public void setBookName(final String sBookName)
    {
        if(sBookName == null)
            msBookName = "";
        else
            msBookName = sBookName;
    }
    
    public void setId(final Integer iId)
    {
        if(iId == null)
            miId = 0;
        else
            miId = iId;
    }
}

, the DAOConcrete class (the interface is just one method which is logical but if you want I'll post that too):

package net.draconia.testWeb.dao;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Repository;

import net.draconia.testWeb.beans.Book;

@Repository("bookDAO")
public class BookDAOImpl implements BookDAO
{
    @Autowired
    private EntityManagerFactory mObjEntityManagerFactory;
    
    public List<Book> getAllBooks()
    {
        EntityManager objEntityManager = getEntityManagerFactory().createEntityManager();
        List<Book> lstBooks = objEntityManager.createQuery("from Books", Book.class).getResultList();
        
        return(lstBooks);
    }
    
    protected EntityManagerFactory getEntityManagerFactory()
    {
        return(mObjEntityManagerFactory);
    }
}

, and the Controller class for the REST endpoints/MVC Controller:

package net.draconia.testWeb.controllers;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

import net.draconia.testWeb.beans.Book;
import net.draconia.testWeb.dao.BookDAO;

@Controller
public class TestController
{
    @Autowired
    private BookDAO mObjDAO;
    
    @GetMapping("/Books")
    public List<Book> getBooks()
    {
        return(getDAO().getAllBooks());
    }
    
    protected BookDAO getDAO()
    {
        return(mObjDAO);
    }
}

The POM file is here just for completeness but I don't think it's necessarily a problem unless I'm missing a dependency:

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    
    <groupId>net.draconia</groupId>
    <artifactId>testWeb</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>testWeb</name>
    <description>Demo project for Spring Boot</description>
    
    <properties>
        <hibernate.version>6.1.0.Final</hibernate.version>
        <java.version>11</java.version>
        <mysql.version>8.0.29</mysql.version>
        <spring.version>5.3.2</spring.version>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.13.3</version>
        </dependency>
        <dependency>
            <groupId>jakarta.persistence</groupId>
            <artifactId>jakarta.persistence-api</artifactId>
            <version>3.0.0</version>
        </dependency>
        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>javax.persistence-api</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-dbcp2</artifactId>
            <version>2.9.0</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate.orm</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

If you'll note, i'm including a dependency for the Jackson library because the list of books should return as a JSON object. I don't think that's a poblem but just saying - and I could probably have remoed that for this but then when it runs, the list of books would be unintelligible to me getting a response when/if it worked. What am I doing wrong???

Sharkey answered 26/6, 2022 at 13:17 Comment(6)
Wrong dependencies. Are you sure you can use ORM 6 with spring 5.3?Awhirl
In HBN6 they have switched to jakarta.persistence-api-3.0.0 and now FQCN of PersistenceProvider in new persistence-api is jakarta.persistence.spi.PersistenceProvider. Basically, modern HBN6 is not compatible with spring.Kevel
Andrey, What does FQCN mean? I theorized since posting that since it keeps assuming jakarta, I am using jakarta's version of the classes now. I already had the jakarta-persistence in the maven file. But I am not sure what to do as for the code to get the results I want.Sharkey
David, I'm not sure but I need to use Spring -Boot and Hibernate with JPA and I don't have the luxury of using Spring-JPA repositories because the powers that be did a crappy job of organizing the DB - there's no foreign keys or anything and few if any primary keys like Id so I'm doing what I can to generate the Hibernate Queries and Entities. I just used Books to test this for myself on my personal computer but when I get it working can copy it over to my work example.Sharkey
FQCN - fully qualified class name. spring data expects javax.persistence.spi.PersistenceProvider, HBN6 uses jakarta.persistence.spi.PersistenceProvider. You need to switch to HBN5.Kevel
I'm now trying to find a tutorial dealing with Hibernate 5 - The last version I used was 4.x and I neither remember nor have any old projects dealing with it at least nothing with JPA - it was all XML files back then. I'll find it now that I know to use an older version and I'll just tell my coworkers it has to be - until at least the new version of Spring or Hibernate comes out.Sharkey
A
14

Change hibernate to version 5.6.9.Final (or any higher 5.6.x):

<hibernate.version>5.6.9.Final</hibernate.version>
Abigael answered 26/6, 2022 at 16:39 Comment(4)
Thank you - I ended up doing that - Evidently that's already inside spring Boot 2.7.1 anyhow so I just removed the version and kept hibernate's dependency. Sorry it took so long to comment - As I found the answer on my own, I didn't bother to returnSharkey
what is the reason to downgrade hibernate version? 6th version contains a bug? p.s. I had the same issue and this approach helped me too.Sebastiansebastiano
Hibernate ORM is not the issue. The changes from Hibernate ORM 5 to 6 are breaking - this is expected with a major version release - and you cannot just replace a library like one would do with 5.6.9 and 5.6.12 (different minors). The other libraries need to release a version that's compatible with ORM 6. Until that happens, you cannot upgrade to ORM 6.Awhirl
Please, check semver.org for more info about semanticversioningAwhirl
S
1

First Check the gradle dependencies tree check which version used for hibernate.entity manager and hibernate-core and update the dependencies In my case I update the dependency and solved he problem. hibernate-core:6.2.13.Final

Songer answered 14/5 at 12:15 Comment(0)
C
0

This did the trick for me in build.gradle:

// With Jakarta
implementation('org.ehcache:ehcache') {
    capabilities {
        requireCapability('org.ehcache:ehcache-jakarta')
    }
}
implementation 'org.hibernate:hibernate-jcache:6.4.4.Final'
Chere answered 2/4 at 7:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.