Can't get JPA2 running with Hibernate and Maven

16,646

Solution 1

Hibernate EntityManager 3.4.0.GA is not a JPA 2.0 implementation so it won't support the standardized javax.persistence.* properties in the persistence.xml (hence the exception about no JDBC connection being supplied). For JPA 2.0, you need Hibernate EM 3.5.1-Final. Below a simple POM with the right dependency:

<project>
  ...
  <repositories>
    <repository>
      <id>jboss</id>
      <name>JBoss repository</name>
      <url>http://repository.jboss.org/maven2</url>
    </repository>
  </repositories>

  <dependencies>
    <!-- JPA API and Hibernate -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
      <version>3.5.1-Final</version>
    </dependency>

    <!-- Logging -->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-simple</artifactId>
      <version>1.5.8</version>
    </dependency>

    ...
  </dependencies>
  ...
</project>

And that's all you need, other dependencies will be pulled transitively. Just replace the slf4j binding I'm using with your favorite one.

If you want to use Bean Validation (JSR-303) API and the RI, add (adapt the scope to suit your needs):

<!-- Bean Validation API and RI -->
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>1.0.0.GA</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>4.0.2.GA</version>
    <scope>runtime</scope>
</dependency>

I didn't test your code but this will at least fix your POM.

PS: You don't need to specify the persistence provider in your persistence.xml if there is only one on the classpath, you don't need to specify the dialect. But this shouldn't hurt.

PPS: Note that javax.persistence:persistence-api:jar:1.0 is an API, not an implementation, it won't do anything by itself (I mean, it's not a replacement for Hibernate, EclipseLink, etc).

Solution 2

If you are not using Maven dependency and using only eclipse classpath settings, you just need to put the above jar files in classpath from hibernate 3.5 and above

1) hibernate core Jar

2) hibernate annotations jar

3) jboss logging jar

4) hibernate entity manager jar

JPA API 2. jar (its included in hibernate distribution).

I had similar issues and I used this approach and it worked. Getting all the depedent jar from the same version of the distribution is the best idea. If you find any error you can find it from the logs and go on putting the jar in the classpath

Share:
16,646
Ta Sas
Author by

Ta Sas

Updated on June 25, 2022

Comments

  • Ta Sas
    Ta Sas almost 2 years

    Have been trying the whole day long and googled the **** out of the web ... in vain. You are my last hope:

    Here's my code:

    The Entity:

    package sas.test.model;
    
    import javax.persistence.Entity;
    import javax.persistence.Id;
    
    @Entity
    public class Employee {
        @Id private int id;
        private String name;
        private long salary;
        public Employee() {}
        public Employee(int id) { this.id = id; }
        public int getId() { return id; }
        public void setId(int id) { this.id = id; }
        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
        public long getSalary() { return salary; }
        public void setSalary (long salary) { this.salary = salary; }
    }
    

    The service class:

    package sas.test.dao;
    
    import sas.test.model.Employee;
    
    import javax.persistence.*;
    import java.util.List;
    
    public class EmployeeService {
    
        protected EntityManager em;
    
        public EmployeeService(EntityManager em) {
            this.em = em;
        }
        public Employee createEmployee(int id, String name, long salary) {
            Employee emp = new Employee(id);
    
          emp.setName(name);
      emp.setSalary(salary);
      em.persist(emp);
      return emp;
    }
      public void removeEmployee(int id) {
          Employee emp = findEmployee(id);
          if (emp != null) {
              em.remove(emp);
          }
      }
      public Employee raiseEmployeeSalary(int id, long raise) {
          Employee emp = em.find(Employee.class, id);
          if (emp != null) {
              emp.setSalary(emp.getSalary() + raise);
          }
          return emp;
      }
      public Employee findEmployee(int id) {
          return em.find(Employee.class, id);
      }
    
    }
    

    And the main class:

    package sas.test.main;
    
    import javax.persistence.*;
    import java.util.List;
    import sas.test.model.Employee;
    import sas.test.dao.EmployeeService;
    
    
    public class ExecuteMe {
        public static void main(String[] args) {
            EntityManagerFactory emf =
                    Persistence.createEntityManagerFactory("EmployeeService");
            EntityManager em = emf.createEntityManager();
            EmployeeService service = new EmployeeService(em);
    
              // create and persist an employee
              em.getTransaction().begin();
              Employee emp = service.createEmployee(158, "John Doe", 45000);
              em.getTransaction().commit();
              System.out.println("Persisted " + emp);
              // find a specific employee
              emp = service.findEmployee(158);
              System.out.println("Found " + emp);
              // find all employees
         //     List<Employee> emps = service.findAllEmployees();
             // for (Employee e : emps)
             //      System.out.println("Found employee: " + e);
              // update the employee
              em.getTransaction().begin();
              emp = service.raiseEmployeeSalary(158, 1000);
              em.getTransaction().commit();
              System.out.println("Updated " + emp);
              // remove an employee
              em.getTransaction().begin();
              service.removeEmployee(158);
              em.getTransaction().commit();
              System.out.println("Removed Employee 158");
              // close the EM and EMF when done
              em.close();
              emf.close();
        }
    }
    

    Finally my confs.

    pom.xml:

    <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/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>Test_JPA_CRUD</groupId>
        <artifactId>Test_JPA_CRUD</artifactId>
        <packaging>jar</packaging>
        <version>1.0</version>
        <name>Test_JPA_CRUD</name>
        <url>http://maven.apache.org</url>
        <repositories>
    
    
            <repository>
                <id>maven2-repository.dev.java.net</id>
                <name>Java.net Repository for Maven</name>
                <url>http://download.java.net/maven/2/
                </url>
                <layout>default</layout>
            </repository>
    
    
            <repository>
                <id>maven.org</id>
                <name>maven.org Repository</name>
                <url>http://repo1.maven.org/maven2</url>
                <releases>
                    <enabled>true</enabled>
                </releases>
                <snapshots>
                    <enabled>true</enabled>
                </snapshots>
            </repository>
        </repositories>
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.8.1</version>
                <scope>test</scope>
            </dependency>
    
            <!--
    
                    <dependency>
                        <groupId>javax</groupId>
                        <artifactId>javaee-api</artifactId>
                        <version>6.0</version>
                    </dependency>
            -->
            <!--
            <dependency>
                <groupId>javax.persistence</groupId>
                <artifactId>persistence-api</artifactId>
                <version>1.0</version>
            </dependency>
                                          -->
            <!-- JPA2 provider -->
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-entitymanager</artifactId>
                <version>3.4.0.GA</version>
            </dependency>
    
            <!-- JDBC driver -->
            <dependency>
                <groupId>org.apache.derby</groupId>
                <artifactId>derby</artifactId>
                <version>10.5.3.0_1</version>
            </dependency>
    
    
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-core</artifactId>
                <version>3.3.2.GA</version>
            </dependency>
            <dependency>
              <groupId>org.hibernate</groupId>
              <artifactId>ejb3-persistence</artifactId>
              <version>3.3.2.Beta1</version>
            </dependency>
    
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-annotations</artifactId>
                <version>3.4.0.GA</version>
            </dependency>
    
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-log4j12</artifactId>
                <version>1.5.2</version>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.14</version>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <!-- compile with mvn assembly:assembly -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>2.2</version>
                </plugin>
                <!-- compile with mvn assembly:assembly -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-assembly-plugin</artifactId>
                    <version>2.2-beta-2</version>
                    <configuration>
                        <descriptorRefs>
                            <descriptorRef>jar-with-dependencies</descriptorRef>
                        </descriptorRefs>
                        <archive>
                            <manifest>
                                <mainClass>sas.test.main.ExecuteMe</mainClass>
                            </manifest>
                        </archive>
                    </configuration>
                    <executions>
                        <execution>
                            <phase>package</phase>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <!-- Force UTF-8 & Java-Version 1.6 -->
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <configuration>
                        <source>1.6</source>
                        <target>1.6</target>
                        <!--<encoding>utf-8</encoding>-->
                    </configuration>
                </plugin>
            </plugins>
        </build>
    
    </project>
    

    and the persistence.xml, which, I promise, is in the classpath of the target:

    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="1.0"
                 xmlns="http://java.sun.com/xml/ns/persistence"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd
    http://java.sun.com/xml/ns/persistence ">
        <persistence-unit name="EmployeeService" transaction-type="RESOURCE_LOCAL">
            <provider>org.hibernate.ejb.HibernatePersistence</provider>
            <class>sas.test.model.Employee</class>
            <properties>
    
                <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver"/>
                <property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect"/>
                <property name="hibernate.show_sql" value="true"/>
                <property name="javax.persistence.jdbc.url" value="jdbc:derby:webdb;create=true"/>
    
    
            </properties>
        </persistence-unit>
    </persistence>
    

    As you may have noticed from some commented code, I tried both, the Hibernate and the J2EE 6 implementation of JPA2.0, however, both failed. The above-mentioned code ends up with following error:

    log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version).
    log4j:WARN Please initialize the log4j system properly.
    Exception in thread "main" java.lang.UnsupportedOperationException: The user must supply a JDBC connection
     at org.hibernate.connection.UserSuppliedConnectionProvider.getConnection(UserSuppliedConnectionProvider.java:54)
     at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446)
     at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:167)
     at org.hibernate.jdbc.JDBCContext.connection(JDBCContext.java:142)
    

    Any idea what's going wrong? Any "Hello World" maven/JPA2 demo that actually runs? I couldn't get any of those provided by google's search running.

    Thanx in advance.

  • Ta Sas
    Ta Sas about 14 years
    Thank you so much! It works! God save stackoverflow and its participators!
  • Kristen
    Kristen over 13 years
    how do you know which hibernate-validator is valid for hibernate 3.5.1-Final?
  • soltysh
    soltysh almost 13 years
    Usually application server, in my case it's at ./jboss-6.0.0/common/lib/hibernate-entitymanager.jar