简体   繁体   中英

Cleaning up connection pool during Hibernate takes too long

I'm trying Many-to-one association mapping in Hibernate for the first time. I have 2 POJO classes - Employee and Address - and the association between them is that one Address object can be associated with multiple Employee objects.

My program has never compiled, it just always gets stuck at this point in the stack trace -

Jun 25, 2020 12:41:09 AM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {5.3.1.Final}
Jun 25, 2020 12:41:09 AM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
Jun 25, 2020 12:41:09 AM org.hibernate.spatial.integration.SpatialService <init>
INFO: HHH80000001: hibernate-spatial integration enabled : true
Jun 25, 2020 12:41:09 AM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {5.0.3.Final}
Jun 25, 2020 12:41:10 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using Hibernate built-in connection pool (not for production use!)
Jun 25, 2020 12:41:10 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: using driver [com.mysql.jdbc.Driver] at URL [jdbc:mysql://localhost/hibernatedb2]
Jun 25, 2020 12:41:10 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {user=root}
Jun 25, 2020 12:41:10 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
Jun 25, 2020 12:41:10 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
Jun 25, 2020 12:41:10 AM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
Jun 25, 2020 12:41:10 AM org.hibernate.envers.boot.internal.EnversServiceImpl configure
INFO: Envers integration enabled? : true
Jun 25, 2020 12:41:11 AM org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl getIsolatedConnection
INFO: HHH10001501: Connection obtained from JdbcConnectionAccess [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess@7a18e8d] for (non-JTA) DDL execution was not in auto-commit mode; the Connection 'local transaction' will be committed and the Connection will be set into auto-commit mode.
Jun 25, 2020 12:41:11 AM org.hibernate.hql.internal.QueryTranslatorFactoryInitiator initiateService
INFO: HHH000397: Using ASTQueryTranslatorFactory
Jun 25, 2020 12:41:11 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop
INFO: HHH10001008: Cleaning up connection pool [jdbc:mysql://localhost/hibernatedb2]

Address.java -

package firsthb;

public class Address {
    
    private int id;
    private String street, city, state;
    
    //getters and setters
    public int getId() {
        return id;
    }
    
    public void setId(int id) {
        this.id = id;
    }
    
    public String getStreet() {
        return street;
    }
    
    public void setStreet(String street) {
        this.street = street;
    }
    
    public String getCity() {
        return city;
    }
    
    public void setCity(String city) {
        this.city = city;
    }
    
    public String getState() {
        return state;
    }
    
    public void setState(String state) {
        this.state = state;
    }
}

Employee.java -

package firsthb;

public class Employee {

    private int id;
    private String firstName, lastName;
    private Address address;
    
    //getters and setters
    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 Address getAddress() {
        return address;
    }
    
    public void setAddress(Address address) {
        this.address = address;
    }
}

employee.hbm.xml (Hibernate mapping file) -

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "<a class='vglnk' href='http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd' rel='nofollow'><span>http</span><span>://</span><span>hibernate</span><span>.</span><span>sourceforge</span><span>.</span><span>net</span><span>/</span><span>hibernate</span><span>-</span><span>mapping</span><span>-</span><span>3</span><span>.</span><span>0</span><span>.</span><span>dtd</span></a>">
<hibernate-mapping>

<class name="firsthb.Employee" table="EMP">
    <meta attribute="class-description">
    This class contains employees' details
    </meta>

    <id column="ID" name="id" type="int">
        <generator class="native" />
    </id>

    <property column="FIRST_NAME" name="firstName" type="string"/>
    <property column="LAST_NAME" name="lastName" type="string"/>

    <many-to-one name="address" column="address" class="firsthb.Address" not-null="true"/>
    <!-- Attributes in <many-to-one> tag - 
        1. name: data member in parent class
        2. column: column name in parent table -->

</class>

<class name="firsthb.Address" table="ADDRESS">
    <meta attribute="class-description">
    This class contains the addresses of employees
    </meta>
    
    <id name="id" column="ID" type="int">
        <generator class="native"/>
    </id>
    
    <property name="street" column="street_name" type="string"/>
    <property name="city" column="city_name" type="string"/>
    <property name="state" column="state_name" type="string"/>

</class>

</hibernate-mapping>

hibernate.cfg.xml (Hibernate configuration file) -

<?xml version='1.0' encoding='UTF-8'?>  
<!DOCTYPE hibernate-configuration PUBLIC  
          "-//Hibernate/Hibernate Configuration DTD 5.3//EN"  
          "http://www.hibernate.org/dtd/hibernate-configuration-5.3.dtd">  

   
<hibernate-configuration>  
  
    <session-factory>  
        
        <property name="hbm2ddl.auto">update</property>  
        <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>  
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>  
        <property name="connection.url">jdbc:mysql://localhost/hibernatedb2</property>  
        <property name="connection.username">root</property>    
    <mapping resource="employee.hbm.xml"/>
    </session-factory>  
  
</hibernate-configuration>  

Lastly, the file where I implement the functionality of many-to-one association -

package firsthb;

import java.util.ArrayList;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;  
import org.hibernate.SessionFactory;  
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration; //new - so that line 24 works, and StandardServiceRegistry + metadata initialization can be avoided
/*
import org.hibernate.boot.Metadata;  
import org.hibernate.boot.MetadataSources;  
import org.hibernate.boot.registry.StandardServiceRegistry;  
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
 */

@SuppressWarnings({"deprecation", "unchecked"})
public class FunctionalityImplementer {
    
    private static SessionFactory factory;

    public static void main(String[] args) {
        
        factory = new Configuration().configure().buildSessionFactory();
        
        FunctionalityImplementer fi = new FunctionalityImplementer();
        Address addr1 = fi.addAddress("E-85, DDA Flats", "New Delhi", "Delhi");
        Employee emp1 = fi.addEmployee("Vikramaditya", "Bhatnagar", addr1);
        Employee emp2 = fi.addEmployee("Yashaswani", "Bhatnagar", addr1);
        fi.listEmployees();
        
        //Address addr1 = ME.add
        
        //System.out.println("Successfully saved");
        factory.close();
    }
    
    public Address addAddress(String street, String city, String state) {
        
        //StandardServiceRegistry ssr = new StandardServiceRegistryBuilder().configure("hibernate.cfg.xml").build();
        //Metadata meta = new MetadataSources(ssr).getMetadataBuilder().build();
        //factory = meta.getSessionFactoryBuilder().build();
        
        Session session = factory.openSession();
        Transaction t = session.beginTransaction();
        
        Address a = new Address(); //better programming practice would be to use a parameterized constructor instead of individual setters
        a.setStreet(street);
        a.setCity(city);
        a.setState(state);
        
        t.commit();
        session.close();
        return a;
    }
    
    public Employee addEmployee(String firstName, String lastName, Address address) {
        
        Session session = factory.openSession();
        Transaction t = session.beginTransaction();
        
        Employee e = new Employee(); //better programming practice would be to use a parameterized constructor instead of individual setters
        e.setFirstName(firstName);
        e.setLastName(lastName);
        e.setAddress(address);
        
        t.commit();
        session.close();
        return e;
    }
    
    
    public void listEmployees() {
        
        Session session = factory.openSession();
        Transaction t = session.beginTransaction();
        
        List<Employee> elist = new ArrayList<>();
        Query<Employee> query = session.createQuery("From Employee");
        elist = (ArrayList<Employee>)query.list();
        
        for(Employee loopctr : elist) {
            System.out.println("EMPLOYEE DETAILS -");
            System.out.println(loopctr.getId() + "\t" + loopctr.getFirstName() + "\t" + loopctr.getLastName());
            System.out.println("ADDRESS DETAILS -");
            Address addr = loopctr.getAddress();
            System.out.println(addr.getStreet() + "\t" + addr.getCity() + "\t" + addr.getState());
        }
        
        t.commit();
        session.close();
    }
}

I read somewhere that a program like this can take forever to compile if you're creating multiple SessionFactory objects throughout your program (since SessionFactory objects are large in size). However, that is not the case here either as I have created a single SessionFactory object with the scope of entire FunctionalityImplementer class, and I create multiple Session objects as I go along (which, from what I know, is fine since they are smaller in size).

Please note that at this particular point, the tables get created in MySQL console (tables did not exist in RDBMS when compilation began) -

describe emp;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| ID         | int(11)      | NO   | PRI | NULL    | auto_increment |
| FIRST_NAME | varchar(255) | YES  |     | NULL    |                |
| LAST_NAME  | varchar(255) | YES  |     | NULL    |                |
| address    | int(11)      | NO   | MUL | NULL    |                |
+------------+--------------+------+-----+---------+----------------+
4 rows in set (0.30 sec)

mysql> desc address;
+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| ID          | int(11)      | NO   | PRI | NULL    | auto_increment |
| street_name | varchar(255) | YES  |     | NULL    |                |
| city_name   | varchar(255) | YES  |     | NULL    |                |
| state_name  | varchar(255) | YES  |     | NULL    |                |
+-------------+--------------+------+-----+---------+----------------+
4 rows in set (0.03 sec) 

Found an answer, Pretty straightforward, I just forgot to add session.save(a); and session.save(em); right before the t.commit(); statement in the 2 data adding functions.

Worked like a charm after that!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM