2012-02-24 17 views
6

के लिए हाइबरनेट के साथ स्प्रिंग जेपीए अनुप्रयोगों को कॉन्फ़िगर करें मुझे एक स्प्रिंग एप्लिकेशन को कॉन्फ़िगर करने में समस्या है जो जेपीए का उपयोग यूनिट परीक्षण के लिए हाइबरनेट के साथ कर रहा है। मेरे पास उत्पादन के लिए 2 persistence.xml फ़ाइलें हैं और एक इकाई परीक्षण के लिए है। परीक्षण के लिए:यूनिट परीक्षण (आलसी लोडिंग)

<?xml version="1.0" encoding="UTF-8"?> 
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0"> 
    <persistence-unit name="prod_pu" transaction-type="JTA"> 
    <provider>org.hibernate.ejb.HibernatePersistence</provider> 
    <jta-data-source>jdbc/ds_prod</jta-data-source> 

    <properties> 
    <property name="hibernate.bytecode.use_reflection_optimizer" value="false"/> 
    <property name="hibernate.connection.driver_class" value="oracle.jdbc.OracleDriver"/> 
    <property name="hibernate.connection.password" value="passsample"/> 
    <property name="hibernate.connection.url" value="jdbc:oracle:thin:urlsample"/> 
    <property name="hibernate.connection.username" value="usernamesample"/> 
    <property name="hibernate.default_schema" value="schemassample"/> 
    <property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/> 
    </properties> 
    </persistence-unit> 

</persistence> 

परीक्षण के लिए:

<?xml version="1.0" encoding="UTF-8"?> 
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0"> 

<persistence-unit name="test_pu" transaction-type="RESOURCE_LOCAL"> 
    <provider>org.hibernate.ejb.HibernatePersistence</provider> 
    <properties> 
    <property name="hibernate.bytecode.use_reflection_optimizer" value="false"/> 
    <property name="hibernate.connection.driver_class" value="oracle.jdbc.OracleDriver"/> 
    <property name="hibernate.connection.password" value="passsample"/> 
    <property name="hibernate.connection.url" value="jdbc:oracle:thin:urlsample"/> 
    <property name="hibernate.connection.username" value="usernamesample"/> 
    <property name="hibernate.default_schema" value="schemasample"/> 
    <property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/> 
    </properties> 
    </persistence-unit> 

</persistence> 

अंतर मैं किसी भी JTA (वैश्विक लेन-देन), मैं केवल स्थानीय लेनदेन का उपयोग का उपयोग न इकाई परीक्षण में है।

उत्पादन के लिए वसंत विन्यास है:

<jee:jndi-lookup id="entityManagerFactory" jndi-name="persistence/ds_prod"/> 

<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> 
    <property name="entityManagerFactory" ref="entityManagerFactory"/> 
</bean> 

<bean id="persAnnoBeanPostProc" class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" > 
    <property name="persistenceUnits"> 
    <map> 
     <entry key="prod_pu" value="persistence/prod_pu"/> 
    </map> 
    </property> 
</bean> 

<context:annotation-config/> 
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/> 
<context:component-scan base-package="com.sample.packagename" /> 
<tx:jta-transaction-manager/> 

इकाई परीक्षण के लिए वसंत विन्यास:

<bean id="entityManagerFactory" 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <!-- This workaround is necessary because Spring is buggy 
    Instead of including the test-classes/META-INF the spring always search into classes/META-INF and ignores the one from test-classes 
    --> 
    <property name="persistenceXmlLocation" value="META-INF/persistence-test.xml" /> 
    <property name="persistenceUnitName" value="test_pu" /> 
</bean> 

    <bean id="persAnnoBeanPostProc" class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" > 
    </bean> 

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

    <context:annotation-config /> 
    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/> 
    <context:component-scan base-package="com.sample.packagename" /> 

यह मुझे मेरे इस विन्यास के लिए तय करने के लिए एक ही समय ले लिया है, अनुप्रयोगों वैश्विक लेनदेन क्योंकि जरूरत हमारे पास जेएमएस और डीबी के बीच लेनदेन है लेकिन यूनिट टेस्ट में मैं केवल स्थानीय लेनदेन को परिभाषित करता हूं इसलिए मैं आवेदन की जांच में सीमित हूं। इस सीमा के साथ मैं अपने यूनिट परीक्षण को परिभाषित करता हूं।

अब मुझे संबंधों के हाइबरनेट और लाज़ी लोडिंग में समस्या है। यूनिट परीक्षण में EntityManager सत्र विधियों को ढूंढने के बाद बंद हो रहा है और फिर LAZY लोडिंग के लिए प्रॉक्सी काम नहीं कर रहा है। (यह केवल हाइबरनेट में परिभाषा के अनुसार परिभाषित है) मेरी समस्या बीन पर्सिस्टेंसएनोटेशन बीनपोस्टप्रोसेसर है जिसमें यूनिट परीक्षणों के लिए कोई यूनिटनाम सेट है और जब भी वह एनोटेशन @PersistenceContext ढूंढ रहा है वह परीक्षण के लिए वसंत विन्यास में परिभाषित EntityManagerFactory से बनाई गई एक नई इकाई प्रबंधक को सम्मिलित कर रहा है।

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = {"classpath:testConfiguration.xml"}) 
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true) 
@Transactional 
public class ConnectionTest { 

    @PersistenceContext 
    EntityManager entityManager; 

    Logger log = Logger.getLogger(ConnectionTest.class); 

    @Resource(name = "syDbVersionDao") 
    SyDbVersionDao dbVersionDao; 

    @Test 
    public void testChanging() { 
    String oldVer = dbVersionDao.getCurrentVersion(); 
    assertNotNull(oldVer); 
    } 
} 


@Component 
public class SyDbVersionDao extends SyDbVersionHome { 

@PersistenceContext 
private EntityManager entityManager; 

    public String getCurrentVersion() { 
     SyDbVersion res = getLastRecord(); 

     if (res == null) return ""; 
     return res.getVersion(); 
    } 

    public SyDbVersion getLastRecord(){ 
     Query query = entityManager.createQuery("from SyDbVersion v order by v.installationDate desc"); 
     query.setMaxResults(1); 
     return (SyDbVersion) query.getSingleResult(); 
    } 
} 


/** 
* Home object for domain model class SyDbVersion. 
* @see com.tsystems.ac.fids.web.persistence.jpa.SyDbVersion 
* @author Hibernate Tools, generated! 
*/ 
@Stateless 
public class SyDbVersionHome { 

    private static final Log log = LogFactory.getLog(SyDbVersionHome.class); 

    @PersistenceContext private EntityManager entityManager; 

    public void persist(SyDbVersion transientInstance) { 
     log.debug("persisting SyDbVersion instance"); 
     try { 
     entityManager.persist(transientInstance); 
     log.debug("persist successful"); 
     } 
     catch (RuntimeException re) { 
     log.error("persist failed", re); 
     throw re; 
     } 
    } 

    public void remove(SyDbVersion persistentInstance) { 
     log.debug("removing SyDbVersion instance"); 
     try { 
     entityManager.remove(persistentInstance); 
     log.debug("remove successful"); 
     } 
     catch (RuntimeException re) { 
     log.error("remove failed", re); 
     throw re; 
     } 
    } 

    public SyDbVersion merge(SyDbVersion detachedInstance) { 
     log.debug("merging SyDbVersion instance"); 
     try { 
     SyDbVersion result = entityManager.merge(detachedInstance); 
     log.debug("merge successful"); 
     return result; 
     } 
     catch (RuntimeException re) { 
      log.error("merge failed", re); 
      throw re; 
     } 
    } 

    public SyDbVersion findById(long id) { 
     log.debug("getting SyDbVersion instance with id: " + id); 
     try { 
      SyDbVersion instance = entityManager.find(SyDbVersion.class, id); 
      log.debug("get successful"); 
      return instance; 
     } 
     catch (RuntimeException re) { 
     log.error("get failed", re); 
     throw re; 
     } 
    } 
    } 

वर्ग SyDbVersionHome डीबी और इकाई वर्ग भी से हाइबरनेट उपकरण के साथ उत्पन्न होता है: अब यूनिट परीक्षण एक @PersistenceContext entityManager सदस्य और डीएओ वर्ग भी हो रही है।

अब समस्या यह है: SyDbVersion instance = entityManager.find (SyDbVersion.class, id); हर बार जब मैं खोज विधि से वापस आ जाता हूं तो सत्र बंद हो जाता है इसलिए आलसी सदस्य अब और उपलब्ध नहीं होते हैं।

मैं दृढ़ता से निरंतर कॉन्फ़िगर करने के लिए एक तरीका सोच रहा था, निरंतर इकाई नाम के साथ बीनपोस्टप्रोसेसर लेकिन बीन जेएनडीआई में दृढ़ता इकाई खोज रहा है और मुझे दृढ़ता इकाई के लिए जेएनडीआई प्रविष्टि पंजीकृत करने का उचित समय नहीं मिल रहा है।

उत्पादन में क्योंकि मैंने लगातार दृढ़ता सेट किया है एंटीमेशन बीनपोस्टप्रोसेसर EntityManager को ठीक से साझा किया जाता है और सत्र खोजने के बाद हर बार बंद नहीं होता है।

एक और समाधान ओपनईजेबी या एम्बेडेड-ग्लासफ़िश का उपयोग यूनिट परीक्षणों में एक अनुप्रयोग सर्वर अनुकरण/करने के लिए करेगा (तब एकीकरण-परीक्षण बन जाएगा)।

यूनिट परीक्षण में इस समस्या से बचने के लिए मुझे वसंत कॉन्फ़िगरेशन में या कोड में संशोधित करने के लिए क्या विकल्प हैं?

उत्तर

1

मुझे अपने कोड की समस्या पता है। समस्या यह थी कि जब एप्लीकेशन कॉन्टेक्स्ट लोड किया गया था तो मैं बीन ऑब्जेक्ट में कुछ जेपीए इकाइयों को कैशिंग कर रहा था।बाद में परीक्षण विधि (दूसरे लेनदेन में) में मैं इस आलसी लोडिंग संबंधों को स्वीकार कर रहा था। बेशक यह डिज़ाइन द्वारा काम नहीं कर रहा है और आपको उसी लेनदेन संदर्भ में आलसी लोडिंग के साथ लोड किए गए संबंधों का उपयोग करना होगा अन्यथा आपको मेरे मामले में अपवाद मिलता है।

समाधान:

  1. उपयोग के बजाय आलसी लोड हो रहा है, उत्सुक लोड हो रहा है।

  2. इसे वापस करने से पहले आवश्यक सभी संगठनों और संग्रहों को स्पष्ट रूप से प्रारंभ करना। फिर आप उन्हें दूसरे लेनदेन में भी एक्सेस कर सकते हैं।

    नोड एन = // .. नोड मिल

    Hibernate.initialize (एन); // get parent के समान 'पैरेंट' प्रारंभ करता है।

    Hibernate.in आरंभ करें (n.getChildren()); // प्रारंभिक होने के लिए सत्र में आलसी संग्रह पास करें।

  3. सत्र/लेनदेन को तब तक खोलने की कोशिश करें जब तक आपको इसकी आवश्यकता न हो। मेरे मामले में वास्तव में संभव नहीं है और कोई मतलब नहीं है।

संबंधित मुद्दे