package ch.alv.components.data.adapter;
import ch.alv.components.core.beans.Identifiable;
import ch.alv.components.core.search.ValuesProvider;
import ch.alv.components.data.DataLayerException;
import ch.alv.components.data.query.NoSuchQueryProviderException;
import ch.alv.components.data.query.QueryFactory;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* JPA implementation of the {@link DataStoreAdapter} interface.
*
* @since 1.0.0
*/
public class JpaDataStoreAdapter<TYPE extends Identifiable<ID>, ID extends Serializable> implements DataStoreAdapter<TYPE, ID> {
@PersistenceContext
private EntityManager em;
private final QueryFactory queryFactory;
private final Map<String, Object> factoryServices = new HashMap<>();
public JpaDataStoreAdapter(QueryFactory queryFactory) {
this.queryFactory = queryFactory;
}
@PostConstruct
private void init() {
factoryServices.put("entityManager", em);
}
@Override
@Transactional
public TYPE save(TYPE entity, Class<TYPE> entityClass) throws DataLayerException {
if (entity.getId() != null) {
em.find(entityClass, entity.getId());
}
TYPE newEntity = em.merge(entity);
return newEntity;
}
@Override
@Transactional(readOnly = true)
public TYPE find(ID id, Class<TYPE> entityClass) throws DataLayerException {
return em.find(entityClass, id);
}
@Override
@Transactional(readOnly = true)
public List<TYPE> find(String queryName, ValuesProvider params, Class<TYPE> entityClass) throws DataLayerException {
try {
String queryString = queryFactory.createQuery(queryName, params, factoryServices, entityClass);
TypedQuery<TYPE> query = em.createQuery(queryString, entityClass);
return query.getResultList();
} catch (NoSuchQueryProviderException e) {
throw new DataLayerException("Could not execute query with name '" + queryName + "'.", e);
}
}
@Override
@Transactional(readOnly = true)
public List<TYPE> find(Class<TYPE> entityClass) throws DataLayerException {
String name = entityClass.getSimpleName();
String token = name.substring(0, 1).toLowerCase();
return em.createQuery("select " + token + " from " + name + " " + token, entityClass).getResultList();
}
@Override
@Transactional
public void delete(ID id, Class<TYPE> entityClass) throws DataLayerException {
Object entity = em.find(entityClass, id);
if (entity != null) {
em.remove(entity);
}
}
}