Hallo,
ich versuche gerade einen Fehler der bei uns auftritt zu analysieren.
Als Beispiel kann das Tutorial mit dem Beispiel "Event" herangzogen werden. Also eine Instanz des Objekts "Event" in der Datenbank ablegen.
Wir nutzen als Datenbank mysql und den mysql-connector-java-5.1.24-bin.jar, hibernate 4.1.11
Code:
import java.util.Date;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
public class PlayWithHibernate {
public static void main(String [] args)
{
System.out.println("Start with output");
Configuration conf = new Configuration();
// if you use the default config file, you do not have to add it as parameter
conf.configure("hibernate.cfg.xml");
// f... to build sessionfactory has changed from
//SessionFactory sessionFactory = conf.buildSessionFactory();
// to
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(conf.getProperties()).buildServiceRegistry();
SessionFactory sessionFactory = conf.buildSessionFactory(serviceRegistry);
// and go on with opening and closing sessions ...
System.out.println(" line 28 ");
System.out.println(serviceRegistry.toString());
System.out.println(sessionFactory.getAllClassMetadata().toString());
System.out.println(sessionFactory.getStatistics());
Session session = sessionFactory.openSession();
System.out.println("31");
session.beginTransaction();
Event myevent = new Event();
myevent.setTitle("Test");
myevent.setDate(new Date());
myevent.setInfo("this is an additional information string");
session.save(myevent);
session.getTransaction().commit();
session.close();
System.out.println("42");
try {
Thread.sleep(12000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(" - 51 - ");
session = sessionFactory.openSession();
try {
session.beginTransaction();
Event myevent2 = new Event();
myevent2.setTitle("Test2");
myevent2.setDate(new Date());
myevent2.setInfo("this is an additional information string");
session.save(myevent2);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
// TODO: handle exception
}
System.out.println(sessionFactory.getStatistics());
sessionFactory.close();
}
}
Folgende Konfiguration wird verwendet.
Code:
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://127.0.0.1:3306/mytest</property>
<property name="connection.username">localtest</property>
<property name="connection.password">mypasswd</property>
<property name="connection.pool_size">5</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>
<property name="hibernate.c3p0.min_size">1</property>
<property name="hibernate.c3p0.max_size">5</property>
<property name="hibernate.c3p0.max_statements">50</property>
<property name="hibernate.c3p0.timeout">5</property>
<property name="hibernate.c3p0.preferredTestQuery">Select * from EVENTS</property>
<property name="hibernate.c3p0.testConnectionOnCheckout">true</property>
<property name="hibernate.c3p0.idle_test_period">1</property>
<property name="c3p0.debugUnreturnedConnectionStackTraces">true</property>
<!-- for hbm2ddl.auto you can use with: create-drop, create, update, ... -->
<property name="hbm2ddl.auto">update</property>
<mapping resource="event.hbm.xml" />
</session-factory>
</hibernate-configuration>
In das Projekt sind folgende Bibliotheken eingebunden:
- antlr-2.7.7.jar
- dom4j-1.6.1.jar
- hibernate-commons-annotations-4.0.1.Final.jar
- hibernate-core-4.1.11.Final.jar
- hibernate-jpa-2.0-api-1.0.1.Final.jar
- javassist-3.15.0-GA.jar
- jboss-logging-3.1.0.GA.jar
- jboss-transaction-api_1.1_spec-1.0.0.Final.jar
- mysql-connector-java-5.1.24.bin.jar
- slf4j-api-1.6.1.jar
da die Bibliotheken für c3p0 hier fehlen, werden die Einstellungen aus der Konfiguration ignoriert, aber dazu komme ich weiter unten noch mal.
Wichtig für die Reproduktion des Fehlers sind noch folgende Einstellungen für mysql:
[mysqld]
....
wait_timeout = 10
interactive_timeout = 10
was passiert nun?
- Objekt "Test" wird erstellt und wird nachvollziehbar gespeichert
- während der Thread schläft unterbricht die Datenbank die Verbindung
- Objekt "Test2" wird erstellt, ein Schreiben in die Datenbank schlägt fehl
Folgende Fehlermeldung wird dabei immer angezeigt (also auch ohne e.printStackTrace();)
Code:
28.03.2013 14:22:06 org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
WARN: SQL Error: 0, SQLState: 08S01
28.03.2013 14:22:06 org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: Communications link failure
Das ganze habe ich auch schon mit dem Pool (c3p0) probiert und auch testweise eine Klasse für "hibernate.c3p0.connectionCustomizerClassName" erstellt, aber ich schaffe es nicht, dass dieses Problem ohne weiteren Code von unserer Seite zu beheben. Wir sind nun hingegangen und erzeugen testweise eine Transaktion und im Fehlerfall wird halt eine neue Factory erstellt. IMHO nicht schön.
Aus Sicht von mysql sieht das ganze ohne c3p0 wie folgt aus:
Code:
130328 14:21:54 102 Connect localtest@localhost on mytest
102 Query /* mysql-connector-java-5.1.24 ( Revision: ${bzr.revision-id} ) */SHOW VARIABLES WHERE Variable_name ='language' OR Variable_name = 'net_write_timeout' OR Variable_name = 'interactive_timeout' OR Variable_name = 'wait_timeout' OR Variable_name = 'character_set_client' OR Variable_name = 'character_set_connection' OR Variable_name = 'character_set' OR Variable_name = 'character_set_server' OR Variable_name = 'tx_isolation' OR Variable_name = 'transaction_isolation' OR Variable_name = 'character_set_results' OR Variable_name = 'timezone' OR Variable_name = 'time_zone' OR Variable_name = 'system_time_zone' OR Variable_name = 'lower_case_table_names' OR Variable_name = 'max_allowed_packet' OR Variable_name = 'net_buffer_length' OR Variable_name = 'sql_mode' OR Variable_name = 'query_cache_type' OR Variable_name = 'query_cache_size' OR Variable_name = 'init_connect'
102 Query /* mysql-connector-java-5.1.24 ( Revision: ${bzr.revision-id} ) */SELECT @@session.auto_increment_increment
102 Query SHOW COLLATION
102 Query SET NAMES latin1
102 Query SET character_set_results = NULL
102 Query SET autocommit=1
102 Query SET sql_mode='STRICT_TRANS_TABLES'
102 Query SET autocommit=0
102 Query commit
102 Query SET autocommit=1
102 Query SHOW FULL TABLES FROM `mytest` LIKE 'EVENTS'
102 Query SHOW FULL TABLES FROM `mytest` LIKE 'EVENTS'
102 Query SHOW FULL COLUMNS FROM `EVENTS` FROM `mytest` LIKE '%'
102 Query SHOW CREATE TABLE `mytest`.`EVENTS`
102 Query SHOW INDEX FROM `EVENTS` FROM `mytest`
102 Query SET autocommit=0
102 Query insert into EVENTS (EVENT_CREATE, EVENT_DATE, title, info) values ('2013-03-28 14:21:54', '2013-03-28 14:21:54', 'Test', 'this is an additional information string')
102 Query commit
und mit
Code:
130328 13:46:27 87 Connect localtest@localhost on mytest
89 Connect localtest@localhost on mytest
88 Connect localtest@localhost on mytest
.... hier noch die Queries wie oben ...
88 Query /* mysql-connector-java-5.1.24 ( Revision: ${bzr.revision-id} ) */SELECT @@session.auto_increm
ent_increment
89 Query /* mysql-connector-java-5.1.24 ( Revision: ${bzr.revision-id} ) */SELECT @@session.auto_increm
ent_increment
87 Query /* mysql-connector-java-5.1.24 ( Revision: ${bzr.revision-id} ) */SELECT @@session.auto_increm
ent_increment
88 Query SHOW COLLATION
87 Query SHOW COLLATION
89 Query SHOW COLLATION
88 Query SET NAMES latin1
88 Query SET character_set_results = NULL
88 Query SET autocommit=1
88 Query SET sql_mode='STRICT_TRANS_TABLES'
89 Query SET NAMES latin1
89 Query SET character_set_results = NULL
89 Query SET autocommit=1
89 Query SET sql_mode='STRICT_TRANS_TABLES'
88 Query SELECT @@session.tx_isolation
89 Query SELECT @@session.tx_isolation
87 Query SET NAMES latin1
87 Query SET character_set_results = NULL
87 Query SET autocommit=1
87 Query SET sql_mode='STRICT_TRANS_TABLES'
87 Query SELECT @@session.tx_isolation
88 Query Select * from EVENTS
88 Query SET autocommit=0
88 Query rollback
88 Query SET autocommit=1
88 Query Select * from EVENTS
88 Query SET autocommit=0
88 Query commit
88 Query SET autocommit=1
88 Query SHOW FULL TABLES FROM `mytest` LIKE 'EVENTS'
88 Query SHOW FULL TABLES FROM `mytest` LIKE 'EVENTS'
88 Query SHOW FULL COLUMNS FROM `EVENTS` FROM `mytest` LIKE '%'
88 Query SHOW CREATE TABLE `mytest`.`EVENTS`
88 Query SHOW INDEX FROM `EVENTS` FROM `mytest`
88 Query SET autocommit=0
88 Query SET autocommit=1
88 Query Select * from EVENTS
88 Query SET autocommit=0
88 Query insert into EVENTS (EVENT_CREATE, EVENT_DATE, title, info) values ('2013-03-28 13:46:27', '201
3-03-28 13:46:27', 'Test', 'this is an additional information string')
88 Query commit
87 Query Select * from EVENTS
89 Query Select * from EVENTS
130328 13:46:28 87 Query Select * from EVENTS
89 Query Select * from EVENTS
130328 13:46:29 87 Query Select * from EVENTS
89 Query Select * from EVENTS
130328 13:46:30 87 Query Select * from EVENTS
89 Query Select * from EVENTS
130328 13:46:31 87 Query Select * from EVENTS
89 Query Select * from EVENTS
130328 13:46:32 87 Query Select * from EVENTS
89 Query Select * from EVENTS
130328 13:46:33 87 Quit
89 Quit
Meine Frage:
Gibt es eine Möglichkeit durch geeignete Settings dieses Problem zu beheben? Für ein Produktivsystem kommt mir eine ständige
Überprüfung auf Benutzerseite doch recht "teuer" vor.
Grüße
re