Hibernate ("showSql", "true") in javaconfig doesn't work - java

I use JPA with Hibernate as persistence provider, and I configure it with below configuration class.
The problem is that I never see SQL statements compiled by Hibernate though I have showSql=true in additional properties. Please check below. Now it is properties.setProperty("hibernate.showsql", "true");, but I also tried properties.setProperty("showSql", "true"); with no effect.
I don't have persistence.xml and I don't use root-context.xml.
My servlet-context.xml contains only
<mvc:annotation-driven />
<beans:bean
class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<task:annotation-driven />
Also, my meta-inf/log4j.xml has all loggers on INFO level including
<logger name="org.hibernate.SQL">
<level value="info" />
</logger>
which I added without any effect as well.
What am I doing wrong?
#Configuration
#EnableTransactionManagement
#ComponentScan("com")
public class MySQLconfiguration {
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(new String[] { "com" });
em.setPersistenceProviderClass(HibernatePersistenceProvider.class);
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
#Bean(destroyMethod = "close")
public DataSource dataSource(){
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setDriverClassName("com.mysql.jdbc.Driver");
hikariConfig.setJdbcUrl("jdbc:mysql://localhost:3306/test");
hikariConfig.setUsername("user");
hikariConfig.setPassword("user");
hikariConfig.setMaximumPoolSize(5);
hikariConfig.setMaxLifetime(30000);
hikariConfig.setIdleTimeout(30000);
hikariConfig.setConnectionTestQuery("SELECT 1");
hikariConfig.setPoolName("springHikariCP");
hikariConfig.addDataSourceProperty("dataSource.cachePrepStmts", "true");
hikariConfig.addDataSourceProperty("dataSource.prepStmtCacheSize", "250");
hikariConfig.addDataSourceProperty("dataSource.prepStmtCacheSqlLimit", "2048");
hikariConfig.addDataSourceProperty("dataSource.useServerPrepStmts", "true");
HikariDataSource dataSource = new HikariDataSource(hikariConfig);
return dataSource;
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
return new PersistenceExceptionTranslationPostProcessor();
}
Properties additionalProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.hbm2ddl.auto", "update");
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLInnoDBDialect");
properties.setProperty("hibernate.archive.autodetection", "class");
properties.setProperty("hibernate.showSql", "true");
return properties;
}
}

The property key should be hibernate.show_sql, not hibernate.showSql.
To verify, you can take a look at Hibernate class AvailableSettings, which lists the available configuration options, one of which is:
/**
* Enable logging of generated SQL to the console
*/
String SHOW_SQL = "hibernate.show_sql";

Related

Hibernate Spring: spring.jpa.hibernate.ddl-auto property doesn't create generate tables doesn't work

I'm using Spring MVC with Hibernate. I configure Hibernate using configuration Java class:
DbConfig.java:
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(basePackages = "testproject", entityManagerFactoryRef = "entityManagerFactory")
public class DbConfig {
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(getDatasource());
entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
entityManagerFactoryBean.setJpaProperties(getHibernateProperties());
entityManagerFactoryBean.setPackagesToScan("testproject");
return entityManagerFactoryBean;
}
#Bean
public DataSource getDatasource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.postgresql.Driver");
dataSource.setUrl("jdbc:postgresql://127.0.0.1:5432/testproject");
dataSource.setUsername("postgres");
dataSource.setPassword("mypass");
return dataSource;
}
#Bean
public SessionFactory getSessionFactory() throws IOException {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setPackagesToScan("testproject");
//getHibernateProperties method is a private method
sessionFactoryBean.setHibernateProperties(getHibernateProperties());
sessionFactoryBean.setDataSource(getDatasource());
sessionFactoryBean.afterPropertiesSet();
return sessionFactoryBean.getObject();
}
#Bean(name = "transactionManager")
public HibernateTransactionManager getTransactionManager() throws IOException {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(getSessionFactory());
return transactionManager;
}
private static Properties getHibernateProperties() {
Properties hibernateProperties = new Properties();
hibernateProperties.put("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
hibernateProperties.put("hibernate.show_sql", false);
hibernateProperties.put("spring.jpa.hibernate.ddl-auto", "create");
System.out.println();
// other properties
return hibernateProperties;
}
}
The auto-creation of tables is configured inside getHibernateProperties method:
hibernateProperties.put("spring.jpa.hibernate.ddl-auto", "create");
However it doesn't seem to work: after I deploy server and try to insert an entity I get an error and the database has no tables.
The property spring.jpa.hibernate.ddl-auto is of type org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.Hibernate which is from Spring Boot. But you are using Spring MVC.
use hibernate.hbm2ddl.auto instead.
Further Reading
Metadata Format in Spring Boot Reference
This is the properties code that works:
#Bean
private static Properties getHibernateProperties() {
Properties hibernateProperties = new Properties();
hibernateProperties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
hibernateProperties.put("hibernate.show_sql", true);
hibernateProperties.put( "hibernate.hbm2ddl.auto", "create-drop");
return hibernateProperties;
}

org.hibernate.LazyInitializationException in spring data jpa

I met 'org.hibernate.LazyInitializationException: could not initialize proxy - no Session' in spring data jpa.
Below is my code.
// this is service layer
#Transactional(rollbackFor = Exception.class)
public BlogEntity saveBlog(BlogEntity blogEntityInput) {
BlogEntity blogEntity = blogDao.find(blogEntityInput.getId());
System.out.println(blogEntity);
return blogDao.saveBlog(blogEntityInput);
}
// this is dao layer which will call
#Override
public BlogEntity find(Integer id) {
return blogRepository.getOne(id); // JpaRepository#getOne
}
The exception will occur when I print the blogEntity after I call getOne. I know that getOne is lazy loaded.
But I have already add the #Transactional which will ensure the inner method will be in a hibernate session. How could the LazyInitializationException still occur?
Thanks.
Below is my full database related spring code.
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(
entityManagerFactoryRef = "h2_entityManagerFactory",
basePackages = { "com.taobao.rest.repository.h2" },
transactionManagerRef = "h2_manager"
)
public class H2DBConfig {
#Primary
#Bean(name = "h2_dataSource")
public DataSource dataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl("jdbc:h2:~/new-taobao");
dataSource.setUsername("taobao");
dataSource.setPassword("");
return dataSource;
}
#Primary
#Bean(name = "h2_entityManagerFactory")
public LocalContainerEntityManagerFactoryBean h2EntityManagerFactory() {
LocalContainerEntityManagerFactoryBean em
= new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(new String[] { "com.taobao.rest.entity.h2" });
em.setPersistenceUnitName("h2_unit");
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
Properties additionalProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.hbm2ddl.auto", "update");
properties.setProperty(
"hibernate.dialect", "org.hibernate.dialect.H2Dialect");
properties.setProperty("hibernate.show_sql", "true");
return properties;
}
#Bean(name = "h2_manager")
public PlatformTransactionManager transactionManager(
#Qualifier("h2_entityManagerFactory") EntityManagerFactory emf){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
}

Hibernate does not create tables - Spring Boot

I set spring.jpa.hibernate.ddl-auto = update but when I run spring boot the tables are not created. I want it to update the bank automatically.
Some settings:
application.properties:
## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url = jdbc:mysql://localhost:3306/pell
spring.datasource.username = daniel
spring.datasource.password = root
## Hibernate Properties
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = update
spring.jpa.show-sql = true
Some beans:
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/pell");
dataSource.setUsername("daniel");
dataSource.setPassword("root");
factoryBean.setDataSource(dataSource);
factoryBean.setPackagesToScan(new String[] {"eu.pell.models"});
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
factoryBean.setJpaVendorAdapter(vendorAdapter);
Properties properties = new Properties();
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
properties.setProperty("hibernate.ddl-auto", "update");
properties.setProperty("hibernate.show_sql", "true");
factoryBean.setJpaProperties(properties);
return factoryBean;
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}

Change datasource properties for JPA Spring Configuration during runtime

I am working on a Spring project that needs to connect to multiple databases.
The examples I have used are all connecting to one database using properties, set at the start of the application.
My current JPA configuration looks like this:
#Configuration
#EnableTransactionManagement
public class PersistenceJPAConfig{
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(new String[] { "com.google.persistence.model" });
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
#Bean
public DataSource dataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/spring_jpa");
dataSource.setUsername( "user" );
dataSource.setPassword( "password" );
return dataSource;
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation(){
return new PersistenceExceptionTranslationPostProcessor();
}
Properties additionalProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
return properties;
}
}
In this case, the datasource properties (driver, url, username, password) are already set. But is it possible to modify this current bean or create a new method that would allow me to modify those properties during runtime?
For example, while the application is running, is there a way for me to manually disconnect from the current database, modify the datasource properties, and reconnect to the new database instead?
You can't change this properties in runtime but if you need to use multiple databases you can create multiple persistence units. Here you can find example:
http://www.baeldung.com/spring-data-jpa-multiple-databases
The feature you're looking for is called multi-tenancy.
See, for example, this guide.

New Spring Boot #EntityScan doesn't work

As of Spring ORM v1.4 org.springframework.boot.orm.jpa.EntityScan was deprecated in favor of org.springframework.boot.autoconfigure.domain.EntityScan.
I was going to remove deprecated annotation in favor of new one, but such replacement cause IllegalStateException:
Caused by: java.lang.IllegalStateException: No persistence units parsed from {classpath*:META-INF/persistence.xml}
at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.obtainDefaultPersistenceUnitInfo(DefaultPersistenceUnitManager.java:680) ~[spring-orm-4.3.5.RELEASE.jar:4.3.5.RELEASE]
With org.springframework.boot.orm.jpa.EntityScan annotation, application starts and works correctly.
Here is my config:
#Configuration
#EntityScan("com.app.domain")
#EnableJpaRepositories("com.app.persistence.jpa")
public class JpaInfrastructureConfig {
// ... config props
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(driverName);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
entityManagerFactory.setJpaVendorAdapter(vendorAdapter);
entityManagerFactory.setDataSource(dataSource());
entityManagerFactory.setJpaProperties(new Properties() {{
put("hibernate.dialect", hibernateDialect);
put("hibernate.show_sql", hibernateShowSql);
put("hibernate.hbm2ddl.auto", hibernateHbm2ddl);
}});
return entityManagerFactory;
}
#Bean
public JpaTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
// ...
}
It seams that I've missed something, haven't I?
If you take a look at this issue on Spring Boot's issue tracker, you'll find the behaviour changes with the new annotation, as now documented in the release notes.
In your example, the simplest change would be to add a line to call LocalContainerEntityManagerFactoryBean.setPackagesToScan(…​), as suggested in the release notes.

Categories