2013-03-03 114 views
1

我有關於DAO和服務層模式的問題,我正在使用Spring 3和Hibernate 4作爲小型應用程序。DAO和服務層的設計模式

關於我的應用程序

我有地方員工和部門的數據都顯示在一個JSF形成一個小的應用程序小描述。

部門數據以表格形式使用作爲主數據的數據表以及相關的 以表格形式顯示部門數據使用數據表以及明細(主 - 明細)情景以表格形式顯示。 一旦點擊主數據表按鈕,會出現一個彈出窗口,可以在其中輸入有關部細節和數據庫表中的數據仍然存在(相同的情況下進行刪除和更新)

我的設計是類似如下

DAO層

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 
--- 

服務層

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 
} 

我的問題是我應該爲部門和員工使用單一的服務接口或類,因爲我爲我的JSF表單使用了一個ManagedBean,或者我應該爲部門和員工使用單獨的界面和類?將所有DAO方法與@Transactional合併到一個服務實現類中,在數據庫事務處理時是否會遇到任何性能問題?建議使用類似GenericDAO的通用服務接口?

任何幫助是非常可觀的?

更新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> 

回答

1

要真正回答這個問題,我們需要了解如何爲@事務語義已經配置的詳細信息。例如,每個DAO最終都會在單獨的事務中運行,或者會在Java級別上懶散地連接在一起,並在數據庫級別上懶洋洋地連接等。

假設「common」配置只有一個數據庫和連接當服務加入一個共享的請求級別事務時被懶惰地重用;不管你是否使用一兩個服務,我都不會有任何大的擔憂。

從性能的角度來看,它是數據庫的往返次數,數據庫請求的工作負載以及在數據庫級別保存事務多長時間,這將產生重大影響。有一個或兩個Java對象加入當時可能或可能不會被數據庫連接支持的Java級別事務(更不用說事務),這不會使性能數字變得更差。您可能會發現序列化多個獨立請求的延遲,在這種情況下,可能需要組合,批量或緩存一些查詢。哪一個最好從單個DAO完成;但是隻有在測量性能問題後才能做到這一點。

團隊約定和溝通你的設計意圖/域模型將在這裏變得更加重要。因此,我認爲你是最適合回答自己的問題的人,是否應該選擇一個或兩個服務。

+0

+1用於約定並明確地與名稱進行通信。與複雜的hibernate查詢相比,您會更早地遇到性能問題,而不是您所描述的事務拆分。 – vertti 2013-03-03 13:10:46

+0

Chris,你的意思是關於@Tranasctional語義的細節?你的意思是DAO植入類? – user75ponic 2013-03-03 13:47:35

+0

@Polppan。事務可以聲明爲在web請求開始時打開或者懶惰地創建,在請求之間保持打開狀態,與持有hibernate會話打開的底層數據庫分離,但在不需要時關閉數據庫連接,或者將每個請求置於其自己的事務中等等。還有關於如何合併跨不同會話對象的事務的選項,每次都要啓動一個新事務,是可選事務,必須事務已經在運行等等。這是在提及分佈式交易之前。這是一個很大的話題。 – 2013-03-03 13:54:47