i recently updated from mysql-connector-java 5.1.22 to 5.1.23. After that my application is constantly crashing on update or delete of persisted objects.
Mysql Connectors up to 5.1.22 (including 5.1.22) are working fine. MySQL Connectors from 5.1.23 (including 5.1.23) are not working.
Cause of the Problem seems to be the Time stamp i use for Optimistic locking. Optimistic locking with a Version seems to work fine. But i can't change the whole application and i need the Time stamp fields.
The changelog of 5.1.23 states the following bugfix:
If a timestamp value was passed through prepared statement parameters, fractional-second precision was stripped off, even if the underlying field (such as VARCHAR(255)) could store the full value. A workaround was to convert the timestamp value to a string when specifying the prepared statement argument, for example prepped_stmt.setString(1,time_stamp.toString(). This was partly fixed in 5.1.19, but that fix did not cover the case with the setting useLegacyDatetimeCode=true. (Bug #11750017, Bug #40279, Bug #60584)
I suspect this is the cause of my problems. Any ideas how to solve the problem? I appended a simple sample code causing the error.
---Exception
Jul 02, 2014 9:18:34 AM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {4.0.4.Final}
Jul 02, 2014 9:18:34 AM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {4.3.5.Final}
Jul 02, 2014 9:18:34 AM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
Jul 02, 2014 9:18:34 AM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : javassist
Jul 02, 2014 9:18:34 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH000402: Using Hibernate built-in connection pool (not for production use!)
Jul 02, 2014 9:18:34 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000401: using driver [com.mysql.jdbc.Driver] at URL [jdbc:mysql://localhost:3306/hibernatedb?useFastDateParsing=false]
Jul 02, 2014 9:18:34 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000046: Connection properties: {user=root, password=****}
Jul 02, 2014 9:18:34 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000006: Autocommit mode: false
Jul 02, 2014 9:18:34 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000115: Hibernate connection pool size: 1 (min=1)
Jul 02, 2014 9:18:34 AM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
Jul 02, 2014 9:18:34 AM org.hibernate.engine.transaction.internal.TransactionFactoryInitiator initiateService
INFO: HHH000399: Using default transaction strategy (direct JDBC transactions)
Jul 02, 2014 9:18:34 AM org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory <init>
INFO: HHH000397: Using ASTQueryTranslatorFactory
Jul 02, 2014 9:18:35 AM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: HHH000227: Running hbm2ddl schema export
Jul 02, 2014 9:18:35 AM org.hibernate.tool.hbm2ddl.SchemaExport execute
INFO: HHH000230: Schema export complete
MyPersistentObject (2014-07-02 09:18:35.0) : First persistent object
MyPersistentObject (2014-07-02 09:18:35.0) : A second persistent object
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [MyPersistentObject#2]
at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:2541)
at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:3403)
at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:3630)
at org.hibernate.action.internal.EntityDeleteAction.execute(EntityDeleteAction.java:114)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:463)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:349)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1222)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:425)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
at HibernateExample.manipulatePersistentObjects(HibernateExample.java:143)
at HibernateExample.main(HibernateExample.java:15)
MyPersistentObject (2014-07-02 09:18:35.0) : First persistent object
MyPersistentObject (2014-07-02 09:18:35.0) : A second persistent object
Jul 02, 2014 9:18:35 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop
INFO: HHH000030: Cleaning up connection pool [jdbc:mysql://localhost:3306/hibernatedb?useFastDateParsing=false]
---main class
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.service.ServiceRegistry;
public class HibernateExample {
private final org.hibernate.SessionFactory _sessionFactory;
private MyPersistentObject _myPersistentObject1;
private MyPersistentObject _myPersistentObject2;
private MyPersistentObject _myPersistentObject3;
final static public void main(final String arguments[]) {
HibernateExample example;
example = new HibernateExample();
example.createPersistentObjects();
example.readAndDisplayPersistentObjects();
example.manipulatePersistentObjects();
example.readAndDisplayPersistentObjects();
example.cleanup();
}
private HibernateExample() {
org.hibernate.cfg.Configuration configuration;
java.util.logging.Logger.getLogger("org.hibernate").setLevel(java.util.logging.Level.SEVERE); // Supress
// Hibernate's
// excessive
// output
configuration = new org.hibernate.cfg.Configuration();
configuration.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLDialect"); // Customize
// this
// for
// your
// particular
// RDBMS
configuration.setProperty("hibernate.connection.driver_class", "com.mysql.jdbc.Driver"); // Customize
// this
// for
// your
// particular
// RDBMS
// configuration.setProperty("hibernate.connection.url",
// "jdbc:mysql://localhost:3306/hibernatedb?useLegacyDatetimeCode=true");
// // Customize
configuration.setProperty("hibernate.connection.url",
"jdbc:mysql://localhost:3306/hibernatedb?useFastDateParsing=false"); // Customize
// this
// for
// your
// particular
// RDBMS
configuration.setProperty("hibernate.connection.username", "root"); // Customize
// this
// for
// your
// particular
// RDBMS
configuration.setProperty("hibernate.connection.password", "root"); // Customize
// this
// for
// your
// particular
// RDBMS
// installation
configuration.setProperty("hibernate.connection.pool_size", "1"); // Customize
// this
// for
// your
// particular
// RDBMS
// installation
configuration.setProperty("hibernate.cache.provider_class", "org.hibernate.cache.internal.NoCacheProvider"); // This
// is
// not
// ready
// for
// prime-time
configuration.setProperty("hibernate.show_sql", "false"); // Tell
// hibernate
// to not
// echo the
// SQL
configuration.setProperty("hibernate.hbm2ddl.auto", "create");
configuration.setProperty("useLegacyDatetimeCode", "true");
configuration.addAnnotatedClass(MyPersistentObject.class);
// configuration.configure();
final ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(
configuration.getProperties()).build();
this._sessionFactory = configuration.buildSessionFactory(serviceRegistry);
}
final private void createPersistentObjects() {
org.hibernate.Session session;
boolean committed;
org.hibernate.Transaction transaction;
session = this._sessionFactory.openSession();
try {
committed = false;
transaction = session.beginTransaction();
try {
this._myPersistentObject1 = new MyPersistentObject("First persistent object", new java.util.Date());
session.save(this._myPersistentObject1);
this._myPersistentObject2 = new MyPersistentObject("A second persistent object", new java.util.Date());
session.save(this._myPersistentObject2);
transaction.commit();
session.flush();
committed = true;
} finally {
if (!committed) {
transaction.rollback();
}
}
} finally {
session.close();
}
}
final private void manipulatePersistentObjects() {
org.hibernate.Session session;
org.hibernate.Transaction transaction;
session = this._sessionFactory.openSession();
try {
transaction = session.beginTransaction();
this._myPersistentObject3 = new MyPersistentObject("A third persistent object", new java.util.Date());
// session.save(this._myPersistentObject3);
session.delete(this._myPersistentObject2);
transaction.commit();
session.flush();
} catch (final Exception e) {
e.printStackTrace();
} finally {
session.close();
}
}
final private void readAndDisplayPersistentObjects() {
org.hibernate.Session session;
java.util.List<MyPersistentObject> result;
session = this._sessionFactory.openSession();
try {
session.beginTransaction();
result = (session.createQuery("from MyPersistentObject").list());
for (final MyPersistentObject persistentObject : result) {
System.out.println("MyPersistentObject (" + persistentObject.getDate() + ") : "
+ persistentObject.getTitle());
}
session.getTransaction().commit();
session.flush();
} catch (final Exception e) {
e.printStackTrace();
} finally {
session.close();
}
}
final private void cleanup() {
if (this._sessionFactory != null) {
this._sessionFactory.close();
}
}
}
---Object
import java.util.Calendar;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Version;
@javax.persistence.Entity
public class MyPersistentObject {
@javax.persistence.Id
@javax.persistence.GeneratedValue(generator = "increment")
@org.hibernate.annotations.GenericGenerator(name = "increment", strategy = "increment")
private Long _persistenceID;
private String _title;
@javax.persistence.Temporal(javax.persistence.TemporalType.TIMESTAMP)
@javax.persistence.Column(name = "OBJECT_DATE")
private java.util.Date _date;
@Version
private Calendar timestemp;
// Hibernate needs a no-argument constructor
private MyPersistentObject() {
}
// for application use, to create new persistent objects
public MyPersistentObject(final String title, final java.util.Date date) {
this._title = title;
this._date = date;
}
public java.util.Date getDate() {
return this._date;
}
public String getTitle() {
return this._title;
}
@PrePersist
protected void onCreate() {
System.out.println("create");
}
@PreUpdate
protected void onUpdate() {
System.out.println("update");
}
}
---pom
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>Hibernate34Migrate</groupId>
<artifactId>Hibernate34Migrate</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.5.Final</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>4.3.5.Final</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.31</version>
</dependency>
</dependencies>
</project>