Pārlūkot izejas kodu

[ci fw-only Java/dropwizard] Implement updates batch and manual transaction handling. Fixes #3224 (#3232)

* Ignore build artifact

* use JDBC batch and manual transaction processing for updates

* Update README.md
Radoslav Petrov 7 gadi atpakaļ
vecāks
revīzija
49b1954360

+ 1 - 0
.gitignore

@@ -89,3 +89,4 @@ nimcache
 
 #don't ignore merge request templates
 !.github/
+dependency-reduced-pom.xml

+ 2 - 0
frameworks/Java/dropwizard/README.md

@@ -37,6 +37,8 @@ Each implementation has its own set of `.yml` configuration file and shell scrip
 
 ### (MySQL or PostgreSQL) and Hibernate
 
+The `Updates` test is using JDBC batch updates and manual transaction handling.
+
  * [DB, Queries and Updates](src/main/java/com/example/helloworld/db/hibernate/WorldHibernateImpl.java)
  * [Fortune](src/main/java/com/example/helloworld/db/hibernate/FortuneHibernateImpl.java)
 

+ 3 - 0
frameworks/Java/dropwizard/hello-world-mysql.yml

@@ -34,6 +34,9 @@ database:
   properties:
     charSet: UTF-8
     hibernate.dialect: org.hibernate.dialect.MySQLDialect
+    # enable batch updates in Hibernate
+    hibernate.jdbc.batch_size: 30
+    hibernate.jdbc.batch_versioned_data: true
 
   # the maximum amount of time to wait on an empty pool before throwing an exception
   maxWaitForConnection: 1s

+ 3 - 0
frameworks/Java/dropwizard/hello-world-postgres.yml

@@ -33,6 +33,9 @@ database:
   properties:
     charSet: UTF-8
     hibernate.dialect: org.hibernate.dialect.PostgreSQL9Dialect
+    # enable batch updates in Hibernate
+    hibernate.jdbc.batch_size: 30
+    hibernate.jdbc.batch_versioned_data: true
 
   # the maximum amount of time to wait on an empty pool before throwing an exception
   maxWaitForConnection: 1s

+ 9 - 8
frameworks/Java/dropwizard/src/main/java/com/example/helloworld/HelloWorldService.java

@@ -1,5 +1,14 @@
 package com.example.helloworld;
 
+import io.dropwizard.Application;
+import io.dropwizard.db.DataSourceFactory;
+import io.dropwizard.hibernate.HibernateBundle;
+import io.dropwizard.setup.Bootstrap;
+import io.dropwizard.setup.Environment;
+import io.dropwizard.views.ViewBundle;
+
+import java.net.UnknownHostException;
+
 import com.example.helloworld.config.HelloWorldConfiguration;
 import com.example.helloworld.db.hibernate.FortuneHibernateImpl;
 import com.example.helloworld.db.hibernate.WorldHibernateImpl;
@@ -9,14 +18,6 @@ import com.example.helloworld.resources.FortuneResource;
 import com.example.helloworld.resources.JsonResource;
 import com.example.helloworld.resources.TextResource;
 import com.example.helloworld.resources.WorldResource;
-import io.dropwizard.Application;
-import io.dropwizard.db.DataSourceFactory;
-import io.dropwizard.hibernate.HibernateBundle;
-import io.dropwizard.setup.Bootstrap;
-import io.dropwizard.setup.Environment;
-import io.dropwizard.views.ViewBundle;
-
-import java.net.UnknownHostException;
 
 public class HelloWorldService extends Application<HelloWorldConfiguration> {
 

+ 44 - 25
frameworks/Java/dropwizard/src/main/java/com/example/helloworld/db/hibernate/WorldHibernateImpl.java

@@ -3,34 +3,53 @@ package com.example.helloworld.db.hibernate;
 import io.dropwizard.hibernate.AbstractDAO;
 
 import org.hibernate.SessionFactory;
+import org.hibernate.Transaction;
 
 import com.example.helloworld.db.WorldDAO;
 import com.example.helloworld.db.model.World;
 import com.example.helloworld.resources.Helper;
 
 public class WorldHibernateImpl extends AbstractDAO<World> implements WorldDAO {
-    public WorldHibernateImpl(SessionFactory factory) {
-        super(factory);
-    }
-
-    public World findById(int id) {
-        return get(id);
-    }
-
-    public World findAndModify(int id, int newRandomNumber) {
-        final World world = get(id);
-        world.setRandomNumber(newRandomNumber);
-        return persist(world);
-    }
-
-    @Override
-    public World[] updatesQueries(int totalQueries) {
-        final World[] worlds = new World[totalQueries];
-        //TODO implement write batching
-        for (int i = 0; i < totalQueries; i++) {
-                worlds[i] = findAndModify(Helper.randomWorld(), Helper.randomWorld());
-        }
-        return worlds;
-    }
-
-}
+	public WorldHibernateImpl(SessionFactory factory) {
+		super(factory);
+	}
+
+	public World findById(int id) {
+		return get(id);
+	}
+
+	public World findAndModify(int id, int newRandomNumber) {
+		final World world = get(id);
+		world.setRandomNumber(newRandomNumber);
+		return persist(world);
+	}
+
+	/**
+	 * Using manual transaction handling and JDBC batch updates
+	 */
+	@Override
+	public World[] updatesQueries(int totalQueries) {
+		final World[] worlds = new World[totalQueries];
+		Transaction txn = null;
+
+		try {
+			txn = currentSession().beginTransaction();
+
+			// using write batching. See the data source properties provided in the configuration .yml file
+			for (int i = 0; i < totalQueries; i++) {
+				worlds[i] = findAndModify(Helper.randomWorld(), Helper.randomWorld());
+			}
+			currentSession().flush();
+			currentSession().clear();
+			txn.commit();
+		} catch (RuntimeException e) {
+			if (txn != null && txn.isActive())
+				txn.rollback();
+			throw e;
+		}
+		// The cleaning of the session should happen in the dropwizard provided aspect code
+
+		return worlds;
+	}
+
+}

+ 2 - 2
frameworks/Java/dropwizard/src/main/java/com/example/helloworld/resources/WorldResource.java

@@ -23,14 +23,14 @@ public class WorldResource {
 	}
 	
 	@GET
-	@UnitOfWork(transactional = false) // Needed only for Hibernate - not for Mongo or JDBI
+	@UnitOfWork(transactional = false, readOnly = true) // Needed only for Hibernate - not for Mongo or JDBI
 	public Object db() {
 		return worldDAO.findById(Helper.randomWorld());
 	}
 	
 	@GET
 	@Path("/query")
-	@UnitOfWork(transactional = false) // Needed only for Hibernate - not for Mongo or JDBI
+	@UnitOfWork(transactional = false,  readOnly = true) // Needed only for Hibernate - not for Mongo or JDBI
 	public Object dbTest(@QueryParam("queries") String queries) {
 		int totalQueries = Helper.getQueries(queries); // Optional check is done inside
 		final World[] worlds = new World[totalQueries];