Computer Geek
Computer Geek

Reputation: 105

Java/Hibernate Error: Connection leak detected. The internal connection pool has reached its maximum size and no connection is currently available

I am new to Java/Hibernate and I have no idea what this error means.

ERROR: Connection leak detected: there are 1 unclosed connections upon shutting down pool jdbc:mysql://localhost:3306/hb_student_records?useSSL=false&serverTimezone=UTC
Exception in thread "main" org.hibernate.HibernateException: The internal connection pool has reached its maximum size and no connection is currently available!

I looked up answers on other forums from Stack Overflow but nothing made sense to me there.

My classes are here as follows:

Create Student Demo

package com.rsharma.hibernate.demo;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

import com.rsharma.hibernate.demo.entity.Student;

public class CreateStudentDemo {

    public static void main(String[] args) {

        // create session factory
        SessionFactory factory = new Configuration()
                                .configure("hibernate.cfg.xml")
                                .addAnnotatedClass(Student.class)
                                .buildSessionFactory();

        // create session
        Session session = factory.getCurrentSession();

        try {           
            // create a student object
            System.out.println("Creating new student object...");
            Student tempStudent = new Student("Rishav", "Sharma", "paul@luv2code.com");

            // start a transaction
            session.beginTransaction();

            // save the student object
            System.out.println("Saving the student...");
            session.save(tempStudent);

            // commit transaction
            session.getTransaction().commit();

            System.out.println("Done!");
        }
        finally {
            factory.close();
        }
    }

}

Student.java

package com.rsharma.hibernate.demo.entity;

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

@Entity 
@Table(name="student")
public class Student {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="id")
    private int id; 

    @Column(name="first_name")
    private String firstName; 

    @Column(name="last_name")
    private String lastName; 

    @Column(name="email")
    private String email; 



    public Student(){ 

    }


    public Student(String firstName, String lastName, String email) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
    }


    public int getId() {
        return id;
    }


    public void setId(int id) {
        this.id = id;
    }


    public String getFirstName() {
        return firstName;
    }


    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }


    public String getLastName() {
        return lastName;
    }


    public void setLastName(String lastName) {
        this.lastName = lastName;
    }


    public String getEmail() {
        return email;
    }


    public void setEmail(String email) {
        this.email = email;
    }


    @Override
    public String toString() {
        return "Student [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", email=" + email + "]";
    }

}

And my config.xml file

hibernate.cfg.xml

<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

    <session-factory>

        <!-- JDBC Database connection settings -->
        <property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost:3306/hb_student_records?useSSL=false&amp;serverTimezone=UTC</property>
        <property name="connection.username">hbstudent</property>
        <property name="connection.password">hbstudent</property>

        <!-- JDBC connection pool settings ... using built-in test pool -->
        <property name="connection.pool_size">1</property>

        <!-- Select our SQL dialect -->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

        <!-- Echo the SQL to stdout -->
        <property name="show_sql">true</property>

        <!-- Set the current session context -->
        <property name="current_session_context_class">thread</property>

    </session-factory>

</hibernate-configuration>

I don't know what's causing my open connection as I have closed my factory in the class and the session is temporary.

Upvotes: 4

Views: 14552

Answers (8)

Piercarlo Slavazza
Piercarlo Slavazza

Reputation: 487

Coming a bit late to the party, but the issue is still here (Hibernate 5.6.3 final).

In my case, none of the above solutions worked.

Of course, the missing part in the OP question was the session.close(): however, I had it in place, and the program kept giving the error message about the connections leak.

After some googling, I found that in the past the defualt Hibernate pool was affected by a bug that produced this problem: the related tickets (several duplicated) in the Hibernate's Jira are closed and resolved, but the problem still occurs.

I solved by using the c3p0 pool instead of the default one: it was enough to add it to the dependencies:

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-c3p0</artifactId>
            <version>5.6.3.Final</version>
        </dependency>

Upvotes: 0

B0773N
B0773N

Reputation: 192

What solved it for me was creating a new EntityManager for every transaction and closing it after each transaction like so.

} finally {
    session.close();
    entityManager.close();
}

Upvotes: 0

Nike
Nike

Reputation: 107

In Student class, on Line no.14, you have declared the Id generation strategy as:

@GeneratedValue(strategy=GenerationType.AUTO)

Change it to

@GeneratedValue(strategy = GenerationType.IDENTITY)

This will remove the error.

Look in Hibernate Docs to find out which one is supported by your database. Below are all 4 Id generation strategies:

  • GenerationType.AUTO: Pick an appropriate strategy for the particular database.
  • GenerationType.IDENTITY: Assign primary key using database identity column.
  • GenerationType.SEQUENCE: Assign primary keys using database sequence.
  • GenerationType.TABLE: Assign primary keys using an underlying database table to ensure uniqueness.

Upvotes: 2

Shaiq_Huseynzade
Shaiq_Huseynzade

Reputation: 21

you should change

@GeneratedValue(strategy = GenerationType.AUTO)

to

@GeneratedValue(strategy = GenerationType.IDENTITY)

then it will work.

Upvotes: 0

SPIDER
SPIDER

Reputation: 1

Look i got your doubt see remove the line @GenerationType(Strategy=GeneratedValue.Identity), because i guess you are using auto increment in your primary key column. @GenerationType(Strategy=GeneratedValue.Identity) should only be used when you wanted to save more than one object in your database.

Upvotes: 0

user3148161
user3148161

Reputation: 37

A quick workaround for this issue is to replace the latest Hibernate packages with old Hibernate 5.2 jar files .

Actually issue is not with connection pool , there is some object type mismatch within the try and catch block , you may remove the try and catch block and see what the real exception is.

Probably Hibernate experts can answer this.

And of course "flushing & closing the session object before closing the factory object" won't help you .

Upvotes: 0

Pragyandipta Patro
Pragyandipta Patro

Reputation: 11

Use below in your entity class @GeneratedValue(strategy = GenerationType.IDENTITY)

Upvotes: 1

Another coder
Another coder

Reputation: 398

I think you should also flush & close the session object before closing the factory object.

Upvotes: 4

Related Questions