官术网_书友最值得收藏!

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.

主站蜘蛛池模板: 靖宇县| 定南县| 花垣县| 当雄县| 阿尔山市| 南城县| 托克托县| 水富县| 杭锦旗| 潮安县| 车致| 平武县| 襄垣县| 天祝| 宜丰县| 姜堰市| 崇礼县| 将乐县| 黄大仙区| 伊川县| 会同县| 西宁市| 汽车| 秦安县| 博野县| 仪征市| 本溪| 沧州市| 巩留县| 靖远县| 勐海县| 格尔木市| 通辽市| 横峰县| 调兵山市| 顺昌县| 宽城| 湖南省| 西林县| 鹤壁市| 阿城市|