2017-02-28 1 views
0

Ich benutzte sessionFactory, indem ich es in meinen DAOImpl-Dateien autowiring. Die Dinge funktionierten gut, bis ich anfing eine Ausgabe von "Too many Datenbankverbindungen" in bestimmten DAO-Methoden. Nach der Suche nach möglichen Gründen und Lösungen, erkannte ich, dass ich möglicherweise falsch konfiguriert applicationContext.xml und die Art, wie ich EntityManager ist inkorrekt.Wie Persistence EntityManager zusammen mit SessionFactory im Frühjahr 4 Hibernate 5 verwenden?

Unten ist mein applicationContext.xml Dateiinhalt:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc" 
    xsi:schemaLocation=" 
     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd 
     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd 
     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd 
     http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd 
     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd"> 

    <!-- Enables the Spring MVC @Controller programming model --> 

    <!-- enables cors (cross origin request) for all urls --> 
    <mvc:cors> 
     <mvc:mapping path="/**" /> 
    </mvc:cors> 

    <!-- <mvc:annotation-driven /> --> 

    <mvc:annotation-driven> 
     <mvc:message-converters> 
      <!-- Use the HibernateAware mapper instead of the default --> 
      <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> 
       <property name="objectMapper"> 
        <bean class="com.typjaipur.core.objectmapper.HibernateAwareObjectMapper" /> 
       </property> 
      </bean> 
     </mvc:message-converters> 
    </mvc:annotation-driven> 

    <context:component-scan base-package="com.typjaipur" /> 

    <bean id="messageSource" 
     class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> 
     <property name="basename" value="classpath:messages" /> 
     <property name="defaultEncoding" value="UTF-8" /> 
    </bean> 

    <bean id="propertyPlaceholder" class="com.typjaipur.core.config.EnvironmentPropertyPlaceholderConfigurer"> 
     <property name="locations"> 
      <list> 
       <value>classpath:jdbc.properties</value> 
       <value>classpath:core.properties</value> 
       <value>classpath:mailer.properties</value> 
      </list> 
     </property> 
    </bean> 

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
     <property name="prefix" value="/WEB-INF/jsp/" /> 
     <property name="suffix" value=".jsp" /> 
    </bean> 

    <bean id="dataSource" 
     class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
     <property name="driverClassName" value="${driver}" /> 
     <property name="url" value="${url}" /> 
     <property name="username" value="${username}" /> 
     <property name="password" value="${password}" /> 
    </bean> 

    <bean id="sessionFactory" 
     class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> 
     <property name="dataSource" ref="dataSource" /> 
     <property name="packagesToScan" value="com.typjaipur.model" /> 
     <property name="hibernateProperties"> 
      <props> 
       <prop key="hibernate.max_fetch_depth">3</prop> 
       <prop key="hibernate.default_batch_fetch_size">4</prop> 
       <prop key="hibernate.jdbc.fetch_size">50</prop> 
       <prop key="hibernate.jdbc.batch_size">20</prop> 
       <prop key="hibernate.dialect">${hibernate.dialect}</prop> 
       <prop key="hibernate.show_sql">${hibernate.show_sql}</prop> 
       <prop key="hibernate.format_sql">${hibernate.format_sql}</prop> 
      </props> 
     </property> 
    </bean> 

    <bean id="hibernateTransactionManager" 
     class="org.springframework.orm.hibernate5.HibernateTransactionManager"> 
     <property name="sessionFactory" ref="sessionFactory" /> 
    </bean> 

    <tx:annotation-driven transaction-manager="hibernateTransactionManager" /> 

    <mvc:interceptors> 
     <bean class="org.springframework.orm.hibernate5.support.OpenSessionInViewInterceptor"> 
      <property name="sessionFactory"> 
       <ref bean="sessionFactory" /> 
      </property> 
     </bean> 
     <mvc:interceptor> 
      <mvc:mapping path="/**" /> 
      <!-- excluded urls --> 
      <mvc:exclude-mapping path="/" /> 
      <bean class="com.typjaipur.interceptor.ApiAuthenticationInterceptor" /> 
     </mvc:interceptor> 
    </mvc:interceptors> 


    <!-- Enables swgger ui --> 
    <mvc:resources mapping="swagger-ui.html" location="classpath:/META-INF/resources/" /> 
    <mvc:resources mapping="/webjars/**" 
     location="classpath:/META-INF/resources/webjars/" /> 

    <!-- Include a swagger configuration --> 
    <bean name="/applicationSwaggerConfig" class="com.typjaipur.config.SwaggerConfig" /> 

    <bean id="multipartResolver" 
     class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> 
     <!-- one of the properties available; the maximum file size in bytes --> 
     <!-- <property name="maxUploadSize" value="100000"/> --> 
    </bean> 
</beans> 

Unten ist DAOImpl Codebeispiel dafür, wie ich bin mit EntityManager, die auch funktioniert, aber ich fühle es nicht vielleicht richtig.

@Repository 
public class BusinessDetailsDAOImpl extends BaseDAOImpl<BusinessDetails, Long> implements BusinessDetailsDAO { 

    @Autowired 
    private SessionFactory sessionFactory; 

    @Override 
    public List<BusinessDetails> searchBusiness(BusinessSearchDTO businessSearchDTO, List<Long> businessIds) { 

     EntityManager entityManager = sessionFactory.getCurrentSession().getEntityManagerFactory().createEntityManager(); 
     CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); 
     CriteriaQuery<BusinessDetails> query = criteriaBuilder.createQuery(BusinessDetails.class); 
     Root<BusinessDetails> businessDetails = query.from(BusinessDetails.class); 

     List<Predicate> predicates = new ArrayList<Predicate>(); 
...//rest of code 

Es ist hart für mich sessionFactory an dieser Stelle zu vermeiden, da ich alles über mein Projekt verwendet haben. Gibt es trotzdem, über die ich meine XML-Datei konfigurieren kann, damit ich EntityManager sowie SessionFactory zusammen verwenden kann?

Ich sah mehrere Beispiele für die Konfiguration EntityManager, aber keiner von ihnen hat eine Zeile in xml-Datei im Zusammenhang mit SessionFactory hinzugefügt. Ich bin also verwirrt.

+0

Das Problem wird durch selbst eingeführt. Yuo erstellt selbst Entity Manager-Instanzen, die jeweils eine neue 'Connection' nehmen. Sie verwalten die Entity Manager nicht und irgendwann werden Sie auslaufen. Eine andere Sache, die 'DriverManagerDataSource' nicht verwendet, die zum Testen nicht für die Produktionsnutzung geeignet ist, verwenden einen richtigen Verbindungspool. –

+0

Was wird für 'DriverManagerDataSource' empfohlen? Kannst du es bitte erzählen? –

+0

Wie bereits erwähnt, gibt es verschiedene Optionen. –

Antwort

0

LocalContainerEntityManagerFactoryBean Verwenden EntityManager statt LocalSessionFactoryBean der Verwendung zu erstellen, so dass Sie sessionFactory.getCurrentSession().getEntityManagerFactory().createEntityManager() haben nicht Aufruf der entityManager zu bekommen: diese aktuelle Konfiguration ersetzen

  1. Im Frühjahr Konfigurationsdatei mit:
<!-- Create a datasource --> 
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 

    <property name="driverClassName" value="${driver}" /> 
    <property name="url" value="${url}" /> 
    <property name="username" value="${username}" /> 
    <property name="password" value="${password}" /> 

</bean> 

<!-- Create an Hibernate to Jpa adapter --> 
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 

    <property name="generateDdl" value="true" /> 
    <property name="showSql" value="false" /> 
    <property name="database" value="MYSQL" /> 

</bean> 

<!-- persistenceUnitManager is optional --> 
<bean id="persistenceUnitManager" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager"> 

    <property name="defaultDataSource" ref="dataSource"/> 

</bean> 

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

    <property name="persistenceUnitManager" ref="persistenceUnitManager"/> 
    <property name="jpaVendorAdapter" ref="jpaVendorAdapter" /> 

    <property name="jpaProperties"> 
     <props> 
      <prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop> 
      <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> 
     </props> 
    </property> 

</bean> 

<!-- and create transactionManager --> 
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="entityManagerFactory"/> 
</bean> 
  1. Verwenden Sie es wie folgt:
@Repository 
public class BusinessDetailsDAOImpl extends BaseDAOImpl<BusinessDetails, Long> implements BusinessDetailsDAO { 

    @PersistenceContext 
    protected EntityManager entityManager; 

    @Override 
    public List<BusinessDetails> searchBusiness(BusinessSearchDTO businessSearchDTO, List<Long> businessIds) { 

     // use directly entityManager instead of sessionFactory.getCurrentSession().getEntityManagerFactory().createEntityManager(); 

     CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); 

     // ... 

} 

Edit: Aktualisieren Sie Ihre Konfiguration wie folgt:

<property name="jpaProperties"> 
    <props> 
     <prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop> 
     <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> 

     <!-- add this line --> 
     <prop key="hibernate.enable_lazy_load_no_trans">true</prop> 
    </props> 
</property> 
+0

und wie kann ich 'OpenSessionInViewInterceptor' mit dieser Konfiguration verwenden? –

+0

Da Sie Hibernate 4 verwenden, brauchen Sie nicht mehr 'OpenSessionInViewInterceptor', sondern setzen Sie einfach die folgende Eigenschaft 'hibernate.enable_lazy_load_no_trans' auf' true' und Hibernate sorgt dafür, dass die Sitzung für Sie erstellt wird, wann immer sie benötigt wird. –

+0

Hibernate 4? Ich benutze Hibernate 5. Not 4. –

Verwandte Themen