如何在Spring 4 hibernate 5中使用Persistence EntityManager和SessionFactory?

时间:2017-02-28 11:55:02

标签: java spring hibernate entitymanager

我在我的DAOImpl文件中使用sessionFactory自动装配它。 在我开始面对某些DAO方法中的"太多的数据库连接" 问题之前,情况一直很好。在搜索了可能的原因和解决方案后,我意识到我可能错误地配置了applicationContext.xml我使用EntityManager的方式不正确

以下是我的 applicationContext.xml 文件内容:

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

以下是关于我如何使用EntityManager的DAOImpl代码示例,但是我觉得它不正确。

@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

此时我很难避免sessionFactory ,因为我已经在我的项目中使用了它。无论如何我可以配置我的xml文件以允许我一起使用EntityManager以及SessionFactory吗?

我看到了几个配置EntityManager的示例,但没有一个在SessionFactory的xml文件中添加任何行。所以我对此很困惑。

1 个答案:

答案 0 :(得分:0)

使用LocalContainerEntityManagerFactoryBean创建EntityManager而不是使用LocalSessionFactoryBean,因此您没有致电sessionFactory.getCurrentSession().getEntityManagerFactory().createEntityManager()来获取entityManager

  1. 在Spring配置文件中,将此当前配置替换为:
  2. <!-- 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. 像这样使用:
    2. @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();
      
              // ...
      
      }
      

      修改:按以下步骤更新您的配置:

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