2009-12-17 79 views
1

我正在使用JPA/Spring/Hibernate作爲我的應用程序的持久性機制。目前,我遇到單元測試問題,當我詢問某些對象時,我從DAO返回的數量與數據庫中的行數相對應,但它們都是完全相同的實例。這是導致我的問題的findByName()方法。JPA Spring Hibernate Dao列表問題

 
public class ActionDefinitionDaoJpa extends JpaDaoSupport implements IActionDefinitionDao { 
    public List findByName(String name) { 
     return getJpaTemplate().find("from ActionDefinition where listenerName = ?", name); 
    } 
} 

該方法沒有任何錯誤。我正在DAO層而不是服務層進行測試,所以我沒有在測試中的任何地方引入事務。我不知道它是否是交易性的。如果我使用JPA生成的SQL並執行它,我會從數據庫中獲得正確的結果集。

這裏是我的Spring配置文件和persistence.xml文件

<beans> 

    <!-- My Dao in Test --> 
    <bean id="actionDefinitionDao" class="com.putnam.compliance.cme.dao.actions.jpa.ActionDefinitionDaoJpa"> 
     <property name="entityManagerFactory" ref="entityManagerFactory" /> 
    </bean> 

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 

      <property name="persistenceXmlLocation" value="classpath:persistence.xml" /> 
      <property name="persistenceUnitName" value="cmeJpa" /> 
      <property name="dataSource"    ref="dataSource"/> 

      <property name="jpaVendorAdapter"> 
       <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
        <property name="database"   value="ORACLE"/> 
        <property name="showSql"   value="true"/> 
        <property name="generateDdl"  value="false"/> 
        <property name="databasePlatform" value="org.hibernate.dialect.OracleDialect"/> 
       </bean> 
      </property> 

      <property name="jpaPropertyMap"> 
       <map> 
        <entry key="hibernate.transaction.flush_before_completion" value="true"/> 
        <entry key="hibernate.transaction.auto_close_session"  value="true"/> 
        <entry key="hibernate.current_session_context_class"  value="jta"/> 
        <entry key="hibernate.connection.release_mode"    value="auto"/>        
       </map> 
      </property> 

      <property name="jpaDialect"> 
       <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/> 
      </property> 

    </bean> 


    <!-- 
      DataSource to talk to Database Note: these values are pulled in by the .properties files 
    --> 
    <bean id="localDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" > 
     <property name="driverClassName" value="${dataSource.driverClassName}" /> 
     <property name="url"    value="${dataSource.url}" /> 
     <property name="username"  value="${dataSource.username}" /> 
     <property name="password"  value="${dataSource.password}" /> 
    </bean> 
    <alias name="localDataSource" alias="dataSource"></alias> 

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
     <property name="entityManagerFactory" ref="entityManagerFactory"/> 
     <property name="dataSource" ref="dataSource"/> 
    </bean> 

</bean> 

這裏是我的persistence.xml文件

<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0"> 
<!-- 
    <persistence-unit name="cmeJpa" transaction-type="JTA"> 
--> 
    <persistence-unit name="cmeJpa" transaction-type="RESOURCE_LOCAL"> 
      <class>com.putnam.compliance.cme.model.actions.ActionSequence</class> 
      <class>com.putnam.compliance.cme.model.actions.ActionDefinition</class> 
      <class>com.putnam.compliance.cme.model.actions.ActionXmlDefinition</class> 
      <exclude-unlisted-classes/> 
    </persistence-unit> 

</persistence> 

這裏是我的ActionDefinition JPA豆


@Entity 
@Table(name="PUT_M_DEFINITION") 
public class ActionDefinition implements java.io.Serializable { 


    public ActionDefinition() { 
    } 

    @Id 
    @Column(name="LISTENER_NAME") 
    public String getListenerName() { 
     return listenerName; 
    } 
    public void setListenerName(String n) { 
     listenerName = n; 
    } 
    @Column(name="CONTEXT") 
    public String getContext() { 
     return context; 
    } 
    public void setContext(String n) { 
     context = n; 
    } 
    @Column(name="DATA") 
    public String getData() { 
     return data; 
    } 
    public void setData(String n) { 
     data = n; 
    } 
    @Column(name="NOTES") 
    public String getNotes() { 
     return notes; 
    } 
    public void setNotes(String n) { 
     notes = n; 
    } 
    @Column(name="EMAIL_ID") 
    public String getEmailId() { 
     return emailId; 
    } 
    public void setEmailId(String n) { 
     emailId = n; 
    } 

    ... 
    ... 
} 

我已經玩過很多不同的組合,比如LocalContain的變化erEntityManagerFactoryBeanLocalEntityManagerFactoryBean

我得到了有關persistenceXmlLocation屬性不存在的運行時錯誤。

我也試過將persistance.xml文件中的交易類型更改爲「JTA」,但它似乎並沒有工作,實際上它已經破壞了它。

在這一點上,我掙扎着,不知道我的問題在哪裏。我再一次在JUnit中運行它,因此它不在任何容器內,並且可能在移至生產時。

任何指針,將不勝感激;謝謝

+0

放棄抗辯的整個堆棧跟蹤 - 這是最重要的事情.. – Bozho 2009-12-17 21:48:24

+0

我沒有收到StackTrace錯誤;返回的對象是完全相同的實例;見下文 ####列表= [[email protected] [ listenerName = DEF_TESTING 上下文= ListenerOne 數據=第一JUnit的 筆記輸出=這是純的JUnit測試。 [email protected] ],com.putnam.compliance.cme.model.actions。ActionDefinition @ 12b3349 [ listenerName = DEF_TESTING context = ListenerOne data = First JUnit notes =這是純粹的JUnit測試。 [email protected] ]] – 2009-12-18 13:39:16

回答

1

謝謝你給出的意見:我已經確定我的問題是什麼。我回來的ActionDefinition實例完全一樣的原因是因爲我的表包含複合主鍵。

下面是我如何解決我的模型對象的問題。我改變了我的模型對象包含一個名爲ActionDefinitionPK一個綜合類


@Entity 
@Table(name="PUT_M_DEFINITION") 
@IdClass(ActionDefinitionPK.class) 
public class ActionDefinition implements java.io.Serializable { 


    @Id 
    @Column (name="LISTENER_NAME") 
    private String listenerName  = null; 
    @Id 
    @Column (name="CONTEXT") 
    private String context   = null; 


    @Column (name="DATA") 
    private String data    = null; 
    @Column (name="NOTES") 
    private String notes   = null; 
    @Column (name="EMAIL_ID") 
    private String emailId   = null; 


這裏是綜合類和它的定義


@Embeddable 
public class ActionDefinitionPK implements java.io.Serializable { 


    @Column (name="LISTENER_NAME") 
    private String listenerName  = null; 
    @Column (name="CONTEXT") 
    private String context   = null; 

    /** 
    * Constructor 
    */ 
    public ActionDefinitionPK() { 
    } 
    public ActionDefinitionPK(String name, String context) { 
     setListenerName(name); 
     setContext(context); 
    } 
} 

Thanks to all those who provided help.