Java tutorial
/* * The MIT License * * Copyright 2014 Richard Casar <caricsvk@gmail.com>. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package utils.jpa; import com.fasterxml.jackson.annotation.JsonView; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.persistence.EntityManager; import javax.persistence.NoResultException; import javax.persistence.PersistenceContext; import javax.persistence.Query; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import javax.validation.Valid; import javax.ws.rs.BeanParam; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import utils.enums.EntityFilterType; import utils.enums.OrderType; import utils.jpa.ejb.EntityFilter; import utils.jpa.ejb.TableSearchQuery; public abstract class EntityResource<T> { private final Class<T> entityClass; @PersistenceContext protected EntityManager em; public EntityResource(Class<T> entityClass) { this.entityClass = entityClass; } @POST public void create(@Valid T entity) { em.persist(entity); } @PUT public void edit(@Valid T entity) { em.merge(entity); } @GET @JsonView(JsonViews.Classic.class) @Path("{id}") public T find(@PathParam("id") Long id) { return em.find(entityClass, id); } @GET @JsonView(JsonViews.Detailed.class) @Path("{id}/detail") public T findDetail(@PathParam("id") Long id) { return em.find(entityClass, id); } @DELETE @Path("{id}") public void remove(@PathParam("id") Long id) { em.remove(em.find(entityClass, id)); } @GET @Path("count") public String count(@BeanParam TableSearchQuery tb) { return "{\"count\":" + getAllCount(tb) + "}"; } @GET @Path("entity-field-types") public Map<String, String> types() { HashMap<String, String> types = new HashMap<>(); for (Field field : entityClass.getDeclaredFields()) { types.put(field.getName(), field.getGenericType().toString()); } return types; } /** * * @param tb * @param fieldsSearchBy fields by which is search triggered * @return list of EntityClass's objects */ @GET @JsonView(JsonViews.Classic.class) public List<T> getAll(@BeanParam TableSearchQuery tb, List<String> fieldsSearchBy) { return getAllPriv(tb, fieldsSearchBy); } @GET @JsonView(JsonViews.Detailed.class) @Path("detail") public List<T> getAllDetail(@BeanParam TableSearchQuery tb, List<String> fieldsSearchBy) { return getAllPriv(tb, fieldsSearchBy); } private List<T> getAllPriv(@BeanParam TableSearchQuery tb, List<String> fieldsSearchBy) { CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<T> cq = cb.createQuery(entityClass); Root<T> root = cq.from(entityClass); cq.select(root); //setting order if (tb.getOrderType().equals(OrderType.DESC)) { cq.orderBy(cb.desc(root.get(tb.getOrder()))); } else { cq.orderBy(cb.asc(root.get(tb.getOrder()))); } Query query = tb.createQuery(em, cb, cq, root); if (query == null) { query = createCommonQuery(cb, cq, root, tb, fieldsSearchBy); } if (tb.getOffset() > 0) { query.setFirstResult(tb.getOffset()); } if (tb.getLimit() > 0) { query.setMaxResults(tb.getLimit()); } return query.getResultList(); } public int getAllCount(TableSearchQuery tb) { return getAllCount(tb, null); } public int getAllCount(TableSearchQuery tb, List<String> fieldsSearchBy) { CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery cq = cb.createQuery(); Root<T> root = cq.from(entityClass); cq.select(cb.count(root)); Query query = tb.createQuery(em, cb, cq, root); if (query == null) { query = createCommonQuery(cb, cq, root, tb, fieldsSearchBy); } try { return ((Long) query.getSingleResult()).intValue(); } catch (NoResultException ex) { return 0; } } private Query createCommonQuery(CriteriaBuilder cb, CriteriaQuery cq, Root root, TableSearchQuery tb, List<String> fieldsSearchBy) { List<Predicate> orPredicates = new ArrayList<>(); List<Predicate> andPredicates = new ArrayList<>(); //setting where conditions if (fieldsSearchBy != null && !fieldsSearchBy.isEmpty()) { for (String field : fieldsSearchBy) { if (tb.getFilter() != null && !tb.getFilter().isEmpty()) { orPredicates.add(cb.like(cb.lower(cb.concat(root.<String>get(field), "::text")), "%" + tb.getFilter().toLowerCase() + "%")); } } } else { List<Field> filterColumns = SearchFields.getAll(entityClass); for (Field field : filterColumns) { EntityFilter entityFilter = tb.getFilterParameters().get(field.getName()); if ((Collection.class.isAssignableFrom(field.getType()) || List.class.isAssignableFrom(field.getType())) && (entityFilter == null || !entityFilter.getEntityFilterType().equals(EntityFilterType.EMPTY))) { continue; } if (entityFilter == null) { if (tb.getFilter() != null && !tb.getFilter().isEmpty()) { orPredicates.add(cb.like(cb.lower(cb.concat(root.<String>get(field.getName()), "::text")), "%" + tb.getFilter().toLowerCase() + "%")); } continue; } switch (entityFilter.getEntityFilterType()) { case WILDCARD: andPredicates.add(cb.like(cb.lower(cb.concat(root.<String>get(field.getName()), "::text")), "%" + entityFilter.getValue().toLowerCase() + "%")); break; case EMPTY: if (Collection.class.isAssignableFrom(field.getType()) || List.class.isAssignableFrom(field.getType())) { andPredicates.add(entityFilter.getValue().equals("hide") ? cb.isEmpty(root.<Collection>get(field.getName())) : cb.isNotEmpty(root.<Collection>get(field.getName()))); } else { andPredicates.add( entityFilter.getValue().equals("hide") ? root.<Object>get(field.getName()).isNull() : root.<Object>get(field.getName()).isNotNull()); } break; case MIN_MAX: andPredicates.add(cb.greaterThanOrEqualTo(root.<Date>get(field.getName()), new Date(Long.valueOf(entityFilter.getValues().get(0))))); andPredicates.add(cb.lessThanOrEqualTo(root.<Date>get(field.getName()), new Date(Long.valueOf(entityFilter.getValues().get(1))))); break; case MIN: andPredicates.add(cb.greaterThanOrEqualTo(root.<Date>get(field.getName()), new Date(Long.valueOf(entityFilter.getValue())))); break; case MAX: andPredicates.add(cb.lessThanOrEqualTo(root.<Date>get(field.getName()), new Date(Long.valueOf(entityFilter.getValue())))); break; } } } if (orPredicates.size() > 0 && andPredicates.size() > 0) { cq.where(cb.or(cb.or(orPredicates.toArray(new Predicate[0])), cb.and(andPredicates.toArray(new Predicate[0])))); } else if (orPredicates.size() > 0) { cq.where(cb.or(orPredicates.toArray(new Predicate[0]))); } else if (andPredicates.size() > 0) { cq.where(cb.and(andPredicates.toArray(new Predicate[0]))); } return em.createQuery(cq); } }