0

Full MCVE is at the bottom of this post.

I am trying to run a very basic Hibernate example as I work through a tutorial. However, I am receiving the following error: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]:

Exception in thread "main" java.lang.ExceptionInInitializerError
    at hibernateTutorial.util.HibernateUtil.buildSessionFactory(HibernateUtil.java:50)
    at hibernateTutorial.util.HibernateUtil.getSessionFactory(HibernateUtil.java:30)
    at hibernateTutorial.main.HibernateMain.main(HibernateMain.java:21)
Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:275)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214)
    at org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory.injectServices(DefaultIdentifierGeneratorFactory.java:152)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.injectDependencies(AbstractServiceRegistryImpl.java:286)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:243)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214)
    at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.<init>(InFlightMetadataCollectorImpl.java:176)
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:127)
    at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.build(MetadataBuildingProcess.java:86)
    at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:479)
    at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:85)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:709)
    at hibernateTutorial.util.HibernateUtil.buildSessionFactory(HibernateUtil.java:47)
    ... 2 more
Caused by: org.vibur.dbcp.ViburDBCPException: java.lang.NullPointerException
    at org.vibur.dbcp.ViburDBCPDataSource.start(ViburDBCPDataSource.java:233)
    at org.hibernate.vibur.internal.ViburDBCPConnectionProvider.configure(ViburDBCPConnectionProvider.java:57)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:107)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:246)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214)
    at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.buildJdbcConnectionAccess(JdbcEnvironmentInitiator.java:145)
    at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:66)
    at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:101)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263)
    ... 15 more
Caused by: java.lang.NullPointerException
    at java.util.Hashtable.put(Hashtable.java:460)
    at java.util.Properties.setProperty(Properties.java:166)
    at org.vibur.dbcp.pool.Connector$Builder$Driver.<init>(Connector.java:66)
    at org.vibur.dbcp.pool.Connector$Builder$Driver.<init>(Connector.java:56)
    at org.vibur.dbcp.pool.Connector$Builder.buildConnector(Connector.java:48)
    at org.vibur.dbcp.ViburDBCPDataSource.doStart(ViburDBCPDataSource.java:248)
    at org.vibur.dbcp.ViburDBCPDataSource.start(ViburDBCPDataSource.java:226)
    ... 24 more

My database is on a Microsoft SQL Server 2017 instance that uses Windows Authentication. I have added both the MSSQL JDBC (v6.4.0) updated IntelliJ with the -Djava.library.path VM option so that sqljdbc_auth.dll (required for Windows Authentication) is accessible.

From what I can tell in my research into this ambiguous error message, it could have many different causes, but ultimately boils down to just not being able to connect to the database somehow. Most of the other Q&A I've found seems to be specific to other databases or SQL Server that doesn't use Windows Authentication.

I have copied the JDBC URL directly from my datasource config in IntelliJ so I know that it is correct and works properly in the IDE.

What else is required to properly configure Hibernate to connect to SQL Server?


HibernateMain.java:

package hibernateTutorial.main;

import hibernateTutorial.model.Employee;
import hibernateTutorial.util.HibernateUtil;
import org.hibernate.Session;

import java.time.LocalDateTime;

public class HibernateMain {

    public static void main(String[] args) {

        Employee emp = new Employee();
        emp.setName("Nathan");
        emp.setRole("CEO");
        emp.setInsertTime(LocalDateTime.now());

        // **********************************************************************************************
        // Get Session
        // **********************************************************************************************
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();

        // **********************************************************************************************
        // Start transaction
        // **********************************************************************************************
        session.beginTransaction();

        // **********************************************************************************************
        // Save the model object
        // **********************************************************************************************
        session.save(emp);

        // **********************************************************************************************
        // Commit the transaction
        // **********************************************************************************************
        session.getTransaction().commit();
        System.out.println("Employee ID: " + emp.getId());

        // **********************************************************************************************
        // Terminate the session factory or the program won't end
        // **********************************************************************************************
        HibernateUtil.getSessionFactory().close();
    }

}

HibernateUtil.java:

package hibernateTutorial.util;

import hibernateTutorial.model.Employee1;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

import java.util.Properties;

public class HibernateUtil {

    // **********************************************************************************************
    // XML-based configuration
    // **********************************************************************************************
    private static SessionFactory sessionFactory;

    // **********************************************************************************************
    // Annotation-based configuration
    // **********************************************************************************************
    private static SessionFactory sessionAnnotationFactory;

    // **********************************************************************************************
    // Property-based configuration
    // **********************************************************************************************
    private static SessionFactory sessionJavaConfigFactory;

    public static SessionFactory getSessionFactory() {

        if (sessionFactory == null) sessionFactory = buildSessionFactory();
        return sessionFactory;
    }

    private static SessionFactory buildSessionFactory() {

        try {
            // **********************************************************************************************
            // Create the SessionFactory from hibernate.cfg.xml
            // **********************************************************************************************
            Configuration configuration = new Configuration();
            configuration.configure("hibernate.cfg.xml");
            System.out.println("Hibernate configuration loaded");

            ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
            System.out.println("Hibernate serviceRegistry created");

            return configuration.buildSessionFactory(serviceRegistry);
        } catch (Throwable e) {
            System.err.println("Initial SessionFactory creation failed. " + e);
            throw new ExceptionInInitializerError(e);
        }

    }

    public static SessionFactory getSessionAnnotationFactory() {

        if (sessionAnnotationFactory == null) sessionAnnotationFactory = buildSessionAnnotationFactory();
        return sessionAnnotationFactory;
    }

    private static SessionFactory buildSessionAnnotationFactory() {

        try {
            // **********************************************************************************************
            // Create the SessionFactory from hibernate-annotation.cfg.xml
            // **********************************************************************************************
            Configuration configuration = new Configuration();
            configuration.configure("hibernate-annotation.cfg.xml");
            System.out.println("Hibernate Annotation configuration loaded");

            ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
            System.out.println("Hibernate Annotation serviceRegistry created");

            return configuration.buildSessionFactory(serviceRegistry);
        } catch (Throwable e) {
            System.err.println("Initial SessionFactory creationg failed." + e);
            throw new ExceptionInInitializerError(e);
        }
    }

    public static SessionFactory getSessionJavaConfigFactory() {

        if (sessionJavaConfigFactory == null) sessionJavaConfigFactory = buildSessionJavaConfigFactory();
        return sessionJavaConfigFactory;
    }

    private static SessionFactory buildSessionJavaConfigFactory() {

        try {
            Configuration configuration = new Configuration();

            //Create Properties, can be read from property files too
            Properties props = new Properties();
            props.put("hibernate.connection.driver_class", "com.microsoft.sqlserver.jdbc.SQLServerDriver");
            props.put("hibernate.connection.url", "jdbc:sqlserver://FADBOKT2493V\\KRAFTLAKEODB:51678;database=Dev_RepAssistDB;integratedSecurity=true");
            props.put("hibernate.current_session_context_class", "thread");

            configuration.setProperties(props);

            //we can set mapping file or class with annotation
            //addClass(Employee1.class) will look for resource
            // com/journaldev/hibernate/model/Employee1.hbm.xml (not good)
            configuration.addAnnotatedClass(Employee1.class);

            ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
            System.out.println("Hibernate Java Config serviceRegistry created");

            return configuration.buildSessionFactory(serviceRegistry);
        } catch (Throwable ex) {
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }

    }
}

Employee.java:

package hibernateTutorial.model;

import java.time.LocalDateTime;

public class Employee {

    private int id;
    private String name;
    private String role;
    private LocalDateTime insertTime;

    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 String getRole() {

        return role;
    }

    public void setRole(String role) {

        this.role = role;
    }

    public LocalDateTime getInsertTime() {

        return insertTime;
    }

    public void setInsertTime(LocalDateTime insertTime) {

        this.insertTime = insertTime;
    }
}

Employee1.java:

package hibernateTutorial.model;

import javax.persistence.*;
import java.time.LocalDateTime;

@Entity
@Table(name = "tmp_employees",
        uniqueConstraints =
                {@UniqueConstraint(columnNames = {"id"})})
public class Employee1 {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false, unique = true, length = 11)
    private int id;

    @Column(name = "name", length = 20, nullable = true)
    private String name;

    @Column(name = "role", length = 20, nullable = true)
    private String role;

    @Column(name = "insert_time", nullable = true)
    private LocalDateTime insertTime;
}

employee.hbm.xml:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "https://hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="hibernateTutorial.model.Employee" table="tmp_employees">
        <id name="id" type="int">
            <column name="id"/>
            <generator class="increment"/>
        </id>
        <property name="name" type="java.lang.String">
            <column name="name"/>
        </property>
        <property name="role" type="java.lang.String">
            <column name="role"/>
        </property>
        <property name="insertTime" type="java.time.LocalDateTime">
            <column name="insert_time"/>
        </property>
    </class>
</hibernate-mapping>

hibernate.cfg.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "https://hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- Database connection properties - Driver, URL, user, password -->
        <property name="hibernate.connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property>
        <property name="hibernate.connection.url">jdbc:sqlserver://servername:port;
            database=test_db;integratedSecurity=true
        </property>
        <!-- Connection Pool Size -->
        <property name="hibernate.connection.pool_size">5</property>

        <!-- org.hibernate.HibernateException: No CurrentSessionContext configured! -->
        <property name="hibernate.current_session_context_class">thread</property>

        <!-- Outputs the SQL queries, should be disabled in Production -->
        <property name="hibernate.show_sql">true</property>

        <!-- Dialect is required to let Hibernate know the Database Type, MySQL, Oracle etc
            Hibernate 4 automatically figure out Dialect from Database Connection Metadata -->
        <property name="hibernate.dialect">org.hibernate.dialect.SQLServer2012Dialect</property>

        <!-- mapping file, we can use Bean annotations too -->
        <mapping resource="hibernateTutorial/employee.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

hibernate-annotation.cfg.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "https://hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- Database connection properties - Driver, URL, user, password -->
        <property name="hibernate.connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property>
        <property name="hibernate.connection.url">jdbc:sqlserver:servername:port;database=test_db;integratedSecurity=true</property>
        <!-- Connection Pool Size -->
        <property name="hibernate.connection.pool_size">5</property>

        <!-- org.hibernate.HibernateException: No CurrentSessionContext configured! -->
        <property name="hibernate.current_session_context_class">thread</property>

        <!-- Outputs the SQL queries, should be disabled in Production -->
        <property name="hibernate.show_sql">true</property>

        <!-- Dialect is required to let Hibernate know the Database Type, MySQL, Oracle etc
            Hibernate 4 automatically figure out Dialect from Database Connection Metadata -->
        <property name="hibernate.dialect">org.hibernate.dialect.SQLServer2012Dialect</property>

        <!-- mapping with model class containing annotations -->
        <mapping class="hibernateTutorial.model.Employee1"/>
    </session-factory>
</hibernate-configuration>
Zephyr
  • 9,885
  • 4
  • 28
  • 63
  • Is the file `sqljdbc_auth.dll` present in the `System32` directory? See [this](https://stackoverflow.com/q/16497998/10871900). – dan1st Jun 14 '21 at 15:18
  • @dan1st no, because I do not have admin access on my workstation. However, it just needs to be in my class path (it works fine in other Java applications). – Zephyr Jun 14 '21 at 15:35
  • In other java applications - what is the difference? Do the other applications not use jpa but only jdbc? – dan1st Jun 14 '21 at 15:45
  • Also, are you sure that the `sqljdbc_auth.dll` file should be in the classpath and not in the `java.library.path`? – dan1st Jun 14 '21 at 15:48
  • You are correct, I've added it to my Java library oath, not the class path. I use this in other Java applications (straight JDBC) without issue. This is the first time I've tried connecting via JPA/Hibernate. – Zephyr Jun 14 '21 at 16:26

0 Answers0