Update statement does not get generated when flushing in case we have batching on for following example:
{noformat}@Entity @Inheritance(strategy = InheritanceType.JOINED) class BaseEntity implements Serializable { private static final long serialVersionUID = -5412503864464287451L;
@Id long id; @Column(name = "VAL") int val; }
@Entity @PrimaryKeyJoinColumn(name = "ID") class FooEntity extends BaseEntity { private static final long serialVersionUID = 6681665021507587925L;
@Column(name = "NAME") String name;
FooEntity() {}
FooEntity(long id) { this.id = id; } }
@Entity class SingleTableEntity implements Serializable { private static final long serialVersionUID = -5412503864464287451L;
@Id long id; @Column(name = "NAME") String name;
SingleTableEntity() {}
SingleTableEntity(long id) { this.id = id; } }
public class FlushTest {
@Test public void test() { Transaction txn = null; try (final Session session = newSessionFactory().openSession()) { txn = session.beginTransaction(); final FooEntity foo = new FooEntity(1L); session.persist(foo); session.flush(); session.clear();
FooEntity fetched = session.get(FooEntity.class, 1L); fetched.name = "string"; session.flush(); session.clear(); fetched = session.get(FooEntity.class, 1L); fetched.name = "string2"; // This flush does not generate update, and it should session.flush(); session.clear(); fetched = session.get(FooEntity.class, 1L); assertEquals("string2", fetched.name); txn.rollback(); } }
@Test public void testSingleTable() { Transaction txn = null; try (final Session session = newSessionFactory().openSession()) { txn = session.beginTransaction(); final SingleTableEntity foo = new SingleTableEntity(1L); session.persist(foo); session.flush(); session.clear();
SingleTableEntity fetched = session.get(SingleTableEntity.class, 1L); fetched.name = "string"; session.flush(); session.clear(); fetched = session.get(SingleTableEntity.class, 1L); fetched.name = "string2"; session.flush(); session.clear(); fetched = session.get(SingleTableEntity.class, 1L); assertEquals("string2", fetched.name); txn.rollback(); } }
protected SessionFactory newSessionFactory() { final Properties properties = new Properties(); properties.put("hibernate.hbm2ddl.auto", "create"); properties.put("hibernate.show_sql", "true"); properties.put("hibernate.dialect", "org.hibernate.dialect.HSQLDialect"); properties.put("hibernate.connection.driver_class", "org.hsqldb.jdbc.JDBCDriver"); properties.put("hibernate.connection.url", "jdbc:hsqldb:mem:test"); properties.put("hibernate.connection.username", "sa"); properties.put("hibernate.connection.password", ""); // putting batch_size to 1 solves the problem properties.put("hibernate.jdbc.batch_size", "2");
return new Configuration().addProperties(properties) .addAnnotatedClass(BaseEntity.class) .addAnnotatedClass(FooEntity.class) .addAnnotatedClass(SingleTableEntity.class) .buildSessionFactory(new StandardServiceRegistryBuilder().applySettings(properties).build()); } }
{noformat}
After some debugging found quick workaround and potentially source of the problem, removing
{noformat} if (currentBatch.getKey().equals(key)) { return currentBatch; }{noformat}
from org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.getBatch solves the problem. It seems that state of {{currentBatch}} is left from previous statement execution but with all preparestatements cleared. And since {{BatchKey}} is the same as previous update empty batch, without prepared statements, is being reused and no update statement is being generated/executed.
This issue seems to be related to [https://hibernate.atlassian.net/browse/HHH-16367|https://hibernate.atlassian.net/browse/HHH-16367|smart-link] but that one is I think wrongfully closed as duplicate. Test case eclipse project with pom attached to issue. |
|