- Java EE 8 Design Patterns and Best Practices
- Rhuan Rocha Jo?o Purifica??o
- 595字
- 2021-07-23 16:55:00
Implementing DAO
In order to reuse a lot of code and promote best practices to implement DAO, we will create an abstract DAO, called AbstractDao, which is the superclass of all DAOs, that has methods with the generic logic that can be used by all DAOs:
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public abstract class AbstractDao <T extends Entity>{
//EntityManager that provide JPA functionalities
@PersistenceContext
protected EntityManager em;
//Get the type of Subclass that implements Entity interface
protected Class<T> getType() {
ParameterizedType genericType = (ParameterizedType)
this.getClass().getGenericSuperclass();
return (Class<T>) genericType.getActualTypeArguments()[0];
}
//Find entity filtering by id.
public Optional<T> findById ( T entity ){
return Optional.ofNullable( em.find( (Class<T>)
entity.getClass(), entity.getId() ) );
}
public Optional<T> persist (T entity ){
em.persist( entity );
return Optional.of( entity );
}
public Optional<T> update ( T entity ){
return Optional.ofNullable( em.merge( entity ) );
}
public void delete ( T entity ){
em.remove( entity );
}
protected List<T> listWithNamedQuery(String namedQuery, Map<String,
Object> parameters){
TypedQuery<T> query = em.createNamedQuery( namedQuery,
getType() );
parameters.keySet().stream().forEach( key-> query.setParameter(
key, parameters.get( key ) ) );
return query.getResultList();
}
protected Optional<T> findWithNamedQuery(String namedQuery,
Map<String, Object> parameters){
TypedQuery<T> query = em.createNamedQuery( namedQuery,
getType() );
parameters.keySet().stream().forEach( key-> query.setParameter(
key, parameters.get( key ) ) );
return Optional.ofNullable(query.getSingleResult());
}
}
To prevent the user from instantiating AbstractDao, we created the class in the preceding code as an abstract class. Another AbstractDao characteristic is the return of methods, which only return Entity or a list of Entity. This is a good practice, because we know the object type that is returned by this method and it organizes our code, because we know what type of value our method could return:
import javax.ejb.Stateless;
import java.util.Collections;
import java.util.List;
@Stateless
public class EmployeeDao extends AbstractDao <Employee> {
public List<Employee> findByName(String name ){
return this.listWithNamedQuery("Employee.findByName",
Collections.singletonMap(
"name", name ) );
}
public List<Employee> findAll(){
return this.listWithNamedQuery("Employee.findAll",
Collections.emptyMap());
}
}
We can see that we have the EmployeeDao class, which is the DAO that reads and writes data about Employee. This class is an EJB, meaning that it can control all transactions with the JTA specification—assuming that transactions are managed by the Java EE container—and make the transaction control transparent to the application. To read employee data, we can call the findAll, findByName, and findById methods; to write employee data, we can call the persist and update methods; and to remove (delete) employee data, we can call the delete method. Note that the business class—a class that acts on the business tier—doesn't know about the process of reading and writing data; it only knows the parameters of the method to call as well as its returns. Therefore, we can substitute the data source without impacting the business logic. We have EmployeeBusiness using the DAO to read and write data, which we will see here:
import com.packt.javaee8.dao.EmployeeDao;
import com.packt.javaee8.entity.Employee;
import javax.ejb.Stateless;
import javax.inject.Inject;
import java.util.List;
import java.util.Optional;
@Stateless
public class EmployeeBusiness{
@Inject
protected EmployeeDao employeeDao;
public List<Employee> listByName( String name ){
return employeeDao.findByName( name );
}
public boolean save ( Employee employee ){
return employeeDao.persist( employee ).isPresent();
}
public List<Employee> listAll(){
return employeeDao.findAll();
}
public Optional<Employee> findById(Employee employee ){
return employeeDao.findById(employee);
}
}
This is a good pattern; its use is very broad and most applications implement it. When implementing this pattern, be careful not to expose data-source characteristics, for example, by sending a SQL query as a parameter to DAO's execution or by sending a path of the file system as a parameter to DAO's execution.
- Citrix XenApp Performance Essentials
- Windows Server 2019 Cookbook
- 嵌入式Linux開發技術
- Linux操作系統基礎
- Linux系統文件安全實戰全攻略
- Linux從零開始學(視頻教學版)
- 阿里云數字新基建系列:云原生操作系統Kubernetes
- VMware Horizon View 6 Desktop Virtualization Cookbook
- Windows 7中文版從入門到精通(修訂版)
- 嵌入式實時操作系統:RT-Thread設計與實現
- Linux設備驅動開發
- 計算機應用基礎(Windows 7+Office 2016)
- INSTANT Galleria Howto
- VMware Horizon View Essentials
- iOS 10 開發指南