I am working on REST and JPA technology and want to design Service and Dao layer generically.
I want to follow the decouple rule for each layer. So that in future at any point of time these layer can be changed if required without much modification. So to do the same for DAO layer I am following Factory pattern.
Please have a look what i did till now.
public abstract class AbstractDao {
#PersistenceUnit(name = "Services")
private EntityManagerFactory factory;
public AbstractDao() {
this.factory = Persistence.createEntityManagerFactory("Services");
}
public void save(AbstractEntity entity) {
EntityManager em = getEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
em.persist(entity);
tx.commit();
}
public void delete(AbstractEntity entity) {
getEntityManager().remove(entity);
}
public List<AbstractEntity> findAll() {
CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
CriteriaQuery<AbstractEntity> cq = cb.createQuery(AbstractEntity.class);
Root<AbstractEntity> from = cq.from(AbstractEntity.class);
cq.select(from);
TypedQuery<AbstractEntity> q = getEntityManager().createQuery(cq);
List<AbstractEntity> allitems = q.getResultList();
return allitems;
}
private EntityManager getEntityManager() {
EntityManager em = factory.createEntityManager();
return em;
}
}
So this the design what I used for DAO layer. But not sure is it the right approach or it can be much better like AbstractFactory patter or etc.
Now come to REST Service layer where I am accessing this DAO layer for CRUD.
So this the way how I am accessing the DAO layer on Service layer. But again I am thinking to way some other better way to access this DAO layer.
One more thing I want to ask, would it be good idea if I introduce business layer and follow like this.
Client -> Service Layer-> Business Layer -> DAO Layer
Could someone help me to design the different layer of project.
Thanks in advance.
please use this type of directory structure:
use Spring framework and use Spring Restful service annotations, for example refer this link :
https://dzone.com/articles/exporting-spring-data-jpa
Related
Say I've got a few interfaces extending CRUDRepositor. There are methods in there like findByField. Some of these methods should only return entities that belong to a group of entities to which the user has access (the group is a column in the database, so it's a field that's defined for most entities). I want to achieve this by allowing the use of annotations (like #Protected) on the repository methods, and then when these methods are called instead of calling findByField a method findByFieldAndGroup is called behind the scenes. With the use of AOP (which intercepts methods annotated with my #Protected tag) the group can be assigned before the method is effectively executed.
public interface MyRepository extends CRUDRepository<MyEntity,long> {
#Protected
Optional<MyEntity> findById(Long id); // Should become findByIdAndGroup(Long id, String group) behind the scenes
#Protected
Collection<MyEntity> findAll();
}
Is there a way to achieve this? In the worst case I either add all the methods manually, or completely switch to a query by example approach (where you can more easily add the group dynamically) or generate methods with a Java agent using ASM (manipulating the bytecode) ... but these are much less practical approaches which demand a good deal of refactoring.
Edit : found these relevant questions Spring data jpa - modifying query before execution
Spring Data JPA and spring-security: filter on database level (especially for paging)
Other relevant references include this ticket on GitHub (no progress, only a sort-of-solution with QueryDSL which precludes the use of queries based on method names) and this thread.
You can use filters, a specific Hibernate feature, for this problem.
The idea is the following.
First, you need to annotate your entity with the different filters you want to apply, in your case, something like:
#Entity
//...
#Filters({
#Filter(name="filterByGroup", condition="group_id = :group_id")
})
public class MyEntity implements Serializable {
// ...
}
Then, you need access to the underlying EntityManager because you need to interact with the associated Hibernate Session. You have several ways to do this. For example, you can define a custom transaction manager for the task, something like:
public class FilterAwareJpaTransactionManager extends JpaTransactionManager {
#Override
protected EntityManager createEntityManagerForTransaction() {
final EntityManager entityManager = super.createEntityManagerForTransaction();
// Get access to the underlying Session object
final Session session = entityManager.unwrap(Session.class);
// Enable filter
try{
this.enableFilterByGroup(session);
}catch (Throwable t){
// Handle exception as you consider appropriate
t.printStackTrace();
}
return entityManager;
}
private void enableFilterByGroup(final Session session){
final String group = this.getGroup();
if (group == null) {
// Consider logging the problem
return;
}
session
.enableFilter("filterByGroup")
.setParameter("group_id", group)
;
}
private String getGroup() {
// You need access to the user information. For instance, in the case of Spring Security you can try:
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null) {
return null;
}
// Your user type
MyUser user = (MyUser)authentication.getPrincipal();
String group = user.getGroup();
return group;
}
}
Then, register this TransationManager in your database configuration instead of the default JpaTransactionManager:
#Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new FilterAwareJpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory());
return transactionManager;
}
You can also have access to the EntityManager and associated Session by creating a custom JpaRepository or by injecting #PersistenceContext in your beans, but I think the above-mentioned approach is the simpler one although it has the drawback of being always applied.
I've setup a spring MVC application for a web application and I'm using Hibernates implementation of JPA 2.1.
I've created my models and am able to interact with the database just fine.
I've also decided to use service classes which will manage returning the entities. What I've done is created a BaseService class, so all other service classes will expand on this, and they'll have access to common functions such as create(), delete(), update() and list().
My problem is I'm unsure as to when I should be creating the EntityManager and when I should be closing it?
Currently, in my controller I'm initiating the required services when the controller loads;
#Controller
#RequestMapping("/mycontroller")
public class TestController {
CarService carService = new CarService();
ShowroomService showroomService = new ShowroomService();
}
}
Here is the BaseService that each other service extends;
public class Service<Ety> {
EntityManager em = null;
public Class<Ety> entityClass;
public Service(Class<Ety> entityClass) {
this.entityClass = entityClass;
em = JPAUtil.getEntityManager();
}
public Ety get(int id) {
Ety object = null;
em.getTransaction().begin();
object = em.find(entityClass, id);
em.getTransaction().commit();
return object;
}
public List list() {
List<Ety> objects;
em.getTransaction().begin();
objects = em.createQuery("SELECT c FROM "+entityClass.getName()+" c").getResultList();
em.getTransaction().commit();
return objects;
}
public void save(Ety object) {
em.getTransaction().begin();
em.persist(object);
em.getTransaction().commit();
}
public void update(Ety object) {
em.getTransaction().begin();
em.merge(object);
em.getTransaction().commit();
}
public void delete(Ety object) {
em.getTransaction().begin();
em.remove(object);
em.getTransaction().commit();
}
}
Here's an example Service which expands the above;
public class CarService extends Service<Car> {
public CarService() {
super(Car.class);
}
}
As you can see, I'm creating an EntityManager when the service is created, but at the moment I'm not closing it anywhere.
I'm I creating the entity manager in the correct place? when should I close it.
I had considered putting the entity manager in a static property and creating it within a filter, and then closing it at the end of the application, however I do believe this wouldn't be thread safe and would cause issues?
Any advice would be appreciated.
your CarService should be a spring bean and the instance is created from spring. NOT from your code. The same with the EntityManager. You can use the entityManager with the #autowired annotation.
You open a new EntityManager for each transaction.
This EntityManager is like a Bag mapped to the database, but with zero entity managed inside when it's just opened.
When you work with it, this Bag will be filled with some entities and Hibernate will work to create the adequate requests.
You will close this Bag to save memory at the end of the transaction.
Of course there is some tricks to have many transactions for a given EntityManager, but you have the most general idea. As always it depends...
If you use a framework like Spring or JavaEE, it will open and close the EntityManager, as well starting and committing transactions for you. You have only your business work to write.
I am currently developing a web application using Struts2 with Spring plugin and hibernate and while I was looking at online examples I saw the use of Service and DAO layers now it came to me what are the real use of Service and data access object layers? If The Service layer is just calling the methods of DAO layers to perform CRUD operations. wouldn't be sensible to just call the DAO layers methods directly?
Let's say this example of Dao and Service Layer
PeopleService
#Transactional
public class PeopleService {
private PeopleDao pDao;
public PeopleDao getPDao() { return pDao; }
public void setPDao(PeopleDao peopleDao) { this.pDao = peopleDao; }
public void createPerson(String name){
pDao.createPerson(name);
}
public List<Person> getPeople(){
return pDao.getPeople();
}
}
PeopleDao
public class PeopleDao {
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public Session sess() {
return sessionFactory.getCurrentSession();
}
public Person getPersonById(long id) {
return (Person) sess().load(Person.class, id);
}
public void deletePersonById(long id) {
sess().delete(getPersonById(id));
}
public void createPerson(String name) {
Person p = new Person();
p.setName(name);
sess().save(p);
}
#SuppressWarnings("unchecked")
public List<Person> getPeople() {
return sess().createQuery("from Person").list();
}
}
My question is what is the real use of Service layers if they are only being injected by their representative DAO and then calling its method?
It is a good idea to have those two layers when your business logic is more complex than your data logic. The service layer implements the business logic. In most cases, this layer has to perform more operations than just calling a method from a DAO object. And if you're thinking of making your application bigger, this is probably the best solution.
Imagine you want to include a City entity and create a relationship between People and City. Here is an example:
#Transactional
public class PeopleService {
....
private PeopleDAO pDAO;
private CityDAO cDAO;
...
public void createPerson(String name, String city)
throws PeopleServiceException {
Person p = new Person();
p.setName(name);
City c = cDAO.getCityByName(city);
if (c == null) throw new ServiceException(city + " doesn't exist!");
if (c.isFull()) throw new ServiceException(city + " is full!");
c.addPeople(p);
sess().save(p);
sess().save(c);
}
...
}
In this example, you can implement more complex validations, like checking the consistency of the data. And PersonDAO has not been modified.
Another example:
DAO and Service layers with Spring
Definition of Service layer pattern
If your application will grow with new and changing requirements you are very well served with having distinct layers for those TWO DISTINCT ASPECTS (persistence->DAO, business use case -> services) of your software.
One aspect is your persistence model with its relations, validations, transactions and many access patterns.
The services are driven by the business use cases which have a very different granularity. In the beginning you may have very simple services which don't do much more than calling DAOs to hand over data they received from, let's say, a web page. But this is likely to change over time and services will grow into small networks of collaborating objects that do a lot more to serve the business use case. If you don't use DAOs then
your services will contain code that deals with querying objects, transaction handling, validation, all of which has nothing to do with real business requirements
service code will look messy and it will be difficult to find out what parts of the code are actually business related
if you then change the persistence model you might end up changing many services
Also you can not easily unit test your persistence model but write tests only on the service layer. Do not forget that decoupling and encapsulation are important techniques to minimize the impact of change.
When done right, having a DAO layer will not introduce much implementation overhead so there is not much extra cost in having it. It will soon pay off and you will be very glad to have this dedicated layer.
Check out this article: http://codeblock.engio.net/?p=180. It also comes with a full implementation hosted on github
The usual idiom I see for creating the EntityManager is something like this:
public class BaseDao {
private static final String PERSISTENCE_UNIT_NAME = "Employee";
EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
public EntityManager getEntityManager() {
return factory.createEntityManager();
}
}
Then it is used like this:
Employee emp = new Employee();
emp.setName("Joe M");
getEntityManager().persist(emp);
Question is why not do it this way:
public class BaseDao{
private static final String PERSISTENCE_UNIT_NAME = "Employee";
EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
private EntityManager entityManager = null;
public void setEntityManger() {
EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
this.entityManager = factory.createEntityManager();
}
public EntityManager getEntityManager() {
return this.entityManager;
}
}
In other words is there a need to always get the entity manager through factory.createEntityManager()? or can it be created as an instance (or even static) variable and retrieved like that?
To clarify, I am talking about an environment that doesn't use EJB or Spring containers.
Thanks.
There are two ways to create EntityManager instances.
One way is for SDK applications, and I use this way a lot in unit testing. This is what you have in your example:
EntityManagerFactory factory =
Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
In Enterprise applications you let the container create them for you and inject them when needed.
EntityManager is just a wrapper around a JDBC connection. It's very light weight and can be created and destroyed without performance penalty.
Keep in mind that the EntityManager is not thread safe, so if you have one instance, you may need to synchronize access to it. See transaction basics for details.
Here's how I would do it (roughly):
public class BaseDao{
private static final String PERSISTENCE_UNIT_NAME = "Employee";
private static EntityManagerFactory factory =
Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
public void create(MyEntiy person){
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();
// do what ever you need
em.getTransaction().commit();
em.close();
}
// add more methods to the dao.
}
Once you get this protoyped and ready, you can use a generic DAO.
Today you should probably look at sometime like spring-data and #PersistanceUnit for managing your EntityManager.
An EntityManager is more than just a wrapper a wrapper for a JDBC connection. It defines the scope of a persistence context, which defines the unit of work that should be performed when a transaction is committed (of when you flush queries to the database). Within a persistence context you are also guaranteed that a given entity in the database will result in the same Java object, regardless if you load it directly, or access it through a OneToMany relation of another entity.
With regards to the original question about obtaining an EntityManagerFactory in a non-spring setting. You simply call
Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
This method is a static factory method, depending on your JPA implementation you either get the same instance for the same PU, or a shallow wrapper that wraps the underlying persistence session (of which there is one per PU).
I am working on a java web application that calls database backend through hibernate.I use servlets,jsp and tomcat for test/deployment.Most books on java-ee suggested using Dao classes for database calls.As per examples given in books(Hibernate Recipes by Gary Mak),I created a generic base class and a specific subclass as below.
class BaseDao{
private Class persistentClass;
public BaseDao(Class persistentClass) {
super();
this.persistentClass = persistentClass;
}
public Object findById(Long id) {
SessionFactory factory = HibernateUtil.getSessionFactory();
Session session = factory.openSession();
Object object = null;
try {
object = (Object) session.get(persistentClass, id);
return object;
}
finally {
session.close();
}
}
#Override
public void saveOrUpdate(Object obj) {
SessionFactory factory = HibernateUtil.getSessionFactory();
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
session.saveOrUpdate(obj);
tx.commit();
}catch(HibernateException e){
if (tx != null) {
tx.rollback();
}
throw e;
}finally {
session.close();
}
}
}
class SaleOrderDao extends BaseDao{
public SaleOrderDao() {
super(SaleOrder.class);
}
#Override
public SaleOrder findSaleOrderById(Long saleOrderId){
SaleOrder so = (SaleOrder)findById(saleOrderId);
return so;
}
#Override
public void saveOrUpdateSaleOrder(SaleOrder so){
saveOrUpdate( so);
}
}
While going through the posts in this forum ,I came across Ryan Stewart's advice that beginning and ending transactions in a dao method is not recommended..Sadly, my project does not use any web framework that supports transaction management..and I am limited to using jsp,servlets and a servlet container..
Is there some way I can rewrite my dao implementations sothat transactions can be managed properly..I couldn't find anything in this regard from those books I read..
Hope somebody helps me with suggestions
sincerely,
Jim
Normally transactions should not be handled in the DAO. They should be handled by the service layer. One service method may include multiple DAO calls that are all in the same transaction.
Spring (as well as other DI frameworks) allows you to do that by simply annotating your service methods with #Transactional. Without spring you can still do that manually in the service layer