[JIRA] (HHH-16517) H6: Problems with flush when batch is ON (without @DynamicUpdate)
by Nemanja Jovanovic (JIRA)
Nemanja Jovanovic ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... ) *updated* an issue
Hibernate ORM ( https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiYjFjMmY2MWNl... ) / Bug ( https://hibernate.atlassian.net/browse/HHH-16517?atlOrigin=eyJpIjoiYjFjMm... ) HHH-16517 ( https://hibernate.atlassian.net/browse/HHH-16517?atlOrigin=eyJpIjoiYjFjMm... ) H6: Problems with flush when batch is ON (without @DynamicUpdate) ( https://hibernate.atlassian.net/browse/HHH-16517?atlOrigin=eyJpIjoiYjFjMm... )
Change By: Nemanja Jovanovic ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... )
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.atlass... that one is I think wrongfully closed as duplicate. Test case eclipse project with pom attached to issue.
( https://hibernate.atlassian.net/browse/HHH-16517#add-comment?atlOrigin=ey... ) Add Comment ( https://hibernate.atlassian.net/browse/HHH-16517#add-comment?atlOrigin=ey... )
Get Jira notifications on your phone! Download the Jira Cloud app for Android ( https://play.google.com/store/apps/details?id=com.atlassian.android.jira.... ) or iOS ( https://itunes.apple.com/app/apple-store/id1006972087?pt=696495&ct=EmailN... ) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100223- sha1:cdc0af3 )
1 year, 2 months
[JIRA] (HHH-16517) H6: Problems with flush when batch is ON (without @DynamicUpdate)
by Nemanja Jovanovic (JIRA)
Nemanja Jovanovic ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... ) *updated* an issue
Hibernate ORM ( https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiOThhNzJlNTMx... ) / Bug ( https://hibernate.atlassian.net/browse/HHH-16517?atlOrigin=eyJpIjoiOThhNz... ) HHH-16517 ( https://hibernate.atlassian.net/browse/HHH-16517?atlOrigin=eyJpIjoiOThhNz... ) H6: Problems with flush when batch is ON (without @DynamicUpdate) ( https://hibernate.atlassian.net/browse/HHH-16517?atlOrigin=eyJpIjoiOThhNz... )
Change By: Nemanja Jovanovic ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... )
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();
// log settings
properties.put("hibernate.hbm2ddl.auto", "create");
properties.put("hibernate.show_sql", "true");
// driver settings
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.atlass... that one is I think wrongfully closed as duplicate.
( https://hibernate.atlassian.net/browse/HHH-16517#add-comment?atlOrigin=ey... ) Add Comment ( https://hibernate.atlassian.net/browse/HHH-16517#add-comment?atlOrigin=ey... )
Get Jira notifications on your phone! Download the Jira Cloud app for Android ( https://play.google.com/store/apps/details?id=com.atlassian.android.jira.... ) or iOS ( https://itunes.apple.com/app/apple-store/id1006972087?pt=696495&ct=EmailN... ) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100223- sha1:cdc0af3 )
1 year, 2 months
[JIRA] (HHH-16517) H6: Problems with flush when batch is ON (without @DynamicUpdate)
by Nemanja Jovanovic (JIRA)
Nemanja Jovanovic ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... ) *created* an issue
Hibernate ORM ( https://hibernate.atlassian.net/browse/HHH?atlOrigin=eyJpIjoiNTI4YTJhYjQy... ) / Bug ( https://hibernate.atlassian.net/browse/HHH-16517?atlOrigin=eyJpIjoiNTI4YT... ) HHH-16517 ( https://hibernate.atlassian.net/browse/HHH-16517?atlOrigin=eyJpIjoiNTI4YT... ) H6: Problems with flush when batch is ON (without @DynamicUpdate) ( https://hibernate.atlassian.net/browse/HHH-16517?atlOrigin=eyJpIjoiNTI4YT... )
Issue Type: Bug Affects Versions: 6.2.0, 6.2.1 Assignee: Unassigned Created: 25/Apr/2023 08:56 AM Environment: Tested this issue with 6.2.0.final and 6.2.1.final. JDK 17.0.2 Adoptium (Temurin), HSQL DB used in test case Priority: Major Reporter: Nemanja Jovanovic ( https://hibernate.atlassian.net/secure/ViewProfile.jspa?accountId=557058%... )
Update statement does not get generated when flushing in case we have batching on for following example:
@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();
// log settings
properties.put("hibernate.hbm2ddl.auto", "create");
properties.put("hibernate.show_sql", "true");
// driver settings
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", "");
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());
}
}
After some debugging found quick workaround and potentially source of the problem, removing
if (currentBatch.getKey().equals(key)) {
return currentBatch;
}
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 but that one is I think wrongfully closed as duplicate.
( https://hibernate.atlassian.net/browse/HHH-16517#add-comment?atlOrigin=ey... ) Add Comment ( https://hibernate.atlassian.net/browse/HHH-16517#add-comment?atlOrigin=ey... )
Get Jira notifications on your phone! Download the Jira Cloud app for Android ( https://play.google.com/store/apps/details?id=com.atlassian.android.jira.... ) or iOS ( https://itunes.apple.com/app/apple-store/id1006972087?pt=696495&ct=EmailN... ) This message was sent by Atlassian Jira (v1001.0.0-SNAPSHOT#100223- sha1:cdc0af3 )
1 year, 2 months