|
@@ -2,7 +2,8 @@ package hello;
|
|
|
|
|
|
import hello.domain.World;
|
|
import hello.domain.World;
|
|
|
|
|
|
-import java.util.Optional;
|
|
|
|
|
|
+import java.util.Arrays;
|
|
|
|
+import java.util.Comparator;
|
|
import java.util.concurrent.Callable;
|
|
import java.util.concurrent.Callable;
|
|
import java.util.concurrent.ExecutionException;
|
|
import java.util.concurrent.ExecutionException;
|
|
import java.util.concurrent.Future;
|
|
import java.util.concurrent.Future;
|
|
@@ -10,6 +11,8 @@ import java.util.concurrent.ThreadLocalRandom;
|
|
|
|
|
|
import javax.inject.Inject;
|
|
import javax.inject.Inject;
|
|
import javax.inject.Singleton;
|
|
import javax.inject.Singleton;
|
|
|
|
+import javax.persistence.EntityManager;
|
|
|
|
+import javax.persistence.EntityManagerFactory;
|
|
import javax.ws.rs.GET;
|
|
import javax.ws.rs.GET;
|
|
import javax.ws.rs.Path;
|
|
import javax.ws.rs.Path;
|
|
import javax.ws.rs.Produces;
|
|
import javax.ws.rs.Produces;
|
|
@@ -17,7 +20,6 @@ import javax.ws.rs.QueryParam;
|
|
import javax.ws.rs.core.MediaType;
|
|
import javax.ws.rs.core.MediaType;
|
|
|
|
|
|
import org.hibernate.Session;
|
|
import org.hibernate.Session;
|
|
-import org.hibernate.SessionFactory;
|
|
|
|
import org.hibernate.Transaction;
|
|
import org.hibernate.Transaction;
|
|
|
|
|
|
@Singleton
|
|
@Singleton
|
|
@@ -25,12 +27,13 @@ import org.hibernate.Transaction;
|
|
@Path("/db")
|
|
@Path("/db")
|
|
public class WorldResource {
|
|
public class WorldResource {
|
|
@Inject
|
|
@Inject
|
|
- private SessionFactory sessionFactory;
|
|
|
|
|
|
+ private EntityManagerFactory emf;
|
|
|
|
|
|
@GET
|
|
@GET
|
|
public Object db() throws InterruptedException, ExecutionException {
|
|
public Object db() throws InterruptedException, ExecutionException {
|
|
Callable<World> callable = () -> {
|
|
Callable<World> callable = () -> {
|
|
- Session session = sessionFactory.openSession();
|
|
|
|
|
|
+ EntityManager em = emf.createEntityManager();
|
|
|
|
+ Session session = em.unwrap(Session.class);
|
|
session.setDefaultReadOnly(true);
|
|
session.setDefaultReadOnly(true);
|
|
try {
|
|
try {
|
|
return (World) session.byId(World.class).load(randomWorld());
|
|
return (World) session.byId(World.class).load(randomWorld());
|
|
@@ -50,7 +53,7 @@ public class WorldResource {
|
|
final World[] worlds = new World[queries];
|
|
final World[] worlds = new World[queries];
|
|
|
|
|
|
Callable<World[]> callable = () -> {
|
|
Callable<World[]> callable = () -> {
|
|
- Session session = sessionFactory.openSession();
|
|
|
|
|
|
+ Session session = emf.createEntityManager().unwrap(Session.class);
|
|
session.setDefaultReadOnly(true);
|
|
session.setDefaultReadOnly(true);
|
|
try {
|
|
try {
|
|
for (int i = 0; i < queries; i++) {
|
|
for (int i = 0; i < queries; i++) {
|
|
@@ -73,19 +76,29 @@ public class WorldResource {
|
|
final World[] worlds = new World[queries];
|
|
final World[] worlds = new World[queries];
|
|
|
|
|
|
Callable<World[]> callable = () -> {
|
|
Callable<World[]> callable = () -> {
|
|
- Session session = sessionFactory.openSession();
|
|
|
|
|
|
+ Session session = emf.createEntityManager().unwrap(Session.class);
|
|
session.setDefaultReadOnly(false);
|
|
session.setDefaultReadOnly(false);
|
|
Transaction txn = session.beginTransaction();
|
|
Transaction txn = session.beginTransaction();
|
|
|
|
|
|
try {
|
|
try {
|
|
// using write batching. See the data source properties provided
|
|
// using write batching. See the data source properties provided
|
|
// in the configuration file
|
|
// in the configuration file
|
|
|
|
+
|
|
|
|
+ // 1. Read and update the entities from the DB
|
|
for (int i = 0; i < queries; i++) {
|
|
for (int i = 0; i < queries; i++) {
|
|
final World world = (World) session.byId(World.class).load(randomWorld());
|
|
final World world = (World) session.byId(World.class).load(randomWorld());
|
|
- world.randomNumber = randomWorld();
|
|
|
|
- session.persist(world);
|
|
|
|
|
|
+ world.setRandomNumber(randomWorld());
|
|
worlds[i] = world;
|
|
worlds[i] = world;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ // 2. Sort the array to prevent transaction deadlock in the DB
|
|
|
|
+ Arrays.sort(worlds, Comparator.comparingInt(World::getId));
|
|
|
|
+
|
|
|
|
+ // 3. Actually save the entities
|
|
|
|
+ for (int i = 0; i < worlds.length; i++) {
|
|
|
|
+ session.persist(worlds[i]);
|
|
|
|
+ }
|
|
|
|
+
|
|
session.flush();
|
|
session.flush();
|
|
session.clear();
|
|
session.clear();
|
|
txn.commit();
|
|
txn.commit();
|