Reputation: 771
I've webapp with JSF, Spring and Mybatis. Those frameworks are utlized in controller, business and dao layers respectively. In my DAO layer I've methods for CRUD operations. Now, in my controller layer I need use insert operation. For this I could use this configuration:
Controller Layer
I'm using JSF with annotations
@ManagedBean
public class Controller{
@ManagedProperty("#{business}")
private Business business;
public void insert(){
business.insert();
}
}
Business Layer
I'm using Spring with annotations
public interface Business{
public void insert();
}
@Service("business")
public class BusinessImpl implements Business{
@Autowired
private DaoMapper mapper;
@Override
@Transactional
public void insert(){
mapper.insert();
}
}
DAO layer
I'm using Mybatis (mybatis-spring library)
public interface DaoMapper{
public void insert();
}
But as in this case my business layer only call to DAO layer and don't realize any other operation, I would think to use this configuration:
Controller Layer
@ManagedBean
public class Controller{
@ManagedProperty("#{daoMapper}")
private DaoMapper mapper;
public void insert(){
mapper.insert();
}
}
DAO layer
public interface DaoMapper{
@Transactional
public void insert();
}
I've already tested and works fine but I would like to know if I am incurring a bad practice
[EDIT]
Actually DaoMapper interface is a MyBatis class mapper that is asociated to XML file (Look). I don't know if this makes a DAO class. I think I should actually call it Persisence Layer or Mapper Layer
Source: http://www.infoq.com/articles/ddd-in-practice
As you can see. Presentation layer, In my case Controller Layer (I think I made another mistake naming), invoke directly to DTO (Or that's what I understand )
If in my controller or presentation layer (Whatever you call it) I need use insert or update operation, I could invoke directly from mapper class or I necessarily have to create a business class for for freshly from this class calls to mapper class
Now. If is possible use this configuration I have a doubt:
Suppose in a method of my business class I need to invoke to insert operation. This would be like:
@Service("business")
public class BusinessImpl implements Business{
@Autowired
private DaoMapper mapper;
@Override
@Transactional
public void insert(){
mapper.insert();
}
}
But method insert from DaoMapper interface already has @Transactional annotation. Method insert would be being affected twice by @Transactional annotation. Would not this be a problem?
Upvotes: 2
Views: 1722
Reputation: 385
I suggest to have service layer anyway. It has important function. It implements "verbs" / actions of your domain model and it's a good place where you can also define an atomicity of operations via @Transactional
. In my opinion, it's a bad practice to annotate MyBatis mapper methods with @Transactional
. Entities (MyBatis result POJOs in your case) are "nouns" of your domain model.
Domain model with only "nouns" is useless, you need to be able to perform some actions against it ("verbs"). "Verbs" are implemented by service layer. That's why I think service layer is necessary in 99.9% of cases. By now you just encountered only simple cases where business logic action is 1:1 to CRUD operation. But these are two different things. There could be more complex cases. Imagine online banking application where you have use case of registration of new client. This is a business logic action that involves several entities: you need to create user and you need to create bank account associated with that user. And this must happen in a single SQL transaction. "Verb" - "noun" separation is quite natural approach.
Controllers are web page controllers or REST controllers. They handle aspects related to page model (@ManagedBean
in case of JSF) or define RESTful API (@RestController
in case of Spring WebMVC). They are not intended to implements actions of domain model.
Also because of this reasoning it's also a bad practice to use entities as RESTful API's DTOs. Entities are domain model "nouns", RESTful API's DTOs define representations for RESTful API layer. These are different things.
Upvotes: 0
Reputation: 111
I suggest not using DAO in controller directly. In my opinion. Dao layer is the mapping from database, like if you want to change another database(eg. from sql to nosql) , the only thing is only create a new DAO and injected, but leave controller&Service functions not changed at all. So is the controller, its main responsibility is to handle the request and response, the work should be done by business/service layer. If it's wrong appreciate to point
Upvotes: 3
Reputation: 407
If you want to remove layers you could have the Controller and Service but skip the DAO. Your service could call the mapper directly since you dont have any specific query code. I know some well known Java people like Adam Bien consider the DAO as a dead pattern. http://www.adam-bien.com/roller/abien/entry/jpa_ejb3_killed_the_dao
Upvotes: 1