I want to test whether the FooRepository.lock() works, after someone called the lock(), others calling it should be wait.
The following is my best try, it doesn't work. I believe the reason is both entityManger and fooRepository are participating in the same transaction.
How to call the lock() from another transaction? Or any suggestion for unit-testing the pessimistic lock? Thanks!!
FooRepositoryTest:
package com.example.demo;
import java.util.UUID;
import javax.persistence.LockModeType;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@DataJpaTest
public class FooRepositoryTest {
@Autowired
private TestEntityManager entityManager;
@Autowired
private FooRepository fooRepository;
@Test
public void lockTest() {
// given
Foo foo = new Foo();
foo.setName("foo-name");
UUID fooId = fooRepository.save(foo).getFooId();
entityManager.flush();
entityManager.clear();
// when
Foo savedFoo = fooRepository.findOne(fooId);
fooRepository.lock(savedFoo);
// then
// I want something like this to be lock wait,
// something to confirm the above fooRepository.lock() work
entityManager.getEntityManager().lock(savedFoo, LockModeType.PESSIMISTIC_WRITE);
}
}
class Foo:
package com.example.demo;
import java.util.UUID;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Foo {
@Id
@GeneratedValue
private UUID fooId;
private String name;
public UUID getFooId() {
return fooId;
}
public void setFooId(UUID fooId) {
this.fooId = fooId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class FooApplication:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class FooApplication {
public static void main(String[] args) {
SpringApplication.run(FooApplication.class, args);
}
}
class FooRepository:
package com.example.demo;
import java.util.UUID;
import org.springframework.data.jpa.repository.JpaRepository;
public interface FooRepository extends JpaRepository<Foo, UUID>, FooRepositoryCustom {
}
class FooRepositoryCustom:
package com.example.demo;
public interface FooRepositoryCustom {
public void lock(Foo foo);
}
class FooRepositoryImpl:
package com.example.demo;
import javax.persistence.EntityManager;
import javax.persistence.LockModeType;
import org.springframework.beans.factory.annotation.Autowired;
public class FooRepositoryImpl implements FooRepositoryCustom {
@Autowired
private EntityManager entityManager;
@Override
public void lock(Foo foo) {
entityManager.lock(foo, LockModeType.PESSIMISTIC_WRITE);
}
}