We're updating the issue view to help you get more done. 

When 2LC enabled, flush session and then refresh entity cause dirty read in another session / transaction

Description

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 @Entity @Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "item") public class CacheableItem { private Long id; private String name; public CacheableItem() { } public CacheableItem(String name) { this.name = name; } @Id @GeneratedValue(generator = "increment") @GenericGenerator(name = "increment", strategy = "increment") public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }

Test case:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 @Test public void testUpdateAndRefresh() { // prepare data Session s = openSession(); s.beginTransaction(); CacheableItem item = new CacheableItem( "item" ); s.save( item ); s.getTransaction().commit(); s.close(); Session s1 = openSession(); s1.beginTransaction(); CacheableItem item1 = s1.get( CacheableItem.class, item.getId() ); // into persistent context item1.setName( "some name" ); s1.flush(); s1.clear(); // clear persistent context s1.refresh( item1 ); item1 = s1.get( CacheableItem.class, item.getId() ); assertEquals( "some name", item1.getName() ); // open another session Session s2 = sessionFactory().openSession(); try { s2.beginTransaction(); CacheableItem item2 = s2.get( CacheableItem.class, item.getId() ); assertEquals( "item", item2.getName() ); } catch (PessimisticLockException expected) { // expected if MVCC is not enabled } catch (Exception e) { throw e; } finally { s2.getTransaction().rollback(); s2.close(); } s1.getTransaction().rollback(); s1.close(); }

hibernate.properties

1 2 3 4 5 hibernate.dialect org.hibernate.dialect.H2Dialect hibernate.connection.driver_class org.h2.Driver hibernate.connection.url jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=true hibernate.connection.username sa ...

note: MVCC should be enabled in connection url

In fact, this issue does not only replicate for refresh only, but every time we evict from the cache and reload an uncommitted entry:

1 2 3 s1.getSessionFactory().getCache().evictEntity( CacheableItem.class, item1.getId() ); s1.evict( item1 ); s1.get(CacheableItem.class, item1.getId());

So, it must be addresses such that once an entry is locked, the locked is not released when the entry is evicted.

Environment

h2 with MVCC

Status

Assignee

Vlad Mihalcea

Reporter

Zhenlei Huang

Fix versions

backPortable

None

Suitable for new contributors

None

Requires Release Note

None

backportDecision

None

Components

Affects versions

5.1.1
5.0.9
4.2.21

Priority

Major