Java JPA: Separating transaction control and logic in J2SE environment

At the beginning

Try to separate transaction control and logic in J2SE environment Does not use any J2EE application server container or Spring features

Premise

The execution environment is as follows

Thing you want to do

I made a logic to "register xml file in postgresql" in Jouhousyori.java. I think the textbook example is as follows

Jouhousyori.java


	public void execute() throws Exception{
		EntityManagerFactory factory = Persistence.createEntityManagerFactory("myUnitInPersistenceXML");
		EntityManager em = factory.createEntityManager();		
		EntityTransaction entityTransaction = em.getTransaction();
		JouhousyoriEntity entity = new JouhousyoriEntity();
		String xml = new String(Files.readAllBytes(Paths.get(getPath())));
		entity .setText(xml);
		em.persist(entity);
		entityTransaction.commit();
	}

Problems with this implementation

EM acquisition process is redundant

First, the process of getting an EM is too annoying. Even if it is a write-down program, it is troublesome to write the EM acquisition process every time the number of classes and methods that process the DB increases.

I want to take control of transaction start, end, and rollback

Next, if you put control of transaction start, end, and rollback in the logic class, the readability of the logic class seems to be significantly reduced. I think people have different tastes here, but I want to separate logic and transaction control.

To solve the above implementation problems

Use Interceptor

If you want to process common logic in Java, you can use a function called Interceptor. About Interceptor https://blogs.yahoo.co.jp/dk521123/33226901.html There is a concrete Java implementation example in Also, for the class diagram and brief explanation of the above site https://afternoon-garden-70542.herokuapp.com/diarydetails/show/details/?id=76 I put it on, so please also

Various mounting image

Class diagram

image.png

Explanation of class diagram

The following processing is performed by TransactionInterceptor

--Starting and ending a transaction by EM --Set an instance of EM in the Jouhousyori class

By writing the transaction and EM operation processing on the TransactionInterceptor side, the Jouhousyori class can concentrate on the processing that it originally wants to do, "read the xml file and perform persistence processing on the em". By the way, it seems that something like DI has been realized.

Source after problem solving

Jouhousyori.java


package logic;

import java.nio.file.Files;
import java.nio.file.Paths;

import javax.persistence.EntityManager;

import entity.JouhousyoriEntity;

public class Jouhousyori implements Logic{
	
	private EntityManager em;
	private String path;
	
	@Override
	public void execute() throws Exception{
		JouhousyoriEntity entity = new JouhousyoriEntity();
		String xml = new String(Files.readAllBytes(Paths.get(getPath())));
		entity .setText(xml);
		em.persist(entity);
	}
	public EntityManager getEm() {
		return em;
	}
	public void setEm(EntityManager em) {
		this.em = em;
	}
	public String getPath() {
		return path;
	}
	public void setPath(String path) {
		this.path = path;
	}
}

TransactionIntercepter.java


package proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

public class TransactionIntercepter  implements InvocationHandler {
	   Object target;

	   private TransactionIntercepter(Object target) {
	      this.target = target;
	   }

	   @SuppressWarnings({ "rawtypes", "unchecked" })
	   public static <T> T getProxyInstance(T instance) {
		   Class<? extends Object> clazz = instance.getClass();
	      //List of interfaces implemented by the target class
		   Class[] classes = clazz.getInterfaces();
		   TransactionIntercepter intercepter = new TransactionIntercepter(instance);
		   T proxyInstance = (T) Proxy.newProxyInstance(clazz.getClassLoader(), classes, intercepter);
		   return proxyInstance;
	   }

	   @Override
	   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		   EntityManagerFactory factory = Persistence.createEntityManagerFactory("myUnitInPersistenceXML");
		   EntityManager em = factory.createEntityManager();		
		   EntityTransaction entityTransaction = em.getTransaction();
		   entityTransaction.begin();

		   Object result=null;
		   try {
			  //Set an instance of EntityManater
			  target.getClass().getDeclaredMethod("setEm",EntityManager.class).invoke(target,em);
		      //Call the actual code
			  result = method.invoke(this.target, args);
		   }catch(Exception e) {
			   e.printStackTrace();
			  entityTransaction.rollback();;
			  throw e;
		   }
		   entityTransaction.commit();
		   return result;
	   }
}

LogicTest.java


import org.junit.jupiter.api.Test;

import logic.Jouhousyori;
import logic.Logic;
import proxy.TransactionIntercepter;

class LogicTest {

	@Test
	void testParsePDF() throws Exception{
		Jouhousyori target = new Jouhousyori();
		target.setPath("C:\\java\\workspace\\jyouhousyori2\\pdf\\xml\\2018h30h_sc_am2_qs.pdf.xml");
		Logic targetClass = TransactionIntercepter.getProxyInstance(target);
		targetClass.execute();
	}
}

Recommended Posts

Java JPA: Separating transaction control and logic in J2SE environment
What happened in "Java 8 to Java 11" and how to build an environment
JavaFX environment construction in Java 13
☾ Java / Iterative statement and iterative control statement
Java Spring environment in vs Code
Encoding and Decoding example in Java
StringBuffer and StringBuilder Class in Java
Notes on signal control in Java
Understanding equals and hashCode in Java
JPA (Java Persistence API) in Eclipse
Hello world in Java and Gradle
Java container performance degradation in Menicoa environment
Difference between final and Immutable in Java
[Java] for Each and sorted in Lambda
Play Framework 2.6 (Java) environment construction in Eclipse
What is Java and Development Environment (MAC)
Arrylist and linked list difference in java
Program PDF headers and footers in Java
Learn Flyweight patterns and ConcurrentHashMap in Java
Java Direction in C ++ Design and Evolution
Page number logic and reference code (java)
Java to C and C to Java in Android Studio
Reading and writing gzip files in Java
Difference between int and Integer in Java
Java application development environment created in VM environment
Discrimination of Enums in Java 7 and above
Install Docker and create Java runtime environment
Minimal Java environment construction and Hello World
Sample code for DB control by declarative transaction in Spring Boot + Spring Data JPA