JPA made small revolution among ORM tools and EJB 2 world. Easy to use, simple unified way to develop you model and services. After i used it in few projects, i have found that all JPA services are very similar, so this is a simple try to generalize or template them.
This can be for example simple abstract interface for all:
And abstract implementation class look like this:
Note that even JpaServiceImpl doesnt have any abstract method it is still set to be abstract class. I did this just to enforce that for each entity there is its own implementation of service, since we always going to need few extra special methods for them.
ReflactionUtil its a small class to resolve model beeing used in service and to get id value for it, and looks like this
After that you extend interface like this
And we can extend implementation service like this
Tell me do you use something similar or?
This can be for example simple abstract interface for all:
package test.service; import java.util.List; public abstract interface JpaService<T> { void save(T t); T find(Long id); void remove(Long id); List<T> findAll(); long count(); }
And abstract implementation class look like this:
package test.service.impl; import java.util.List; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.Query; import org.apache.log4j.Logger; import test.service.JpaService; public abstract class JpaServiceImpl<T> implements JpaService<T>{ /** Logger. */ private static final Logger log = Logger.getLogger(JpaServiceImpl.class); /** Entity manager. */ @PersistenceContext protected EntityManager em; /** Reflection util */ protected ReflectionUtil reflectionUtil = ReflectionUtil.get(); /** * Save entity. */ //@Transactional(readOnly = false, propagation=Propagation.REQUIRED, isolation=Isolation.DEFAULT) public void save(T t) { log.debug("JpaServiceImpl-Save"); if (reflectionUtil.getIdValue(t) == null) { // new log.debug("New"); em.persist(t); } else { // update log.debug("Update"); em.merge(t); } } /** * Remove entity. */ //@Transactional(readOnly = false, propagation=Propagation.REQUIRED) public void remove(Long id) { log.debug("remove: " + id); T t = (T) find(id); if (t != null) { log.debug("found try to remove"); em.remove(t); log.debug("removed"); } } /** * Find entity. * */ @SuppressWarnings( { "unchecked" }) //@Transactional(readOnly = false, propagation=Propagation.REQUIRED) public T find(Long id) { log.debug("find!!" + id); return (T) em.find(reflectionUtil.getModelClass(this), id); } /** * Find all entities. */ @SuppressWarnings("unchecked") //@Transactional(readOnly = true, propagation=Propagation.REQUIRED) public List<T> findAll() { log.debug("JpaServiceImpl-findAll"); String queryStr = new StringBuilder().append("select t FROM ").append( reflectionUtil.getModelClass(this).getName()).append(" t").toString(); //getSimpleName() log.debug(queryStr); Query query = em.createQuery(queryStr); return query.getResultList(); } public long count() { String queryStr = new StringBuilder().append("SELECT COUNT(t) FROM ").append(reflectionUtil.getModelClass(this).getName()).append(" t").toString(); Query query = em.createQuery(queryStr); return (Long) query.getSingleResult(); } }
Note that even JpaServiceImpl doesnt have any abstract method it is still set to be abstract class. I did this just to enforce that for each entity there is its own implementation of service, since we always going to need few extra special methods for them.
ReflactionUtil its a small class to resolve model beeing used in service and to get id value for it, and looks like this
package test.service.impl; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.util.HashMap; import java.util.Map; import javax.persistence.Id; import org.apache.log4j.Logger; public class ReflectionUtil { /** Logger */ private static final Logger log = Logger.getLogger(ReflectionUtil.class); /** Cache Map of scanned obj */ private Map<String, Object> map = new HashMap<String, Object>(); /** single instance */ private static ReflectionUtil instance; private ReflectionUtil() {} public static ReflectionUtil get() { if (instance == null) { instance = new ReflectionUtil(); } return instance; } public Class getModelClass(Class cls) { String key = "modelClass-" + cls.getName(); if (!map.containsKey(key)) { Class<?> modelClass = (Class<?>) (((ParameterizedType) (cls .getGenericSuperclass())).getActualTypeArguments()[0]); map.put(key, modelClass); } return (Class<?>) map.get(key); } public Class<?> getModelClass(Object obj) { return getModelClass(obj.getClass()); } public Object getIdValue(Object t) { try { Method method = getIdMethod(t); return (Object) method.invoke(t, null); } catch (Exception e) { log.error(e); return null; } } private Method getIdMethod(Object t) throws SecurityException, NoSuchMethodException { String key = t.getClass().getName(); //key + "-method" if (map.get(key + "-method") == null) { String methodNameForId = getMethodNameForId(t); log.debug("methodName: " + methodNameForId); Method m = t.getClass().getMethod(methodNameForId, null); map.put(key + "-method", m); } return (Method) map.get(key + "-method"); } public String getPropertyNameForId(Object t){ return getMethodOrPropertyNameForId(t, "-propertyNameForId"); } public String getMethodNameForId(Object t){ return getMethodOrPropertyNameForId(t, "-methodNameForId"); } private String getMethodOrPropertyNameForId(Object t, String subKey){ String key = t.getClass().getName(); if (map.get(key) == null || map.get(key + subKey) == null ) { Class<?> modelClass = getModelClass(t); // set methodNameForId // finds getter name for field which has id annotation for (Field f : modelClass.getDeclaredFields()) { if (f.isAnnotationPresent(Id.class)) { String propertyNameForId = f.getName(); map.put(key + "-propertyNameForId", propertyNameForId); String methodNameForId = "get" + capitalize(f.getName()); map.put(key + "-methodNameForId", methodNameForId); break; } } } return (String) map.get(key + subKey); } /** Capitalize string */ private String capitalize(String str) { return str.substring(0, 1).toUpperCase() + str.substring(1, str.length()); } }
After that you extend interface like this
package test.service; import java.util.List; import test.model.Person; public interface PersonService extends JpaService<Person> { List<Person> findByLastName(String name); }
And we can extend implementation service like this
package test.service.impl; import java.util.List; import javax.persistence.Query; import test.model.Person; import test.service.PersonService; public class PersonServiceImpl extends JpaServiceImpl<Person> implements PersonService { public List<Person> findByLastName(String name) { Query query = em.createQuery("SELECT p FROM " + reflectionUtil.getModelClass(this).getName() + " p WHERE p.lastName = '" + name + "' "); return query.getResultList(); } }
Tell me do you use something similar or?
Comments
If anyone looking for Java training in Bangalore i suggest Apponix Technologies, they provide best Java training. For more information visit : https://www.apponix.com/Java-Institute/Java-Training-Institute-in-Bangalore.html