Spring Hibernate JPA Konfiguration

Vor jedem neuen Software Projekt mit Datenbankanbindung kommt man immer wieder in die Situation eine funktionierende Spring Hibernate JPA Konfiguration zu erstellen. Daher habe ich einmal eine Basis-Konfiguration erstellt, die ich in fast allen Projekten verwende und entsprechend anpassen kann.

Als Erstes wird die Datenquelle konfiguriert. Hier wird die bereits beschriebene Umgebungsunabhängige Konfiguration verwendet. Für die Kommunikation mit der Datenbank verwende ich Apache Commons DBCP. Die hier gezeigten Einstellungen sind ein Beispiel für eine MySQL Datenbank.

@Bean
public DataSource dataSource() throws Exception {
    BasicDataSource dataSource = new BasicDataSource();
    dataSource.setDriverClassName(configuration().getString(ConfigurationKeyImpl.CONFIGURATION_PARAM_DATASOURCE_DRIVERCLASSNAME));
    dataSource.setUrl(configuration().getString(ConfigurationKeyImpl.CONFIGURATION_PARAM_DATASOURCE_URL));
    dataSource.setUsername(configuration().getString(ConfigurationKeyImpl.CONFIGURATION_PARAM_DATASOURCE_USERNAME));
    dataSource.setPassword(configuration().getString(ConfigurationKeyImpl.CONFIGURATION_PARAM_DATASOURCE_PASSWORD));
    dataSource.setRemoveAbandoned(true);
    dataSource.setRemoveAbandonedTimeout(300);
    dataSource.setTestOnBorrow(true);
    dataSource.setTestWhileIdle(true);
    dataSource.setInitialSize(5);
    dataSource.setPoolPreparedStatements(true);
    dataSource.setValidationQuery("SELECT 1");
    dataSource.setMaxActive(40);

    return dataSource;
}

Im nächsten Schritt wird nun Hibernate mit JPA aufgesetzt. Zusätzlich verwende ich die Klasse IsolationSupportHibernateJpaDialect, beschrieben in Shahzad Mughal’s Tech Blog: Spring JPA Hibernate: Support for custom Isolation Level, um auch in JPA Unterstützung für Isolation.READ_UNCOMMITTED zu haben. Die Konfiguration ist ein Beispiel für eine Verbindung mit einer MySQL 5 Datenbank.

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws Exception {
    JpaDialect jpaDialect = new IsolationSupportHibernateJpaDialect();

    Properties jpaProperties = new Properties();
    jpaProperties.setProperty("hibernate.hbm2ddl.auto", "validate");
    jpaProperties.setProperty("hibernate.ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy");
    jpaProperties.setProperty("hibernate.connection.charSet", "UTF-8");
    jpaProperties.setProperty("hibernate.showSql", "false");
    jpaProperties.setProperty("hibernate.format_sql", "false");
    jpaProperties.setProperty("hibernate.cache.use_query_cache", "false");
    jpaProperties.setProperty("hibernate.cache.use_second_level_cache", "false");
    jpaProperties.setProperty("hibernate.generate_statistics", "true");
    jpaProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");

    HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
    jpaVendorAdapter.setShowSql(false);
    jpaVendorAdapter.setGenerateDdl(false);

    LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
    entityManagerFactoryBean.setDataSource(dataSource());
    entityManagerFactoryBean.setJpaDialect(jpaDialect);
    entityManagerFactoryBean.setJpaProperties(jpaProperties);
    entityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter);
    entityManagerFactoryBean.setPackagesToScan("de.volkerfaas.common.entity");
    entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);

    return entityManagerFactoryBean;
}

Der Aufruf der Methode setPackagesToScan muss entsprechend auf das Paket verweisen, in welchem sich die Hibernate Entitäten befinden. Ich selbst achte bei meinen Projekten stets darauf, dass sich alle verwendeten Entitäten immer unterhalb eines einzigen Paketes befinden.

Das Caching habe ich in den meisten Fällen deaktiviert, da ich versuche eine hohe Performance durch Tuning der Datenbank, z.B. durch Setzen von Indizes, zu erreichen.

Der Parameter „hibernate.hbm2ddl.auto“ sollte in einer Produktionsumgebung immer auf „validate“ stehen, um zu vermeiden, dass bereits bestehende Daten überschrieben werden. Mögliche Werte sind hier:

  • validate: Überprüft das Schema, nimmt keine Änderungen an der Datenbank vor.
  • update: Aktualisiert das Schema.
  • create: Erstellt das Schema neu und löscht alle existierenden Daten.
  • create-drop: Erstellt das Schema neu und löscht es nach Beendigung der Session.

Zuletzt wird noch der Transaktionsmanager konfiguriert. Da ich in meinen Projekten JPA verwende kommt hier der JpaTransactionManager zum Einsatz.

@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactory);

    return transactionManager;
}

Hiermit hat man eine funktionierende Spring Hibernate JPA Konfiguration, die dann im Detail an die Anforderungen eines Software Projektes angepasst werden kann.

Schreibe einen Kommentar