简体   繁体   中英

Design pattern for DAO and Service layers

I have question regarding DAO and Service layer pattern and I am using Spring 3 and Hibernate 4 for a small application.

Small description regarding my application

I have a small application where employee and department data are displayed in a JSF form.

Department data is shown in tabular form using datatable which is master and the related Employees data is shown in tabular form using datatable as well which is detail (Master-Detail) scenario. Upon clicking button in master datatable, a popup window is displayed where details regarding Department can be entered and data persists in database table(same the case for delete and update)

My design is something like the following

DAO Layer

public interface GenericDAO<T> {
    public void create(T entity);
    public void update(T entity);
    public void delete(T entity);
}

public interface DepartmentDAO extends GenericDAO<Department>
--methods for getting Department list and others
  public void findDepartment(DepartmentData data);
  -----

 public interface EmployeeDAO extends GenericDAO<Employee>
 --methods for getting Employeelist and others
 ---

Service Layer

public interface DepartmentService {
 public void findDepartment(DepartmentData data);
 -- other methods
 }

@Transactional
@Named
public class DepartmentServiceImpl implements DepartmentService {

@Inject
DepartmentDAO departmentDAO;

-- implementation of methods
}

public interface EmployeeService {
 public void findEmployees(EmployeeData data);
 -- other methods
 }

@Transactional
@Named
public class EmployeeServiceImpl implements EmployeeService {

@Inject
EmployeeDAO employeeDAO;

-- implementation of methods
}

My question is should I use one single service interface or class for Department and Employee as I use one ManagedBean for my JSF form or should I have separate inerfaces and classes for Department and Employee? Having all DAO methods in one service implementation class with @Transactional, will it have any performance issue at the time of database transactions? Is it advisable to use a generic Service interface something similar to GenericDAO?

Any help is highly appreciable?

Update 1

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd"
>   
    <context:component-scan base-package="net.test" />
    <!-- Data Source Declaration -->    
    <bean id="DataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="jdbc/myDS"/>     
</bean>
    <bean
        class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
    <bean class="org.springframework.orm.hibernate4.HibernateExceptionTranslator" />
    <!-- JPA Entity Manager Factory -->
    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="DataSource" />
        <property name="packagesToScan" value="net.test.entity" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="true" />
                <property name="generateDdl" value="false" />
                <property name="databasePlatform" value="${jdbc.dialectClass}" />
            </bean>
        </property>
    </bean>
    <bean id="defaultLobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler" />
    <!-- Session Factory Declaration -->
    <bean id="SessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="DataSource" />
        <property name="annotatedClasses">
            <list>
                <value>net.test.entity.Employee</value>
                <value>net.test.entity.Department</value>

            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.query.factory_class">org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory
                </prop>
            </props>
        </property>
    </bean> 
    <tx:annotation-driven transaction-manager="txManager" />
    <tx:annotation-driven transaction-manager="transactionManager" />   
    <bean id="txManager"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="SessionFactory" />
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>
    <!-- <tx:annotation-driven transaction-manager="txManager"/> -->
    <context:annotation-config />
    <bean id="hibernateStatisticsMBean" class="org.hibernate.jmx.StatisticsService">
        <property name="statisticsEnabled" value="true" />
        <property name="sessionFactory" value="#{entityManagerFactory.sessionFactory}" />
    </bean>
    <bean name="ehCacheManagerMBean"
        class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />
    <bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
        <property name="locateExistingServerIfPossible" value="true" />
    </bean>
    <bean id="jmxExporter" class="org.springframework.jmx.export.MBeanExporter"
        lazy-init="false">
        <property name="server" ref="mbeanServer" />
        <property name="registrationBehaviorName" value="REGISTRATION_REPLACE_EXISTING" />
        <property name="beans">
            <map>
                <entry key="SpringBeans:name=hibernateStatisticsMBean"
                    value-ref="hibernateStatisticsMBean" />
                <entry key="SpringBeans:name=ehCacheManagerMBean" value-ref="ehCacheManagerMBean" />
            </map>
        </property>
    </bean>
</beans>

To really answer this problem we would need details on how the semantics for @Transactional have been configured. For example will each DAO end up running in a separate transaction, or will the join together eagerly at the Java level and lazily at the database level etc.

Assuming the 'common' configuration of there being only one database and the connections being reused lazily as services join a shared request level transaction then; I would not have any big concerns whether you went with one service or two.

From a performance point of view, it is the number of round trips to the database, the work load of the database requests and how long the transaction is held at the database level that will have the big effect. Having one or two Java objects joining a Java level transaction that may or may not be backed by a database connection (let alone transaction) at that time will not dwarf the performance numbers. You may find latency build up from serializing multiple separate requests, in which case some queries may need to be combined, batched or cached. Which would be best done from a single DAO; however only do this once you have a measured performance problem.

Team convention and communicating the intent of your design/domain model are going to be much more important here. Thus I think that you are the person best placed to answer your own question as to whether to go with one service or two.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM