Я использую Hibernate в своем веб-приложении, которое разработано с использованием чистого сервлета и JSP. Когда я выполняю код, я сталкиваюсь с большой проблемой «иногда». Что происходит, я получаю ошибку Too many Connections
из Hibernate.Слишком много соединений Ошибка: Hibernate
Я прошел через множество вопросов, связанных с Stackoverflow, в поисках ответа, и я нашел разные решения. Некоторые предложили использовать стороннюю систему объединения, некоторые предложили быть потокобезопасными, некоторые предложили использовать один SessionFactory
и т. Д., Поэтому я не уверен, какая из них применима к моей.
Ниже приведена часть моего уровня базы данных.
package dao;
import java.util.List;
import model.main.Familyvisa;
import model.main.Familyvisa;
import model.main.Familyvisa;
import model.main.Pensionhistory;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
/**
*
* @author user
*/
public class FamilyVisaImpl implements FamilyVisaInterface
{
private Session currentSession;
private Transaction currentTransaction;
public Session openCurrentSession() {
currentSession = getSessionFactory().openSession();
return currentSession;
}
public Session openCurrentSessionwithTransaction() {
currentSession = getSessionFactory().openSession();
currentTransaction = currentSession.beginTransaction();
return currentSession;
}
public void closeCurrentSession() {
currentSession.close();
}
public void closeCurrentSessionwithTransaction() {
currentTransaction.commit();
currentSession.close();
}
private static SessionFactory getSessionFactory() {
Configuration configuration = new Configuration().configure();
StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties());
SessionFactory sessionFactory = configuration.buildSessionFactory(builder.build());
return sessionFactory;
}
public Session getCurrentSession() {
return currentSession;
}
public void setCurrentSession(Session currentSession) {
this.currentSession = currentSession;
}
public Transaction getCurrentTransaction() {
return currentTransaction;
}
public void setCurrentTransaction(Transaction currentTransaction) {
this.currentTransaction = currentTransaction;
}
@Override
public void save(Familyvisa entity) {
getCurrentSession().save(entity);
}
@Override
public void update(Familyvisa entity) {
getCurrentSession().update(entity);
}
@Override
public Familyvisa findById(int id) {
Familyvisa book = (Familyvisa) getCurrentSession().get(Familyvisa.class, id);
return book;
}
@Override
public void delete(Familyvisa entity) {
getCurrentSession().delete(entity);
}
@Override
public List<Familyvisa> findAll() {
List<Familyvisa> remDur = (List<Familyvisa>) getCurrentSession().createQuery("from Familyvisa").list();
return remDur;
}
public Familyvisa findByForiegnKey_Family(int idFamily)
{
String hql = "FROM Familyvisa WHERE idFamily = :famId";
//String hql = "FROM Visa WHERE idFamily = :famId";
Query q = getCurrentSession().createQuery(hql);
q.setParameter("famId", idFamily);
Familyvisa v = new Familyvisa();
if(!q.list().isEmpty())
{
v = (Familyvisa)q.list().get(0);
}
return v;
}
@Override
public void saveOrUpdate(Familyvisa p)
{
getCurrentSession().saveOrUpdate(p);
}
@Override
public List<Object[]> findReminderActiveVisaWithFamilyAndEmployee()
{
String sql = "";
SQLQuery createSQLQuery = getCurrentSession().createSQLQuery(sql);
return createSQLQuery.list();
}
@Override
public void batchUpdate(List<Familyvisa> list)
{
for(int i=0;i<list.size();i++)
{
getCurrentSession().update(list.get(i));
}
}
}
Ниже представлен мой сервисный уровень, относящийся к вышеуказанному коду.
package service;
import dao.FamilyVisaImpl;
import java.util.List;
import model.main.Familyvisa;
/**
*
* @author user
*/
public class FamilyVisaService
{
private FamilyVisaImpl familyVisaImpl;
public FamilyVisaService()
{
familyVisaImpl = new FamilyVisaImpl();
}
public Familyvisa findByForiegnKey_Family(int idFamily)
{
familyVisaImpl.openCurrentSession();
Familyvisa findByForiegnKey_Family = familyVisaImpl.findByForiegnKey_Family(idFamily);
familyVisaImpl.closeCurrentSession();
return findByForiegnKey_Family;
}
public List<Object[]> findReminderActiveVisaWithFamilyAndEmployee()
{
familyVisaImpl.openCurrentSession();
List<Object[]> visa = familyVisaImpl.findReminderActiveVisaWithFamilyAndEmployee();
familyVisaImpl.closeCurrentSession();
return visa;
}
public void batchUpdate(List<Familyvisa> list)
{
familyVisaImpl.openCurrentSessionwithTransaction();
familyVisaImpl.batchUpdate(list);
familyVisaImpl.closeCurrentSessionwithTransaction();
}
}
Ниже приведен код сервлета, в котором объясняется, как я выполняю код.
private void updateDatabase(List<VisaWithFamilyAndEmployeeBean> reminderSentList)
{
FamilyVisaService service = new FamilyVisaService();
List<Familyvisa> visa = new ArrayList<Familyvisa>();
for(int i=0;i<reminderSentList.size();i++)
{
Familyvisa familyVisa = service.findByForiegnKey_Family(reminderSentList.get(i).getIdFamily());
familyVisa.setNumberOfReminders(familyVisa.getNumberOfReminders()+1);
familyVisa.setLastReminderSent(Common.getCurrentDateSQL());
visa.add(familyVisa);
}
service.batchUpdate(visa);
}
У меня есть много классов в трех слоях (сервлет, DAO, Service) и все следует точно такой же структуре, обслуживая разные цели, но метода выглядит почти так же (как обновление, вставка и т.д.).
Пожалуйста, обратите некоторые достойные внимания к коду, ключевым словам, использование спецификаторов доступа и т.д. В некоторых других классах, в уровне услуг, я определяю это осуще в static
, а например: private static EmployeeImpl employeeimpl;
Можете ли вы найти то, что здесь происходит неправильно? Так как это происходит только «иногда» и в любом из кода (не только здесь, но и в других классах, то только различие в том, что они обращаются к разным таблицам), поэтому я могу понять это.
UPDATE
Учитывая замечания и ответы, я изменил код ниже. Пожалуйста, дайте мне знать, находится ли он на уровне качества.
FamilyVisaService service = new FamilyVisaService();
Session session = service.openCurrentSession(); //This method will call openCurrentSession() in Impl class
try {
for(int i=0;i<reminderSentList.size();i++)
{
/* findByForiegnKey_Family() has Session argument now! */
Familyvisa familyVisa = service.findByForiegnKey_Family(session, reminderSentList.get(i).getIdFamily());
familyVisa.setNumberOfReminders(familyVisa.getNumberOfReminders()+1);
familyVisa.setLastReminderSent(Common.getCurrentDateSQL());
visa.add(familyVisa);
}
} catch (Exception ex) {
System.out.println("ERROR:"+ex);
} finally {
session.close();
}
Интересно, но похоже, что я должен внести массу изменений? –
@JustCause, на самом деле вам нужно просто открыть и закрыть сеанс вне функции .findByForiegnKey_Family() 'и цикла. + отказаться от операций без транзакций. Это все – WildDev
Хорошо, не могли бы вы сделать его потокобезопасным? –