2015-10-02 2 views
0

Я использую Spring + Hibernate в своем проекте JavaEE.Сброс соединения с использованием Spring + Hibernate

В этом проекте пользователь может загрузить файл XLS, который я должен импортировать в свою базу данных. Перед импортом я должен проверить этот файл, проверяя его целостность с другими объектами в моей базе данных. Так что у меня более или менее следующее:

// The importer 
@Component("importer") 
public class Importer { 

    @Autowired 
    FirstDAO firstDao; 

    @Autowired 
    SecondDAO secondDao; 

    // Read the file and open it (65.000 lines for example) 

    public void validate() { 

     foreach line in the file { 
      firstDAO.has(line[col1]); 
      secondDao.has(line[col2]); 
     } 

     // It stores the valid objects in a List and persist them at the end 

    } 
} 

// The DAO 
@Repository 
public class FirstDao { 

    @PersistenceContext 
    protected EntityManager entityManager; 

    @Transactional(propagation = Propagation.NOT_SUPPORTED) 
    public boolean has(String name) { 

     List<Object> result = entityManager.createQuery(from FIRST_TABLE where name = :name) 
     .setParameter("name", name) 
     .getResultList(); 

     if (result.size > 0) return true; 
     else return false; 
    } 

} 

// The PersistenceContext/Hibernate configuration 

<!-- Data Source --> 
<jee:jndi-lookup id="myDS" jndi-name="jdbc/my-DS" cache="true" proxy-interface="javax.sql.DataSource" /> 

<!-- Entity Manager --> 
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property value="classpath:META-INF/my_persistence.xml" name="persistenceXmlLocation"/> 
    <property name="dataSource" ref="myDS"/> 
    <property name="persistenceUnitName" value="myPersistenceUnit" /> 
    <!-- 
    <property name="loadTimeWeaver"> 
     <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/> 
    </property> 
    --> 
    <property name="jpaVendorAdapter"> 
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
      <property name="database" value="ORACLE" /> 
      <property name="showSql" value="false" /> 
     </bean> 
    </property> 
</bean> 

После входа в приложение, я заметил:

  • Для каждого запроса (есть метод в моем DAO) открывается соединение и закрывается с моей базой данных.
  • Память на сервере затоплена (возможно, утечка памяти).
  • После многих открытий и закрытий соединений у меня есть соединение с базой данных. Не знаю, почему. И если я все еще продолжаю запрашивать coonections, Datasource приостанавливается.

Я прочитал нечто о entityManager, но я до сих пор не знаю, если я делаю это правильно, так:

  • Правильно ли выполнить проверку в цикле таким образом? (Одно соединение для каждого элемента, т.е. 130 000 соединений открываются и закрываются в файле с файлами 65000)
  • Я прочитал о Stateless Persistence Context для entityManager. Я подозреваю, что утечка памяти может быть там. Возможно, Hibernate хранит много объектов в PersistenceContext. Как я могу сказать, что Entity Manager не кэшировал этих парней при проверке?

Заранее спасибо.

+0

Ваш вопрос звучит как список вопросов. Но о подключении к БД для каждой строки файла, что сильно снизит производительность вашей системы. Не можете ли вы выполнить итерацию по всему файлу, загрузить его в память и запустить один оператор select, чтобы получить данные db, которые нужно сравнить с загруженным файлом? Загрузите все данные в память, а затем верните все сразу. Возможно, вам придется сначала исправить проблему утечки памяти. – wdoering

ответ

0

Прежде всего, вам действительно не следует делать это за строкой, если у вас нет очень веской причины. Даже если размер данных больше, чем ваша память, вы должны делать это 1000 строк за раз или что-то в этом роде, но определенно не один за другим. Поскольку одна из самых важных оптимизаций для использования базы данных - это сокращение числа ударов по базе данных.

Во-вторых, вы не должны извлекать данные, чтобы проверить, существует ли он. Вы должны использовать базовый запрос «select count». Таким образом, вы избавитесь от всех вещей, таких как потребление IO, для чтения данных и извлечения этих данных через сеть на ваш сервер и расходования памяти, чтобы просто получить количество объектов в этом списке.

Если вы воспользуетесь моим первым советом и проверьте существующие записи не по одному за один раз, а за 1000 секунд, вы можете выбрать только имена вместо всех строк.

Кстати, насколько я вижу, вы используете источник данных, если он правильно настроен как номер максимального соединения и т. Д. Вам не стоит беспокоиться о количестве соединений с базой данных.

Смежные вопросы