#java #hibernate
#java #гибернация
Вопрос:
Я получаю следующую ошибку:
.
.
.
.
6844 [main] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 1040, SQLState: 08004
6844 [main] ERROR org.hibernate.util.JDBCExceptionReporter - Data source rejected establishment of connection, message from server: "Too many connections"
Exception in thread "main" org.hibernate.exception.JDBCConnectionException: Cannot open connection
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:99)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:52)
at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:449)
at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:167)
at org.hibernate.jdbc.JDBCContext.connection(JDBCContext.java:160)
at org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:81)
at org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1473)
at sun.reflect.GeneratedMethodAccessor121.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:345)
at $Proxy0.beginTransaction(Unknown Source)
at com.mycomp.myproj.matcher.Matcher.findMatch(Matcher.java:228)
at com.mycomp.myproj.Confidence.Confidence.main(Confidence.java:160)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Data source rejected establishment of connection, message from server: "Too many connections"
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:409)
at com.mysql.jdbc.Util.getInstance(Util.java:384)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1015)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:989)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:984)
at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1105)
at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2186)
at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:787)
at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:49)
at sun.reflect.GeneratedConstructorAccessor16.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:409)
at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:357)
at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:285)
at java.sql.DriverManager.getConnection(Unknown Source)
at java.sql.DriverManager.getConnection(Unknown Source)
at org.hibernate.connection.DriverManagerConnectionProvider.getConnection(DriverManagerConnectionProvider.java:133)
at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446)
... 11 more
Биты гибернации моей программы выглядят следующим образом:
for loop_1 // this will execute say 2000 times
{
for loop_2 // this will execute say 1000 times
{
// Opening 2 sessions for 2 different databases
Configuration config_1 = new Configuration().configure("Hibernate_1.cfg.xml");
SessionFactory sessionFactory_1 = config_1.buildSessionFactory();
Session session_1 = sessionFactory_1.getCurrentSession();
session_1.beginTransaction();
Configuration config_2 = new Configuration().configure("Hibernate_2.cfg.xml");
SessionFactory sessionFactory_2 = config_2.buildSessionFactory();
Session session_2 = sessionFactory_2.getCurrentSession();
session_2.beginTransaction();
doInsertDb_1(some_object_1, session_1);
doUpdateDb_2(some_object_2, session_2);
}
}
public int doInsertDb_1(Object obj, Session session) {
try {
session.save(obj);
session.flush();
session.getTransaction().commit();
return 1;
} catch (Exception ex) {
ex.printStackTrace();
return 0;
}
}
public int doUpdate_2(Object obj, Session session) {
try {
Query query = session.createQuery("" <Creating some query> );
query.executeUpdate();
session.getTransaction().commit();
return 1;
} catch (Exception ex) {
ex.printStackTrace();
return 0;
}
}
Очевидно, что где-то я не закрываю соединения должным образом. Я не могу понять, где? Может кто-нибудь, пожалуйста, помочь мне с этим?
Большое спасибо.
Ответ №1:
Вы уверены, что вам нужно создавать оба сеанса каждый раз через цикл? Создание их один раз, перед обоими циклами, скорее всего, решит вашу проблему и ускорит ваш код. Однако, если вы настаиваете на том, чтобы открывать их во внутреннем цикле, обязательно сделайте close()
это впоследствии, поскольку это должно, по крайней мере, освободить соединения с базой данных, которые вы открываете (но никогда не закрываете.)
РЕДАКТИРОВАТЬ: Вам следует отложить внесение изменений до тех пор, пока вы не внесете их все, чтобы не закрывать соединения преждевременно.
ПРАВКА 2: Поскольку вам нужны результаты каждого обновления для обработки дальнейших обновлений, вы можете, по крайней мере, перенести создание SessionFactories за пределы циклов.
Комментарии:
1. @dlev: Спасибо за ваш ответ. как я ответил Cris, если я создаю их снаружи
for loop_1
, я получаюSession already closed!
ошибку. Это потому, что, когда я делаюsession.getTransaction().commit();
, я вижу в отладчике, что он закрывает сеанс после этого stmt.2. Интересно. Возможно, вам следует просто отложить фиксацию, пока вы не внесете все свои изменения?
3. я обязательно попробую это. где-то я обнаружил, что оператор закрытия и ResultSet помогли запрашивающему. Я также выполняю некоторые выборки в каждом цикле (которые я не добавил в свой вопрос). так и думал, что в этом проблема. но я также закрываю инструкцию и результирующий набор, и все та же проблема.
4. @dlev: ваше предложение помогает, но есть одна проблема. в цикле, когда я вставляю записи в БД, я должен рассмотреть эту запись в следующем цикле. поэтому, если я не зафиксирую это немедленно, я не смогу получить эту запись и, следовательно, конечный результат будет неправильным. есть ли способ получше?
5. Хм … одной из возможностей было бы переместить создание SessionFactory за пределы обоих циклов, но сохранить само создание сеанса внутри. Это работает?
Ответ №2:
Попробуйте создать сеансы вне цикла
Комментарии:
1. Спасибо за ваш ответ. Я попытался создать их вне
for loop_2
и получил ту же ошибку. Кроме того, я попытался создать их внеfor loop_2
и я получаюSession already closed!
, что и ожидалось.2. я создал сеанс вне цикла, а также удалил
session.getTransaction().commit();
stmt, и теперь я совершаю транзакцию снаружиfor loop_1
. но когда я вставляю записи в БД, я должен учитывать эту запись в следующем цикле. поэтому, если я не зафиксирую это немедленно, я не смогу получить эту запись и, следовательно, конечный результат будет неправильным. есть ли способ получше?