Java 连接太多错误:休眠
我在我的web应用程序中使用Hibernate,它是用纯Servlet和JSP开发的。我在执行代码时“有时”会遇到大麻烦。发生的情况是,我从Hibernate获得了太多的连接 为了寻找答案,我经历了很多问题,我找到了不同的解决方案。一些人建议使用第三方池系统,一些人建议线程安全,一些人建议使用一个Java 连接太多错误:休眠,java,database,hibernate,servlets,connection-pooling,Java,Database,Hibernate,Servlets,Connection Pooling,我在我的web应用程序中使用Hibernate,它是用纯Servlet和JSP开发的。我在执行代码时“有时”会遇到大麻烦。发生的情况是,我从Hibernate获得了太多的连接 为了寻找答案,我经历了很多问题,我找到了不同的解决方案。一些人建议使用第三方池系统,一些人建议线程安全,一些人建议使用一个SessionFactory等,因此我不确定哪一个适用于我的系统 下面是我的数据库层的一部分 package dao; import java.util.List; import model.main
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));
}
}
}
您的代码在很多方面都是错误的:
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();
}
服务层单例不应该存储状态,因为它们是由并发请求访问的。如果您有一个当前正在运行的会话,并且第二个请求也打开了一个新会话,该怎么办?第一个线程永远不会有机会关闭其会话,但它将尝试关闭上次打开的会话(例如currentSession)会话
甚至不是线程安全的,因此您会遇到各种奇怪的并发修改或更改可见性错误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);
}
上面的例子是线程安全的。因为您在单个函数中打开、操作和关闭会话
Hibernate需要事务块,即使对于读取操作也是如此。因此,您必须像这样修复代码:
Session session = ...
try {
session.beginTransaction();
...
Your Loop
...
session.getTransaction.commit();
...
1.它不是线程安全的,因为
类级别变量?但是它不是在Servlet
中,而是在另一个类中?2.我没抓住要点。3.好像“关闭内的会话最终阻止
?4.我想我们太晚了。最后,如何创建SessionFactory
?看起来,它每次都在updateDatabase
1的循环中打开新实例。多个请求可以调用openCurrentSession
,因此设置会话
,并且每个会话都应该绑定到调用线程。在您的例子中,会话
保存最后打开的会话,而且这甚至不是线程安全的。3.即使您在finally块上调用close,您确定要关闭您首先打开的会话吗?1。多个请求可以调用openCurrentSession并因此设置会话,并且每个会话都应该绑定到调用线程
-我如何才能做到这一点?。。请检查SessionFactory
,我正在一个方法中定义它。FamilyVisaService
是单例的,它有一个familyvisimpl
实例。多个请求调用FamilyVisaService
方法,因此同时调用openCurrentSession()。因此,每次新的openCurrentSession()
调用都会覆盖session
变量。有意义吗?FamilyVisaService
不是单身。我试着做一个,但后来我停了下来。这不是单例。很有趣,但似乎我必须做很多更改?@JustCause,实际上您只需将打开和关闭会话的操作移到.findbyforeignkey_Family()
函数和循环之外即可拒绝非事务性操作。这就是安拉,所以你的整个代码都在一个函数中。好的,我认为会话
是一个全局变量,因为您没有声明函数。我添加了一个更新,另一个有一些更改的小代码,我根据答案进行了更改。请看一看,让我知道是否有任何问题或是否可以。您忘记了事务块。最好添加它以防止意外结果。其余的都可以,应该可以。
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();
}
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);
}
Session session = ...
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();
}
Session session = ...
try {
session.beginTransaction();
...
Your Loop
...
session.getTransaction.commit();
...