2017-05-31 96 views
0

我有另一個奇怪的Hibernate問題。我搜索了谷歌並搜索了一個答案,但是找不到任何我理解的東西。休眠與MySQL打開一堆連接

當一個人導航到我們的主頁時,它會打開1到59個連接/會話。它永遠不會一致。他們通常不會關閉,但有時會這樣。在這方面也不明顯一致。我嘗試使用getStatistics只返回零。

DAO.java

package com.grandcircus.spring.util; 

import com.grandcircus.spring.controller.HomeController; 
import com.grandcircus.spring.models.FamiliesEntity; 
import com.grandcircus.spring.models.UsersEntity; 
import org.hibernate.Criteria; 
import org.hibernate.Session; 
import org.hibernate.SessionFactory; 
import org.hibernate.Transaction; 
import org.hibernate.cfg.Configuration; 
import org.hibernate.criterion.Restrictions; 
import org.hibernate.stat.Statistics; 
import org.springframework.stereotype.Repository; 
import org.springframework.transaction.annotation.Transactional; 
import java.util.ArrayList; 

/** 
* Class description 
* 
* @author Sarah Guarino 
* @version 1.0 
*/ 

@Repository 
@Transactional 
public class DAO { 
    private static Configuration configurationObject = new Configuration().configure("hibernate.cfg.xml"); 
    private static SessionFactory sessionFactory = configurationObject.buildSessionFactory(); 

    public static FamiliesEntity newFamily(String famName) { 
     Session browsingSession = sessionFactory.openSession(); 
     Transaction databaseTransaction = browsingSession.beginTransaction(); 

     FamiliesEntity newFamily = new FamiliesEntity(); 
     newFamily.setName(famName); 

     browsingSession.save(newFamily); 
     databaseTransaction.commit(); 
     browsingSession.close(); 

     return newFamily; 
    } 

    public static void newUser(String fName, String lName, 
           String email, String password, 
           int usergroup, int familyid) { 
     Session browsingSession = sessionFactory.openSession(); 
     Transaction databaseTransaction = browsingSession.beginTransaction(); 
     UsersEntity user = new UsersEntity(); 

     user.setFname(fName); 
     user.setLname(lName); 
     user.setEmail(email); 
     user.setUsergroup(usergroup); 
     user.setPassword(password); 
     user.setFamilyid(familyid); 

     browsingSession.save(user); 
     databaseTransaction.commit(); 
     browsingSession.close(); 
    } 

    public static void updateUserCoordinates(String checkinLat, 
              String checkinLong, 
              String userId) { 
     Session browsingSession = sessionFactory.openSession(); 
     Transaction myTransaction = browsingSession.beginTransaction(); 

     Criteria criteria = browsingSession.createCriteria(UsersEntity.class); 
     UsersEntity personCheckingIn = (UsersEntity) criteria 
       .add(Restrictions.eq("userid", Integer.parseInt(userId))) 
       .uniqueResult(); 

     personCheckingIn.setLastlat(checkinLat); 
     personCheckingIn.setLastlong(checkinLong); 
     personCheckingIn.setLasttime(HomeController.getCurrentTime()); 

     browsingSession.save(personCheckingIn); 
     myTransaction.commit(); 
     browsingSession.close(); 
    } 

    public static boolean doesUserExist(String email) { 
     // this will pass if the email exists, or fail if the user does not exist. 
     boolean doesThisExist = true; 
     Session browsingSession = sessionFactory.openSession(); 
     Criteria usersCriteria = browsingSession.createCriteria(UsersEntity.class); 

     try { 
      UsersEntity newUser = (UsersEntity) usersCriteria 
        .add(Restrictions.eq("email", email)) 
        .uniqueResult(); 
      if(newUser.getEmail() == null) { 
       doesThisExist = false; 
      } 
     } catch (Exception e) { 
      doesThisExist = false; 
     } finally { 
      browsingSession.close(); 
     } 

     return doesThisExist; 
    } 

    public static boolean doesFamilyExist(int famId) { 
     boolean doesThisExist = true; 
     Session browsingSession = sessionFactory.openSession(); 
     Criteria familyCriteria = browsingSession.createCriteria(FamiliesEntity.class); 

     try { 
      FamiliesEntity family = (FamiliesEntity) familyCriteria 
        .add(Restrictions.eq("familyid", famId)) 
        .uniqueResult(); 
      if(family.getFamilyid() == 0) { 
       doesThisExist = false; 
      } 
     } catch (NullPointerException e) { 
      doesThisExist = false; 
     } finally { 
      browsingSession.close(); 
     } 

     return doesThisExist; 
    } 

    public static UsersEntity getUserByEmail(String email) { 
     Session browsingSession = sessionFactory.openSession(); 
     Criteria userCriteria = browsingSession.createCriteria(UsersEntity.class); 

     UsersEntity user = (UsersEntity) userCriteria 
       .add(Restrictions.eq("email", email)) 
       .uniqueResult(); 

     browsingSession.close(); 

     return user; 
    } 

    public static UsersEntity loadThisAccount(String userId) { 
     Session browsingSession = sessionFactory.openSession(); 
     Criteria userCriteria = browsingSession.createCriteria(UsersEntity.class); 

     UsersEntity user = (UsersEntity) userCriteria 
       .add(Restrictions.eq("userid", 
         Integer.parseInt(userId))) 
       .uniqueResult(); 

     browsingSession.close(); 

     return user; 
    } 

    public static ArrayList<UsersEntity> loadChildAccounts(int familyId) { 
     Session browsingSession = sessionFactory.openSession(); 

     Criteria childCriteria = browsingSession.createCriteria(UsersEntity.class); 

     ArrayList<UsersEntity> children = (ArrayList<UsersEntity>) childCriteria 
       .add(Restrictions.eq("familyid", familyId)) 
       .add(Restrictions.eq("usergroup", 1)) 
       .list(); 

     browsingSession.close(); 

     return children; 
    } 

    public static FamiliesEntity loadFamily(int familyId) { 
     Session browsingSession = sessionFactory.openSession(); 
     Criteria familyCriteria = browsingSession.createCriteria(FamiliesEntity.class); 

     FamiliesEntity family = (FamiliesEntity) familyCriteria 
       .add(Restrictions.eq("familyid", familyId)) 
       .uniqueResult(); 

     browsingSession.close(); 

     return family; 
    } 

    public static UsersEntity loadParentAccount(int familyId) { 
     Session browsingSession = sessionFactory.openSession(); 
     Criteria adminCriteria = browsingSession.createCriteria(UsersEntity.class); 
     UsersEntity parent = (UsersEntity) adminCriteria 
       .add(Restrictions.eq("familyid", familyId)) 
       .add(Restrictions.eq("usergroup", 0)) 
       .uniqueResult(); 

     browsingSession.close(); 

     return parent; 
    } 
} 

的hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?> 
<!DOCTYPE hibernate-configuration PUBLIC 
     "-//Hibernate/Hibernate Configuration DTD//EN" 
     "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> 
<hibernate-configuration> 
    <session-factory> 
     <property name="connection.url">jdbc:mysql://localhost:3306/checkin</property> 
     <property name="connection.driver_class">com.mysql.jdbc.Driver</property> 
     <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> 
     <property name="show_sql">true</property> 

     <property name="hibernate.connection.username">*****</property> 
     <property name="hibernate.connection.password">*****</property> 

     <property name="hibernate.c3p0.min_size">5</property> 
     <property name="hibernate.c3p0.max_size">20</property> 
     <property name="hibernate.c3p0.timeout">300</property> 
     <property name="hibernate.c3p0.max_statements">50</property> 
     <property name="hibernate.c3p0.idle_test_period">3000</property> 

     <mapping class="com.grandcircus.spring.models.FamiliesEntity"/> 
     <mapping class="com.grandcircus.spring.models.LocationsEntity"/> 
     <mapping class="com.grandcircus.spring.models.UsersEntity"/> 

     <mapping resource="FamiliesEntity.hbm.xml"/> 
     <mapping resource="LocationsEntity.hbm.xml"/> 
     <mapping resource="UsersEntity.hbm.xml"/> 
    </session-factory> 
</hibernate-configuration> 
+0

假設您共享數據庫連接圖層類。你使用JPA還是會話工廠來連接數據庫? –

+0

@RajithPemabandu我使用sessionFactory作爲這個類中的一個字段。你的意思是我的hibernate.cfg.xml? –

回答

0

建議使用連接池 您不必自己打開會話

2

你有幾個問題在這裏。主要問題和我認爲是什麼導致你會話泄漏的是,在doesUserExist和doesFamilyExist你得到NullPointerException經常,永遠不會關閉會話。這裏剩下的問題:

1)你的DAO使用事務註釋,但所有的方法都是靜態的。刪除註釋或製作方法實例作用域並將會話工廠注入到DAO。最好的做法是依賴事務註釋,並讓容器如Spring或EJB3來處理事務的開始/提交調用。

2)您沒有正確關閉會話,您需要將它們封裝在try/finally塊中,並在finally塊中關閉會話。最好的做法是依靠Spring或EJB3來處理會話管理。

3)永遠不會捕獲NullPointerException。總是檢查對象是否爲空,並在那裏添加適當的邏輯。

更新:

這裏修改你的一些DAO方法的版本。這將是你最簡單的修復,但我認爲在某些時候與適當的春天來改善你的DAO,Hibernate和JPA集成:

public static FamiliesEntity newFamily(String famName) { 
     Session browsingSession = null; 
     Transaction databaseTransaction = null; 

     try{ 
      browsingSession = sessionFactory.openSession(); 
      databaseTransaction = browsingSession.beginTransaction(); 

      FamiliesEntity newFamily = new FamiliesEntity(); 
      newFamily.setName(famName); 

      browsingSession.save(newFamily); 
      databaseTransaction.commit(); 

      return newFamily; 
     }catch(RuntimeException e){ 
      if (databaseTransaction != null){ 
       try{ databaseTransaction.rollback(); } 
       catch(RuntimeException ex){throw ex;} 
      } 
      throw e; 
     }finally{ 
      if (browsingSession != null){ 
       browsingSession.close(); 
      } 
     }    
    }  

    public static boolean doesUserExist(String email) { 
     Session browsingSession = null; 

     try{ 
      browsingSession = sessionFactory.openSession(); 

      UsersEntity newUser = (UsersEntity) usersCriteria 
      .add(Restrictions.eq("email", email)) 
      .uniqueResult(); 

      if(newUser.getEmail() == null) { 
       return false; 
      }else{ 
       return true; 
      }     
     }finally{ 
      if (browsingSession != null){ 
       browsingSession.close(); 
      } 
     } 
    } 

    public static UsersEntity getUserByEmail(String email) { 
     Session browsingSession = null; 

     try{ 
      browsingSession = sessionFactory.openSession(); 
      Criteria userCriteria = browsingSession.createCriteria(UsersEntity.class); 

      UsersEntity user = (UsersEntity) userCriteria 
        .add(Restrictions.eq("email", email)) 
        .uniqueResult(); 
     }finally{ 
      if (browsingSession != null){ 
       browsingSession.close(); 
      } 
     } 

     return user; 
    } 

這裏是發生了什麼變化:

1)會議被外界定義的try塊並在finally塊中關閉。確保在關閉之前始終檢查會話是否已實際初始化。否則,如果sessionFactory.openSession()拋出異常或返回null,您將在finally塊中獲得NPE。

2)事務,就像session在try塊外面定義的那樣,在try裏面初始化並在try塊內部提交。但是我們仍然需要處理這樣的情況:如果在提交之前的任何代碼拋出異常,我們不會保持事務處於打開狀態,這就是爲什麼我們需要將它重新放回catch塊。由於會話創建拋出異常,事務在catch塊中可以爲空。

+0

我有幾個問題: 1)我需要我的SessionFactory在Hibernate中使用Criteria對象。另外,我的理解是我需要事務來提交到我的數據庫。我如何「讓春天處理」而仍然做這些事情? 2)試圖實現這個創建了我返回的項目的很多範圍問題。用我目前的知識,做出這些改變是不可能的或不切實際的。這是這個問題的嚴重根源嗎? 3)我解決了這個問題。 –

+0

查看更新的部分。 – tsolakp

0

Tsolakp有很好的建議,它解決了我有很多鬆散的連接泄漏。但是,這不是真正的答案。

如果您的項目在AWS上,您還應完全確保包含數據庫用戶名和密碼的WAR文件未被推送到Git或其他地方。這通常會導致您的連接受到非常激進的來源的攻擊。