Hibernate error when hbm2ddl.auto is update - java

#Configuration
#EnableTransactionManagement
#ComponentScans(value = {
#ComponentScan("org.kalifornia.fridgeapp.DAO"),
#ComponentScan("org.kalifornia.fridgeapp.service")
} )
#PropertySource("classpath:mysql.properties")
public class HibernateConfig {
#Autowired
private ApplicationContext context;
#Autowired
private Environment env;
#Bean
public LocalSessionFactoryBean getSessionFactory()
{
LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
try
{
factoryBean.setHibernateProperties(hibernateProperties());
factoryBean.afterPropertiesSet();
factoryBean.setDataSource(restDataSource());
factoryBean.setAnnotatedClasses(FridgeUser.class);
factoryBean.setAnnotatedClasses(Community.class);
factoryBean.setAnnotatedClasses(Container.class);
factoryBean.setAnnotatedClasses(Item.class);
factoryBean.setAnnotatedClasses(Product.class);
} catch(IOException exception) {
System.out.print(exception.fillInStackTrace());
return null;
}
return factoryBean;
}
#Bean
public DataSource restDataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/fridge");
dataSource.setUsername("root");
dataSource.setPassword("kaszanka");
return dataSource;
}
#Bean
public HibernateTransactionManager getTransactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(getSessionFactory().getObject());
return transactionManager;
}
Properties hibernateProperties() {
return new Properties() {
{
setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
setProperty("show_sql", "true");
setProperty("hibernate.hbm2ddl.auto", "update");
}
};
}
}
I wrote that code from tutorial and it works now but when I try to change a hbm2ddl.auto from create to update I get this error:
$Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'DAOImpl': Unsatisfied dependency expressed through field 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'getSessionFactory' defined in org.kalifornia.fridgeapp.spring.config.HibernateConfig: Invocation of init method failed; nested exception is java.lang.UnsupportedOperationException: Not supported by BasicDataSource

According to your log nested exception is java.lang.UnsupportedOperationException: Not supported by BasicDataSource seems like an issue with BasicDataSource, try changing it to DriverManagerDataSource because it may be the case that BasicDataSource doesn't support hibernate.hbm2ddl.auto = update

Related

Bean is expected to be of type 'CourseDAO' but was actually of type 'com.sun.proxy.$Proxy49'

In a training Spring MVC + JPA/Hibernate project, I'm getting the error in question, after I've changed my configuration.
Originally the DAO class was like this:
public Course getById(Integer id) throws DAOException {
Course result = null;
try {
EntityManager em = emf.getFactory().createEntityManager();
result = em.find(Course.class, id);
} catch (Exception e) {
logger.error(e.getMessage(), e);
throw new DAOException("Could not get Course By Id", e);
}
return result;
}
I was told to spawn EntityManager with #PersistenceContext, and avoid creating new EntityManager every now and then. So I replaced the above EntityManager em = ... line with a #Autowired EntityManager em; field, and changed the JpaConfig class, so it looks like:
#Configuration
#ComponentScan(basePackages = "com.example.school")
#PropertySource("classpath:database.properties")
#EnableTransactionManagement
public class JpaConfig {
private final Environment environment;
#Autowired
public JpaConfig(Environment environment) {
this.environment = environment;
}
#Autowired
DataSource dataSource;
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws NamingException {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan("com.example.school");
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
return em;
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
}
While previously the configuration file was that simple:
#Configuration
public class EntityManagerConfig {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("PU");
#Bean
EntityManager em() {
return emf.createEntityManager();
}
}
Now I get a stacktrace with the following most important problem in it:
org.springframework.beans.factory.UnsatisfiedDependencyException ...
...
Caused by: org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'courseDAO' is expected to be of type 'com.example.school.dao.CourseDAO' but was actually of type 'com.sun.proxy.$Proxy49'
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1317)
What can be wrong about this configuration?

How to configure Datasource using #Bean in Java class

I'm following an example in a Spring book to create a little web store application.
The example uses the hsqldb embedded Database, but I don't want to use it.
I want to connect to a MySQL database and, later, use the Hibernate sessionFractory.
I edited the example code this way:
#Configuration
#ComponentScan("com.packagename.webstore")
public class RootApplicationContextConfig {
#Bean
public DataSource dataSource() {
// this is the original code of the example
/*EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
EmbeddedDatabase db = builder
.setType(EmbeddedDatabaseType.HSQL)
.addScript("db/sql/create-table.sql")
.addScript("db/sql/insert-data.sql")
.build();
return db; */
//this is my code
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/dbName");
dataSource.setUsername( "user" );
dataSource.setPassword( "pass" );
return dataSource;
}
}
Then, in my classes I access the datasource this way:
#Autowired
private DataSource datasource;
...
Connection connection = datasource.getConnection();
...
Is it correct what I did?
If later I want to use the Hibernate sessionFactory, how should I edit my code?
Thank you guys
If you want configure SessionFactory with spring then to create required beans like below
#Configuration
#EnableTransactionManagement
#PropertySource({ "classpath:persistence-mysql.properties" })
#ComponentScan({ "org.baeldung.spring.persistence" })
public class PersistenceConfig {
#Autowired
private Environment env;
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(restDataSource());
sessionFactory.setPackagesToScan(
new String[] { "entity class package name so it can scan them" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public DataSource restDataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.user"));
dataSource.setPassword(env.getProperty("jdbc.pass"));
return dataSource;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(
SessionFactory sessionFactory) {
HibernateTransactionManager txManager
= new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory);
return txManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
Properties hibernateProperties() {
return new Properties() {
{
setProperty("hibernate.hbm2ddl.auto",
env.getProperty("hibernate.hbm2ddl.auto"));
setProperty("hibernate.dialect",
env.getProperty("hibernate.dialect"));
setProperty("hibernate.globally_quoted_identifiers",
"true");
}
};
}
}
property file
# jdbc confi
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_hibernate_dev?createDatabaseIfNotExist=true
jdbc.user=tutorialuser
jdbc.pass=tutorialmy5ql
# hibernate config
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
hibernate.show_sql=false
hibernate.hbm2ddl.auto=create-drop
then you can you and Datasource or SessionFactory in your required class
public class HibernateDAO{
#Autowired
SessionFactory sessionFactory;
#Autowired
DataSource datasource;
}
Here is example link

Spring 4 + Spring repositories + hibernate 5: Error create java config

I have spring 4 app and I want use spring repositories. I tried include spring jpa_hibernate
compile 'org.springframework.data:spring-data-jpa:1.11.4.RELEASE'
compile group: 'org.hibernate', name: 'hibernate-core', version: '5.0.5.Final'
and create config like oficial spring doc:
#Configuration
#ComponentScan("my.domain")
#EnableJpaRepositories("my.domain")
#EnableTransactionManagement
public class ApplicationConfiguration {
#Bean
public Config getConfig() {
return ConfigLoader.load();
}
#Bean
#Autowired
public DataSource getDatasource(Config config) throws Exception {
Properties props = new Properties();
Config dbConfig = config.getConfig("db.config");
dbConfig.entrySet().forEach(entry -> props.put(entry.getKey(), entry.getValue().unwrapped()));
return new DataSourceFactory().createDataSource(props);
}
#Bean
#Autowired
public NamedParameterJdbcTemplate getJdbcTemplate(DataSource datasource) {
return new NamedParameterJdbcTemplate(datasource);
}
#Bean
#Autowired
public PlatformTransactionManager getTransactionManager(DataSource datasource) {
return new DataSourceTransactionManager(datasource);
}
#Bean
#Autowired
public EntityManagerFactory entityManagerFactory(DataSource datasource) {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setDataSource(datasource);
factory.afterPropertiesSet();
return factory.getObject();
}
#Bean
#Autowired
public PlatformTransactionManager transactionManager(DataSource datasource) {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory(datasource));
return txManager;
}
}
But I get error when tried run app:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in my.ApplicationConfiguration:
Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate
[javax.persistence.EntityManagerFactory]: Factory method 'entityManagerFactory' threw exception; nested exception is java.lang.IllegalStateException:
Failed to determine Hibernate PersistenceProvider
I used repositories in springboot and Configure in file, But I not found worck actual example for java config spring(not boot only simple core app)
As you are using latest Spring Data release, upgrade to the latest Hibernate release:
compile group: 'org.hibernate', name: 'hibernate-core', version: '5.2.10.Final'
Spring requires hibernate's EntityManagerFactory implementation which previosly was provisioned by separate jar which is now deprecated, so you need only single hibernate-core dependency.
Also consider using following configuration:
#Configuration
#ComponentScan("my.domain")
#EnableJpaRepositories("my.domain")
#EnableTransactionManagement
public class ApplicationConfiguration {
#Bean
public Config getConfig() {
return ConfigLoader.load();
}
#Bean
public DataSource getDatasource(Config config) throws Exception {
Properties props = new Properties();
Config dbConfig = config.getConfig("db.config");
dbConfig.entrySet().forEach(entry -> props.put(entry.getKey(), entry.getValue().unwrapped()));
return new DataSourceFactory().createDataSource(props);
}
#Bean
public NamedParameterJdbcTemplate getJdbcTemplate(DataSource datasource) {
return new NamedParameterJdbcTemplate(datasource);
}
#Bean
#Autowired
public PlatformTransactionManager getTransactionManager(DataSource datasource) {
return new DataSourceTransactionManager(datasource);
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setDataSource(dataSource());
factory.setPackagesToScan("my.domain");
return factory;
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory);
return txManager;
}
}
You were referencsing old spring data documentation, current version is available here.

Multiple DB configuration in java spring throws exception

I am using two different databases for my spring hibernate application.
I defined two persistence config file for creating two session factory.
When i start the servlet container it throws below exception
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'transactionManager' defined in class path resource
PersistenceConfig1
#Configuration
#EnableTransactionManagement
#PropertySource({ "classpath:persistence.properties" })
#ComponentScan({ "com.test.test2.*" })
public class PersistenceConfiguration1 {
#Autowired
private Environment env;
#Bean(name="fSessionFactory")
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(testDataSource());
sessionFactory.setPackagesToScan(new String[] {
" com.test.test2"});
sessionFactory.setHibernateProperties(hibernateProperties1());
return sessionFactory;
}
#Bean
public DataSource testDataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.user"));
dataSource.setPassword(env.getProperty("jdbc.pass"));
return dataSource;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(
SessionFactory sessionFactory) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory);
return txManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
Properties hibernateProperties1() {
return new Properties() {
{
setProperty("hibernate.hbm2ddl.auto",
env.getProperty("hibernate.hbm2ddl.auto"));
setProperty("hibernate.dialect",
env.getProperty("hibernate.dialect"));
setProperty("hibernate.globally_quoted_identifiers", "true");
}
};
}
}
Persistence Config 2
#Configuration
#EnableTransactionManagement
#PropertySource({ "classpath:persistence.properties" })
#ComponentScan({ "com.test.test3.*" })
public class PersistenceConfigurationDOTC {
#Autowired
private Environment env;
#Bean(name="dSessionFactory")
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(test1DataSource());
sessionFactory.setPackagesToScan(new String[] {
"com.test.test3.entity"});
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public DataSource test1DataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc1.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc1.url"));
dataSource.setUsername(env.getProperty("jdbc1.user"));
dataSource.setPassword(env.getProperty("jdbc1.pass"));
return dataSource;
}
Properties hibernateProperties() {
return new Properties() {
{
setProperty("hibernate.hbm2ddl.auto",
env.getProperty("hibernate.hbm2ddl.auto"));
setProperty("hibernate.dialect",
env.getProperty("hibernate.dialect"));
setProperty("hibernate.globally_quoted_identifiers", "true");
}
};
}
}
If I defined two transaction manager also im getting exception.
Help me on how to configure two transaction managers in one spring hibernate application.
Do you want a single transaction manager for both the configs? Or would you prefer a multiple config? Try defining transaction manager in your Persistence Config 2 too.

DataSourceInitializer does not get called

I am setting up java config for database in my spring mvc app, and what I cannot figure out is why DataSourceInitializer bean does not get created, i.e. dataSourceInitializer method is never called.
#Configuration
#EnableJpaRepositories(basePackageClasses = {CustomerRepository.class})
#EnableTransactionManagement
public class DatabaseConfig {
#Resource
Environment environment;
#Bean
public NamedParameterJdbcTemplate jdbcTemplate(DataSource dataSource) {
return new NamedParameterJdbcTemplate(dataSource);
}
#Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
dataSource.setUsername(environment.getRequiredProperty("jdbc.user"));
dataSource.setPassword(environment.getRequiredProperty("jdbc.pwd"));
return dataSource;
}
#Bean
public DataSourceInitializer dataSourceInitializer(DataSource dataSource) {
final DataSourceInitializer initializer = new DataSourceInitializer();
initializer.setDataSource(dataSource);
initializer.setDatabasePopulator(databasePopulator());
return initializer;
}
#Bean
public DatabasePopulator databasePopulator() {
ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
databasePopulator.addScript(new ClassPathResource("classpath:/db/sql/create-db.sql", DatabaseConfig.class));
databasePopulator.addScript(new ClassPathResource("classpath:/db/sql/insert-data.sql", DatabaseConfig.class));
return databasePopulator;
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) throws Exception {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setPersistenceUnitName("CustomersPU");
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("com.myapp.domain");
factory.setDataSource(dataSource);
factory.setJpaProperties(jpaProperties());
return factory;
}
Properties jpaProperties() {
Properties props = new Properties();
props.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
props.put("hibernate.hbm2ddl.auto", "validate");
...
return props;
}
}
UPDATE: Exception that I get is
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [com/myapp/conf/DatabaseConfig.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: CustomersPU] Unable to build Hibernate SessionFactory
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1578)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at ....
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: CustomersPU] Unable to build Hibernate SessionFactory
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:877)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:805)
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60)
at ...
Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: missing table [CUSTOMERS]
at org.hibernate.tool.schema.internal.SchemaValidatorImpl.validateTable(SchemaValidatorImpl.java:67)
at org.hibernate.tool.schema.internal.SchemaValidatorImpl.doValidation(SchemaValidatorImpl.java:50)
at org.hibernate.tool.hbm2ddl.SchemaValidator.validate(SchemaValidator.java:91)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:484)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:802)
... 62 more
What I am looking for is to have it configured similar to this configuration: embedded database + special username and password + paths to schema and insertion sql files. Like described here https://github.com/JohnathanMarkSmith/HelloSpringJavaBasedJavaConfig
UPDATE
If I just use EmbeddableDatabase, then it does not allow me to define username, password and DB connection URL, which is necessary to me. The following example works, but it does not allow me to define username, password and DB connection URL.
#Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("classpath:/db/sql/create-db.sql")
.addScript("classpath:/db/sql/insert-data.sql")
.build();
}

Categories