我还有另一个怪异的冬眠问题。我已经谷歌搜索并搜索了一个答案,但找不到我了解的任何东西。
当一个人导航到我们的主页时,它将打开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>
您在这里有几个问题。主要的问题和我认为导致会话泄漏的原因是,在Douserexist和Do dioFamilyExist中,您经常获得NullpoInterException,并且永不结束。在这里,其余问题:
1(您的DAO使用交易注释,但所有方法都是静态的。删除注释,或者将方法范围和对DAO的注入会话范围。最好的做法是依靠交易注释,让诸如Spring或EJB3之类的容器处理交易开始/提交呼叫。
2(您无法正确结束会话,您需要将它们包裹在尝试/最终阻止中,然后将会话结束,最终将其关闭。最好的做法再次是依靠春季或EJB3来处理会话管理。
3(永远不要捕获NullPoInterException。始终检查对象是否为null并在此处添加适当的逻辑。
更新:
这是您的某些DAO方法的修改版本。这对您来说是最简单的解决方案,但我建议通过适当的春季,Hibernate和JPA集成在某个时候改善您的DAO:
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 Block之外定义的,并在最终块中关闭。确保在关闭之前始终检查会话是否实际初始化。否则,如果sessionfactory.opensession((投掷异常或返回null,您将在最终块中获得NPE。
2(交易,就像会话是在Try Block之外定义的一样,在Try Block中进行初始化,并且在Try Block内进行了投入。但是,我们仍然需要处理这样的情况:如果提交之前的任何代码抛出异常,我们将不会保持交易的打开状态,这就是为什么我们需要将其倒在渔获块中的原因。由于会话创建异常,因此在捕获块中再次交易。
建议使用连接池您不必自己打开会话
tsolakp有很好的建议,它解决了我所拥有的许多松散连接泄漏。但是,这不是实际答案。
如果您的项目在AWS上,则应完全确保包含数据库用户名和密码的战争档案不会被推到Git或其他地方。这通常会导致您的连接受到非常激进的来源的攻击。