2009-12-17 6 views
1

J'utilise JPA/Spring/Hibernate comme mécanisme de persistance pour mon application. Actuellement, je suis confronté à des problèmes de tests unitaires où lorsque je demande des objets, je reçois la bonne quantité renvoyée par le DAO qui correspond au nombre de lignes dans la base de données, mais elles sont toutes exactement identiques. Voici la méthode findByName() qui me cause le problème.JPA Spring Hibernate Dao List problème

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

Cette méthode fonctionne sans erreur. Je suis en train de tester cela sur la couche DAO et non sur la couche Service, donc je n'ai aucune transaction introduite dans le test. Je ne sais pas si c'est transactionnel ou non. Si je prends le SQL que le JPA produit et l'exécute, j'obtiens le bon jeu de résultats de la base de données.

Voici mon fichier de configuration du printemps et le fichier 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> 

Voici mon fichier 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> 

Voici mon ActionDefinition JPA haricot


@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; 
    } 

    ... 
    ... 
} 

I ai joué avec beaucoup de différentes combinaisons comme le changement de LocalContain erEntityManagerFactoryBean à LocalEntityManagerFactoryBean.

J'ai rencontré des erreurs d'exécution à propos de la propriété persistenceXmlLocation non présente.

J'ai également essayé de changer le transaction-type dans le fichier persistance.xml à "JTA" qui n'a pas semblé fonctionner il l'a cassé réellement. À ce stade, je patauge et je ne sais pas où mon problème est. Encore une fois, je lance ceci dans JUnit afin qu'il ne se trouve dans aucun conteneur et peut être déplacé vers la production.

Des pointeurs seraient appréciés; merci

+0

donner toute stacktrace du exceptio - c'est la chose la plus importante .. – Bozho

+0

Je ne reçois pas une erreur StackTrace; Les objets qui reviennent sont exactement les mêmes instances; Voir ci-dessous la sortie #### List = [[email protected] [ listenerName = DEF_TESTING contexte = ListenerOne data = Première JUnit notes = Ceci est pour le test pur JUnit. [email protected] ], com.putnam.compliance.cme.model.actions.ActionDefinition @ 12b3349 [ listenerName = DEF_TESTING context = ListenerOne data = Premier JUnit notes = Ceci est pour le test pur JUnit. [email protected] ]] –

Répondre

1

Merci pour les commentaires: J'ai déterminé quel est mon problème. La raison pour laquelle je récupérais l'instance d'ActionDefinition qui était exactement la même était parce que ma table contenait une clé primaire composite.

Voici comment j'ai résolu mon problème avec mon objet modèle. J'ai changé mon modèle d'objet pour contenir une classe composite appelé 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; 


Voici la classe Composite et sa définition


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