├── src └── main │ ├── resources │ └── META-INF │ │ ├── beans.xml │ │ └── persistence.xml │ ├── webapp │ ├── WEB-INF │ │ ├── faces-config.xml │ │ └── web.xml │ └── index.xhtml │ └── java │ └── com │ └── rodrigouchoa │ └── generic │ └── dao │ ├── entity │ ├── Order.java │ ├── BaseEntity.java │ ├── Invoice.java │ └── Customer.java │ ├── util │ ├── ResourcesProducer.java │ └── InitDB.java │ ├── action │ └── IndexAction.java │ ├── GenericDaoHibernate.java │ └── GenericDaoJpa.java ├── README.md └── pom.xml /src/main/resources/META-INF/beans.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/faces-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/java/com/rodrigouchoa/generic/dao/entity/Order.java: -------------------------------------------------------------------------------- 1 | package com.rodrigouchoa.generic.dao.entity; 2 | 3 | /** 4 | *

5 | * The ordering of a collection of objects. 6 | *

7 | * 8 | * 12 | */ 13 | public enum Order { 14 | 15 | ASC, DESC; 16 | 17 | 18 | public boolean isAscOrder() { 19 | return ASC.equals(this); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/rodrigouchoa/generic/dao/util/ResourcesProducer.java: -------------------------------------------------------------------------------- 1 | package com.rodrigouchoa.generic.dao.util; 2 | 3 | import javax.enterprise.context.ApplicationScoped; 4 | import javax.enterprise.inject.Produces; 5 | import javax.persistence.EntityManager; 6 | import javax.persistence.PersistenceContext; 7 | 8 | @ApplicationScoped 9 | public class ResourcesProducer { 10 | 11 | @Produces 12 | @PersistenceContext( unitName = "generic-dao") 13 | private EntityManager entityManager; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/webapp/index.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | JSF Page 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 |
18 |
19 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | org.h2.server.web.DbStarter 10 | 11 | 12 | 13 | Faces Servlet 14 | javax.faces.webapp.FacesServlet 15 | 1 16 | 17 | 18 | Faces Servlet 19 | *.xhtml 20 | 21 | 22 | 23 | index.xhtml 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/persistence.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | false 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ##Sample Java EE 7 Project with a generic DAO implementation 2 | 3 | Read the blog post: 4 | - http://rodrigouchoa.wordpress.com/2014/09/26/generic-dao-example/ (english version) 5 | - http://rodrigouchoa.wordpress.com/2014/09/26/exemplo-dao-generico/ (versão em português) 6 | 7 | This is just some code you can play with. I've tested this against JBoss WildFly 8.1, but 8 | it should run in any Java EE 7 compliant server with minor maven libs adjusments. 9 | 10 | The application comes with its own embedded H2 database, which is started up and shutdown 11 | automatically. Each time you run the app, the database is initialized from scratch. 12 | 13 | To get this running you need: 14 | - JDK 8 15 | - JBoss WildFly 8.1.0 16 | - An IDE of your choice (or none) 17 | - If you intend to use a server different than JBoss 8.1 (WildFly), 18 | please remember you probably you'll need to register the H2 Database JDBC Driver. 19 | - Remember to use **UTF-8 encoding**! 20 | - Deploy the app, run http://localhost:8080/generic-dao and you should get the main page that 21 | contains a simple button to trigger the tests. Browse the code to get a feeling for what it does. 22 | 23 | 24 | *Please note that running JDK 8 and JBoss WildFly in Eclipse might need some tweaks.* 25 | 26 | -------------------------------------------------------------------------------- /src/main/java/com/rodrigouchoa/generic/dao/entity/BaseEntity.java: -------------------------------------------------------------------------------- 1 | package com.rodrigouchoa.generic.dao.entity; 2 | 3 | import java.io.Serializable; 4 | 5 | import org.hibernate.proxy.HibernateProxyHelper; 6 | 7 | /** 8 | * Base class for all JPA entities. 9 | * 10 | * @author Rodrigo Uchôa (http://rodrigouchoa.wordpress.com) 11 | * 12 | */ 13 | public abstract class BaseEntity { 14 | 15 | 16 | /** 17 | * This method should return the primary key. 18 | * 19 | * @return 20 | */ 21 | public abstract T getId(); 22 | 23 | /* As a starting point, we provide a basic mean for entities 24 | * to test for equality using their "id". 25 | * 26 | * Please note that THIS IS NOT ALWAYS ACCEPTABLE since newly generated 27 | * ids might break Set/Collection semantics. Please refer to the documentarion 28 | * before doing something like this. 29 | * 30 | */ 31 | @SuppressWarnings("unchecked") 32 | @Override 33 | public boolean equals(Object obj) { 34 | if (this == obj) { 35 | return true; 36 | } 37 | if (!(obj instanceof BaseEntity)) { 38 | return false; 39 | } 40 | if (getId() == null || ((BaseEntity) obj).getId() == null) { 41 | return false; 42 | } 43 | if (!getId().equals(((BaseEntity) obj).getId())) { 44 | return false; 45 | } 46 | if (!HibernateProxyHelper.getClassWithoutInitializingProxy(obj) 47 | .isAssignableFrom(this.getClass())) { 48 | return false; 49 | } 50 | return true; 51 | } 52 | 53 | @Override 54 | public int hashCode() { 55 | return getId() == null ? super.hashCode() : getId().hashCode(); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/rodrigouchoa/generic/dao/util/InitDB.java: -------------------------------------------------------------------------------- 1 | package com.rodrigouchoa.generic.dao.util; 2 | 3 | import java.math.BigDecimal; 4 | 5 | import javax.annotation.PostConstruct; 6 | import javax.ejb.Singleton; 7 | import javax.ejb.Startup; 8 | import javax.inject.Inject; 9 | 10 | import com.rodrigouchoa.generic.dao.GenericDaoHibernate; 11 | import com.rodrigouchoa.generic.dao.entity.Customer; 12 | import com.rodrigouchoa.generic.dao.entity.Invoice; 13 | 14 | 15 | /** 16 | * Helper class to insert data into the database. 17 | * 18 | * @author Rodrigo Uchôa (http://rodrigouchoa.wordpress.com) 19 | * 20 | */ 21 | @Singleton 22 | @Startup 23 | public class InitDB { 24 | 25 | @Inject 26 | private GenericDaoHibernate dao; 27 | 28 | @PostConstruct 29 | public void init() { 30 | Invoice i1 = new Invoice("Invoice 1", new BigDecimal("10.00")); 31 | Invoice i2 = new Invoice("Invoice 2", new BigDecimal("20.00")); 32 | Invoice i3 = new Invoice("Invoice 3", new BigDecimal("30.00")); 33 | Invoice i4 = new Invoice("Invoice 4", new BigDecimal("40.00")); 34 | Invoice i5 = new Invoice("Invoice 5", new BigDecimal("50.00")); 35 | Invoice i6 = new Invoice("Invoice 6", new BigDecimal("60.00")); 36 | Invoice i7 = new Invoice("Invoice 7", new BigDecimal("70.00")); 37 | Invoice i8 = new Invoice("Invoice 8", new BigDecimal("80.00")); 38 | Invoice i9 = new Invoice("Invoice 9", new BigDecimal("90.00")); 39 | Invoice i10 = new Invoice("Invoice 10", new BigDecimal("100.00")); 40 | 41 | Customer c1 = new Customer("Barack Obama", 33, i1, i2, i3, i4); 42 | Customer c2 = new Customer("Peter Gabriel", 45, i5, i6, i7, i8); 43 | Customer c3 = new Customer("Scarlett Johansson", 33, i9, i10); 44 | 45 | dao.save(c1); 46 | dao.save(c2); 47 | dao.save(c3); 48 | 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/rodrigouchoa/generic/dao/entity/Invoice.java: -------------------------------------------------------------------------------- 1 | package com.rodrigouchoa.generic.dao.entity; 2 | 3 | import java.math.BigDecimal; 4 | 5 | import javax.persistence.Column; 6 | import javax.persistence.ConstraintMode; 7 | import javax.persistence.Entity; 8 | import javax.persistence.ForeignKey; 9 | import javax.persistence.GeneratedValue; 10 | import javax.persistence.Id; 11 | import javax.persistence.JoinColumn; 12 | import javax.persistence.ManyToOne; 13 | import javax.persistence.Table; 14 | 15 | @Entity 16 | @Table(name = "TB_INVOICE") 17 | public class Invoice extends BaseEntity { 18 | 19 | @Id 20 | @GeneratedValue 21 | @Column(name = "id_invoice") 22 | private Long id; 23 | 24 | @Column(name = "description") 25 | private String description; 26 | 27 | @Column(name = "value") 28 | private BigDecimal value; 29 | 30 | @ManyToOne 31 | @JoinColumn(name = "id_customer", foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT)) 32 | private Customer customer; 33 | 34 | public Invoice() {} 35 | 36 | public Invoice(String description, BigDecimal value) { 37 | this.description = description; 38 | this.value = value; 39 | } 40 | 41 | @Override 42 | public Long getId() { 43 | return id; 44 | } 45 | 46 | public void setId(Long id) { 47 | this.id = id; 48 | } 49 | 50 | public String getDescription() { 51 | return description; 52 | } 53 | 54 | public void setDescription(String description) { 55 | this.description = description; 56 | } 57 | 58 | public BigDecimal getValue() { 59 | return value; 60 | } 61 | 62 | public void setValue(BigDecimal value) { 63 | this.value = value; 64 | } 65 | 66 | public Customer getCustomer() { 67 | return customer; 68 | } 69 | 70 | public void setCustomer(Customer customer) { 71 | this.customer = customer; 72 | } 73 | 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/com/rodrigouchoa/generic/dao/entity/Customer.java: -------------------------------------------------------------------------------- 1 | package com.rodrigouchoa.generic.dao.entity; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import javax.persistence.CascadeType; 7 | import javax.persistence.Column; 8 | import javax.persistence.Entity; 9 | import javax.persistence.GeneratedValue; 10 | import javax.persistence.Id; 11 | import javax.persistence.OneToMany; 12 | import javax.persistence.Table; 13 | 14 | @Entity 15 | @Table(name = "TB_CUSTOMER") 16 | public class Customer extends BaseEntity { 17 | 18 | @Id 19 | @GeneratedValue 20 | @Column(name = "id_customer") 21 | private Long id; 22 | 23 | @Column(name = "name") 24 | private String name; 25 | 26 | @Column(name = "age") 27 | private Integer age; 28 | 29 | @OneToMany(mappedBy = "customer", cascade = {CascadeType.PERSIST}) 30 | private List invoices = new ArrayList(); 31 | 32 | public Customer() {} 33 | 34 | public Customer(String name, Integer age, Invoice...invoices) { 35 | this.name = name; 36 | this.age = age; 37 | for (Invoice i : invoices) { 38 | addInvoice(i); 39 | } 40 | } 41 | 42 | @Override 43 | public Long getId() { 44 | return id; 45 | } 46 | 47 | public void setId(Long id) { 48 | this.id = id; 49 | } 50 | 51 | public String getName() { 52 | return name; 53 | } 54 | 55 | public void setName(String name) { 56 | this.name = name; 57 | } 58 | 59 | public List getInvoices() { 60 | return invoices; 61 | } 62 | 63 | public void setInvoices(List invoices) { 64 | this.invoices = invoices; 65 | } 66 | 67 | public void addInvoice(Invoice invoice) { 68 | invoices.add(invoice); 69 | invoice.setCustomer(this); 70 | } 71 | 72 | public Integer getAge() { 73 | return age; 74 | } 75 | 76 | public void setAge(Integer age) { 77 | this.age = age; 78 | } 79 | 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/com/rodrigouchoa/generic/dao/action/IndexAction.java: -------------------------------------------------------------------------------- 1 | package com.rodrigouchoa.generic.dao.action; 2 | 3 | import java.math.BigDecimal; 4 | import java.util.List; 5 | 6 | import javax.enterprise.context.RequestScoped; 7 | import javax.inject.Inject; 8 | import javax.inject.Named; 9 | 10 | import com.rodrigouchoa.generic.dao.GenericDaoJpa; 11 | import com.rodrigouchoa.generic.dao.GenericDaoJpa.MatchMode; 12 | import com.rodrigouchoa.generic.dao.entity.Customer; 13 | import com.rodrigouchoa.generic.dao.entity.Invoice; 14 | import com.rodrigouchoa.generic.dao.entity.Order; 15 | 16 | 17 | /** 18 | * A simple JSF Managed Bean for index.xhtml 19 | * 20 | * 21 | * @author Rodrigo Uchôa (http://rodrigouchoa.wordpress.com) 22 | * 23 | */ 24 | @Named 25 | @RequestScoped 26 | public class IndexAction { 27 | 28 | /* In case you want o use hibernate directly */ 29 | //@Inject 30 | //private GenericDaoHibernate dao; 31 | 32 | @Inject 33 | private GenericDaoJpa dao; 34 | 35 | 36 | @SuppressWarnings("unused") 37 | public void go() { 38 | //find by id 39 | Customer c1 = dao.find(Customer.class, new Long(1)); 40 | Invoice i1 = dao.find(Invoice.class, new Long(3)); 41 | 42 | //find all without any order 43 | List listCustomers = dao.findAll(Customer.class); 44 | List listInvoices = dao.findAll(Invoice.class); 45 | 46 | //finding all with an order 47 | List listCustomers2 = dao.findAll(Customer.class, Order.DESC, "name"); 48 | List listInvoices2 = dao.findAll(Invoice.class, Order.ASC, "description"); 49 | 50 | //findind by a non-textual property 51 | List listCustomers3 = dao.findByProperty(Customer.class, "age", 33); 52 | List listInvoices3 = dao.findByProperty(Invoice.class, "value", new BigDecimal("90.00")); 53 | 54 | //finding by a text property, using the like operator. 55 | List listCustomers4 = dao.findByProperty(Customer.class, "name", "rack", MatchMode.ANYWHERE); //should return Barack Obama 56 | 57 | //etc etc etc 58 | 59 | //you get the idea 60 | 61 | 62 | } 63 | 64 | 65 | } 66 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 4.0.0 5 | 6 | com.rodrigouchoa 7 | generic-dao 8 | 0.0.1-SNAPSHOT 9 | 10 | war 11 | 12 | Generic DAO 13 | A simple WEB project showing two implement a generic DAO 14 | 15 | 16 | UTF-8 17 | 1.8 18 | 19 | 20 | 21 | 22 | 23 | true 24 | org.apache.maven.plugins 25 | maven-compiler-plugin 26 | 3.1 27 | 28 | ${java.version} 29 | ${java.version} 30 | ${project.build.sourceEncoding} 31 | true 32 | true 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | com.h2database 45 | h2 46 | 1.3.173 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | org.hibernate 56 | hibernate-core 57 | 4.3.6.Final 58 | provided 59 | 60 | 61 | 62 | javax 63 | javaee-api 64 | 7.0 65 | provided 66 | 67 | 68 | -------------------------------------------------------------------------------- /src/main/java/com/rodrigouchoa/generic/dao/GenericDaoHibernate.java: -------------------------------------------------------------------------------- 1 | package com.rodrigouchoa.generic.dao; 2 | 3 | import java.io.Serializable; 4 | import java.util.List; 5 | 6 | import javax.ejb.Stateless; 7 | import javax.inject.Inject; 8 | import javax.persistence.EntityManager; 9 | import javax.ws.rs.NotFoundException; 10 | 11 | import org.hibernate.Criteria; 12 | import org.hibernate.Session; 13 | import org.hibernate.criterion.MatchMode; 14 | import org.hibernate.criterion.Restrictions; 15 | 16 | import com.rodrigouchoa.generic.dao.entity.BaseEntity; 17 | import com.rodrigouchoa.generic.dao.entity.Order; 18 | 19 | /** 20 | * A generic DAO implementation using Hibernate's Session directly, not JPA. 21 | * 22 | *

The primary noticeable difference is the use of "hibernate criteria" instead of "JPA criteria". 23 | * 24 | * @author Rodrigo Uchôa (http://rodrigouchoa.wordpress.com) 25 | * 26 | */ 27 | @Stateless 28 | public class GenericDaoHibernate { 29 | 30 | //take a look at the getSession() method. 31 | //This is not used "directly". 32 | @Inject 33 | private EntityManager entityManager; 34 | 35 | 36 | /** 37 | * Saves an entity. 38 | * 39 | * @param entity 40 | * @return newly created id for the entity. 41 | */ 42 | @SuppressWarnings("unchecked") 43 | public , PK extends Serializable> PK save(T entity) { 44 | return (PK) getSession().save(entity); 45 | } 46 | 47 | /** 48 | * Marges objects with the same identifier within a session into a newly created object. 49 | * 50 | * @param entity 51 | * @return a newly created instance merged. 52 | */ 53 | @SuppressWarnings("unchecked") 54 | public , PK extends Serializable> T merge(T entity) { 55 | return (T) getSession().merge(entity); 56 | } 57 | 58 | /** 59 | * Deletes tne entity. 60 | * 61 | * @param clazz 62 | * @param id 63 | * @throws NotFoundException if the id does not exist. 64 | */ 65 | public , PK extends Serializable> void delete(Class clazz, PK id) { 66 | T entity = find(clazz, id); 67 | if (entity != null) { 68 | getSession().delete(entity); 69 | } else { 70 | throw new NotFoundException(); 71 | } 72 | } 73 | 74 | /** 75 | * Find an entity by its identifier. 76 | * 77 | * @param clazz 78 | * @param id 79 | * @return 80 | */ 81 | @SuppressWarnings("unchecked") 82 | public > T find(Class clazz, Serializable id) { 83 | return (T) getSession().get(clazz, id); 84 | } 85 | 86 | /** 87 | * Finds entities by one of its properties. 88 | * 89 | * 90 | * 91 | * @param clazz the entity class. 92 | * @param propertyName the property name. 93 | * @param value the value by which to find. 94 | * @return 95 | */ 96 | @SuppressWarnings("unchecked") 97 | public > List findByProperty(Class clazz, String propertyName, Object value) { 98 | return getSession().createCriteria(clazz).add(Restrictions.eq(propertyName, value)).list(); 99 | } 100 | 101 | /** 102 | * Finds entities by a String property specifying a MatchMode. This search 103 | * is case insensitive. 104 | * 105 | * @param clazz the entity class. 106 | * @param propertyName the property name. 107 | * @param value the value to check against. 108 | * @param matchMode the match mode: EXACT, START, END, ANYWHERE. 109 | * @return 110 | */ 111 | @SuppressWarnings("unchecked") 112 | public > List findByProperty(Class clazz, String propertyName, String value, MatchMode matchMode){ 113 | if (matchMode != null){ 114 | return getSession().createCriteria(clazz).add(Restrictions.ilike(propertyName, value, matchMode)).list(); 115 | }else{ 116 | return getSession().createCriteria(clazz).add(Restrictions.ilike(propertyName, value, MatchMode.EXACT)).list(); 117 | } 118 | } 119 | 120 | /** 121 | * Finds all objects of an entity class. 122 | * 123 | * @param clazz the entity class. 124 | * @return 125 | */ 126 | @SuppressWarnings("unchecked") 127 | public > List findAll(Class clazz) { 128 | return getSession().createCriteria(clazz).list(); 129 | } 130 | 131 | /** 132 | * Finds all objects of a class by the specified order. 133 | * 134 | * @param clazz the entity class. 135 | * @param order the order: ASC or DESC. 136 | * @param propertiesOrder the properties on which to apply the ordering. 137 | * 138 | * @return 139 | */ 140 | @SuppressWarnings("unchecked") 141 | public > List findAll(Class clazz, Order order, String... propertiesOrder) { 142 | Criteria criteria = getSession().createCriteria(clazz); 143 | 144 | for (String propertyOrder : propertiesOrder) { 145 | if (order.isAscOrder()) { 146 | criteria.addOrder(org.hibernate.criterion.Order.asc(propertyOrder)); 147 | } else { 148 | criteria.addOrder(org.hibernate.criterion.Order.desc(propertyOrder)); 149 | } 150 | } 151 | 152 | return criteria.list(); 153 | } 154 | 155 | 156 | protected Session getSession() { 157 | return (Session) entityManager.getDelegate(); 158 | } 159 | 160 | } 161 | -------------------------------------------------------------------------------- /src/main/java/com/rodrigouchoa/generic/dao/GenericDaoJpa.java: -------------------------------------------------------------------------------- 1 | package com.rodrigouchoa.generic.dao; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import javax.ejb.Stateless; 8 | import javax.inject.Inject; 9 | import javax.persistence.EntityManager; 10 | import javax.persistence.criteria.CriteriaBuilder; 11 | import javax.persistence.criteria.CriteriaQuery; 12 | import javax.persistence.criteria.Root; 13 | import javax.ws.rs.NotFoundException; 14 | 15 | 16 | 17 | import com.rodrigouchoa.generic.dao.entity.BaseEntity; 18 | import com.rodrigouchoa.generic.dao.entity.Order; 19 | 20 | /** 21 | * A generic dao implementation based solely on JPA. 22 | * 23 | *

Comparing to the Hibernate version, the main difference is Criteria 24 | * API. JPA's criteria is a lot more verbose. Type safety comes at a price. 25 | * 26 | *

Please note that this implementation is not type safe, properties are passed 27 | * as String's. Probably something that could be better since that's what JPA's criteria 28 | * API is all about. 29 | * 30 | * @author Rodrigo Uchôa (http://rodrigouchoa.wordpress.com) 31 | * 32 | */ 33 | @Stateless 34 | public class GenericDaoJpa { 35 | 36 | /* 37 | * A "copy" of the Hibernate's API as this doesn't exist 38 | * in JPA. 39 | */ 40 | public enum MatchMode { START, END, EXACT, ANYWHERE } 41 | 42 | 43 | @Inject 44 | private EntityManager entityManager; 45 | 46 | /** 47 | * Saves an entity. 48 | * 49 | * @param entity 50 | * @return newly created id for the entity. 51 | */ 52 | public , PK extends Serializable> PK save(T entity) { 53 | entityManager.persist(entity); 54 | return entity.getId(); 55 | } 56 | 57 | 58 | /** 59 | * Marges objects with the same identifier within a session into a newly 60 | * created object. 61 | * 62 | * @param entity 63 | * @return a newly created instance merged. 64 | */ 65 | public , PK extends Serializable> T merge(T entity) { 66 | return entityManager.merge(entity); 67 | } 68 | 69 | /** 70 | * Deletes tne entity. 71 | * 72 | * @param clazz 73 | * @param id 74 | * @throws NotFoundException if the id does not exist. 75 | */ 76 | public , PK extends Serializable> void delete(Class clazz, PK id) { 77 | T entity = find(clazz, id); 78 | if (entity != null) { 79 | entityManager.remove(entity); 80 | } else { 81 | throw new NotFoundException(); 82 | } 83 | } 84 | 85 | /** 86 | * Find an entity by its identifier. 87 | * 88 | * @param clazz 89 | * @param id 90 | * @return 91 | */ 92 | public > T find(Class clazz, Serializable id) { 93 | return entityManager.find(clazz, id); 94 | } 95 | 96 | /** 97 | * Finds an entity by one of its properties. 98 | * 99 | * 100 | * @param clazz the entity class. 101 | * @param propertyName the property name. 102 | * @param value the value by which to find. 103 | * @return 104 | */ 105 | public > List findByProperty(Class clazz, String propertyName, Object value) { 106 | CriteriaBuilder cb = entityManager.getCriteriaBuilder(); 107 | CriteriaQuery cq = cb.createQuery(clazz); 108 | Root root = cq.from(clazz); 109 | cq.where(cb.equal(root.get(propertyName), value)); 110 | return entityManager.createQuery(cq).getResultList(); 111 | } 112 | 113 | /** 114 | * Finds entities by a String property specifying a MatchMode. This search 115 | * is case insensitive. 116 | * 117 | * @param clazz the entity class. 118 | * @param propertyName the property name. 119 | * @param value the value to check against. 120 | * @param matchMode the match mode: EXACT, START, END, ANYWHERE. 121 | * @return 122 | */ 123 | public > List findByProperty(Class clazz, String propertyName, String value, MatchMode matchMode) { 124 | //convert the value String to lowercase 125 | value = value.toLowerCase(); 126 | if (MatchMode.START.equals(matchMode)) { 127 | value = value + "%"; 128 | } else if (MatchMode.END.equals(matchMode)) { 129 | value = "%" + value; 130 | } else if (MatchMode.ANYWHERE.equals(matchMode)) { 131 | value = "%" + value + "%"; 132 | } 133 | 134 | CriteriaBuilder cb = entityManager.getCriteriaBuilder(); 135 | CriteriaQuery cq = cb.createQuery(clazz); 136 | Root root = cq.from(clazz); 137 | cq.where(cb.like(cb.lower(root.get(propertyName)), value)); 138 | 139 | return entityManager.createQuery(cq).getResultList(); 140 | } 141 | 142 | 143 | 144 | /** 145 | * Finds all objects of an entity class. 146 | * 147 | * @param clazz the entity class. 148 | * @return 149 | */ 150 | public > List findAll(Class clazz) { 151 | CriteriaBuilder cb = entityManager.getCriteriaBuilder(); 152 | CriteriaQuery cq = cb.createQuery(clazz); 153 | cq.from(clazz); 154 | return entityManager.createQuery(cq).getResultList(); 155 | } 156 | 157 | /** 158 | * Finds all objects of a class by the specified order. 159 | * 160 | * @param clazz the entity class. 161 | * @param order the order: ASC or DESC. 162 | * @param propertiesOrder the properties on which to apply the ordering. 163 | * 164 | * @return 165 | */ 166 | public > List findAll(Class clazz, Order order, String... propertiesOrder) { 167 | CriteriaBuilder cb = entityManager.getCriteriaBuilder(); 168 | CriteriaQuery cq = cb.createQuery(clazz); 169 | Root root = cq.from(clazz); 170 | 171 | List orders = new ArrayList<>(); 172 | for (String propertyOrder : propertiesOrder) { 173 | if (order.isAscOrder()) { 174 | orders.add(cb.asc(root.get(propertyOrder))); 175 | } else { 176 | orders.add(cb.desc(root.get(propertyOrder))); 177 | } 178 | } 179 | cq.orderBy(orders); 180 | 181 | return entityManager.createQuery(cq).getResultList(); 182 | } 183 | 184 | } 185 | --------------------------------------------------------------------------------