Configure Hibernate models discovery in Spring - java

I want to configure Spring with Hibernate 5 and JNDI using this code:
#Configuration
#EnableTransactionManagement
public class ContextDatasource {
#Bean
public LocalSessionFactoryBean sessionFactory() throws NamingException {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan("org.database.models");
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public PlatformTransactionManager hibernateTransactionManager() throws NamingException {
HibernateTransactionManager transactionManager
= new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
private final Properties hibernateProperties() {
Properties hibernateProperties = new Properties();
hibernateProperties.setProperty(
"hibernate.show_sql", "true");
hibernateProperties.setProperty(
"hibernate.format_sql", "true");
hibernateProperties.setProperty(
"hibernate.hbm2ddl.auto", "create-drop");
hibernateProperties.setProperty(
"hibernate.dialect", "org.hibernate.dialect.MariaDBDialect");
return hibernateProperties;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory()
throws NamingException {
LocalContainerEntityManagerFactoryBean em
= new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
return em;
}
#Bean
public DataSource dataSource() throws NamingException {
return (DataSource) new JndiTemplate().lookup("java:/global/production_gateway");
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
}
But when I deploy the code I get error. Looks like I have to add another XML configuration file:
Caused by: java.lang.IllegalStateException: No persistence units parsed from {classpath*:META-INF/persistence.xml}
Hibernate models are located in a remote jar under Java package org.database.models How I can map them using Java code?

May you need to add dependencies to your pom file, if you use maven
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.1.0.Final</version>
</dependency>

To prevent hibernate persistence.xml usage, you must define on LocalContainerEntityManagerFactoryBean the packages to scan entity from.
emf.setPackagesToScan(myPackagesToScan);

Related

Multiple database connection reusing entity mapping

We have a case where we connect to different databases environments, but the tables in each of the environment are the same.
Is there any way I can reuse the entity class for each of the environment?
I am using separate config class for each of the environment. Below is the config for one of the environment, similarly I have 4 others. The "packages" deduce which environment to connect to.
codejava
#Configuration
#EnableJpaRepositories(basePackages = {"packages"},
entityManagerFactoryRef = "OneEntityManager",
transactionManagerRef = "OneTransactionManager")
public class DevDataSourceConfig {
#Bean
#Primary
public LocalContainerEntityManagerFactoryBean OneEntityManager() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(OneDataSource());
em.setPackagesToScan(String[]{"packages"});
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
properties.put("hibernate.dialect", env.getProperty("hibernate.dialect"));
em.setJpaPropertyMap(properties);
return em;
}
#Primary
#Bean
public DataSource OneDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(driverclass);
dataSource.setUrl(url);
dataSource.setUsername(uName);
dataSource.setPassword(dbPass);
return dataSource;
}
#Primary
#Bean
public PlatformTransactionManager OneTransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(OneEntityManager().getObject());
return transactionManager;
}
}

org.hibernate.service.UnknownUnwrapTypeException: Cannot unwrap to requested type [javax.sql.DataSource]

I am getting this error while running my application : org.hibernate.service.UnknownUnwrapTypeException: Cannot unwrap to requested type [javax.sql.DataSource]
My configuration class :
#Configuration
#PropertySource("classpath:META-INF/spring/jdbc.properties")
public class HibernateConfig {
#Autowired
private Environment env;
#Bean(name="dataSource")
public DataSource getDataSource() throws PropertyVetoException{
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass(env.getProperty("db.driverClass"));
dataSource.setJdbcUrl(env.getProperty("db.jdbcUrl"));
dataSource.setUser(env.getProperty("db.user"));
dataSource.setPassword(env.getProperty("db.password"));
dataSource.setMaxPoolSize(50);
dataSource.setMinPoolSize(5);
dataSource.setMaxConnectionAge(1800);
dataSource.setMaxIdleTime(1800);
dataSource.setAutoCommitOnClose(false);
dataSource.setInitialPoolSize(5);
return dataSource;
}
#Bean(name="sessionFactory")
#Scope("singleton")
public LocalSessionFactoryBean getSessionFactory(DataSource dataSource){
LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.dialect", env.getProperty("db.dialect"));
hibernateProperties.setProperty("hibernate.jdbc.batch_size", "0");
hibernateProperties.setProperty("c3p0.acquire_increment", "1");
localSessionFactoryBean.setHibernateProperties(hibernateProperties);
return localSessionFactoryBean;
}
#Bean(name="transactionManager")
public HibernateTransactionManager getTransactionManager(SessionFactory sessionFactory){
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory);
return transactionManager;
}
}
I ran actually into this thread which talks about the same issue. However I am wondering if it is a sort of bug in hibernate5 that has not been fixed yet or does it relate to something else. Thank you in advance.

Unable to lookup JDBC datasource by JNDI

I am using Spring Data, Hibernate and jBoss 6.x.x.
I would like to look up at the jBoss 6.x.x the already configured jdbc datasource by JNDI.
Looking at the file standalone.xml, I have found the following entries:
<profile>
...
<datasources>
...
<datasource enabled="true" jndi-name="name_of_the_ds" pool-name="name_of_the_pool" use-java-context="true">
<connection-url>connection_uri</connection-url>
<driver>driver_name</driver>
<security>
<user-name>fake_login</user-name>
<password>fake_password</password>
</security>
</datasource>
...
</datasources>
...
</profile>
Based on this, I have written the following Spring annotation configuration
class for the data base (I am using Spring Data and Hibernate as the JPA provider)
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(basePackages = "dao.repository")
#PropertySource("classpath:application.properties")
public class DataBaseContextConfiguration {
private static final Logger LOGGER = LoggerFactory.getLogger(DataBaseContextConfiguration.class);
private Database dataBase = Database.SOME_DATA_BASE;
#Value("${jpa.showSql}")
private Boolean showSql;
#Value("${name.data.source}")
private String dataSourceJndiName;
#Bean
public LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean() throws NamingException {
final LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
localContainerEntityManagerFactoryBean.setDataSource(dataSource());
localContainerEntityManagerFactoryBean.setPackagesToScan(PACKAGE_WITH_DB_ENTITIES);
JpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
localContainerEntityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter);
return localContainerEntityManagerFactoryBean;
}
#Bean
public PlatformTransactionManager platformTransactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
jpaTransactionManager.setEntityManagerFactory(entityManagerFactory);
return jpaTransactionManager;
}
public DataSource dataSource() throws NamingException {
DataSource dataSource = null;
JndiTemplate jndi = new JndiTemplate();
dataSource = (DataSource) jndi.lookup(dataSourceJndiName);
return dataSource;
}
}
The String dataSourceJndiName has the following value name_of_the_ds.
When I am trying to run simple integration test the following exception occurres:
Caused by: javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial

Atomikos + OpenJpa +DB2 XA standalone - setAutocommit(true) not allowed

I have a spring batch project and am using Atomikos for transaction management.
Here is my datasource configuration and atomikos configuration.
#Bean
public DataSource dataSource() {
Properties properties = new Properties();
properties.setProperty("serverName", "localhost");
properties.setProperty("databaseName", "somedb");
properties.setProperty("portNumber", "9999");
properties.setProperty("currentSchema", "sch");
properties.setProperty("user", "user");
properties.setProperty("password", "pwd");
properties.setProperty("driverType", "4");
properties.setProperty("resultSetHoldability","2");
AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
atomikosDataSourceBean.setXaDataSourceClassName("com.ibm.db2.jcc.DB2XADataSource");
atomikosDataSourceBean.setXaProperties(properties);
atomikosDataSourceBean.setPoolSize(5);
return atomikosDataSourceBean;
}
#Bean(initMethod = "init", destroyMethod = "close")
public UserTransactionManager atomikosTransactionManager(){
UserTransactionManager atomikosTransactionManager = new UserTransactionManager();
atomikosTransactionManager.setForceShutdown(false);
return atomikosTransactionManager;
}
#Bean
public UserTransactionImp atomikosUserTransaction() throws SystemException{
UserTransactionImp atomikosUserTransaction = new UserTransactionImp();
atomikosUserTransaction.setTransactionTimeout(300);
return atomikosUserTransaction;
}
#Bean
public JtaTransactionManager transactionManager(UserTransactionManager atomikosTransactionManager, UserTransactionImp atomikosUserTransaction) throws SystemException{
JtaTransactionManager jtaTransactionManager = new JtaTransactionManager();
jtaTransactionManager.setTransactionManager(atomikosTransactionManager);
jtaTransactionManager.setUserTransaction(atomikosUserTransaction);
jtaTransactionManager.setAllowCustomIsolationLevels(true);
return jtaTransactionManager;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setJtaDataSource(dataSource);
em.setPackagesToScan("org.company.entity");
em.setJpaVendorAdapter(new OpenJpaVendorAdapter());
em.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
em.setSharedCacheMode(SharedCacheMode.ALL);
em.setJpaProperties(additionalProperties());
return em;
}
final Properties additionalProperties() {
final Properties openJpaProperties = new Properties();
openJpaProperties.setProperty("javax.persistence.transactionType","jta");
openJpaProperties.setProperty("openjpa.TransactionMode", "local");
openJpaProperties.setProperty("openjpa.ConnectionFactoryMode", "local");
openJpaProperties.setProperty("openjpa.MetaDataRepository", "Preload=true");
openJpaProperties.setProperty("openjpa.Compatibility", "QuotedNumbersInQueries=true");
openJpaProperties .setProperty("openjpa.ConnectionFactoryProperties", "PrettyPrint=true, PrettyPrintLineLength=80, PrintParameters=true");
return openJpaProperties;
}
When i call spring repository to update the database it throws me an error saying Invalid operation: setAutoCommit(true) is not allowed during Global Transaction. See stacktrace below. Any thoughts on this will be very helpful.
com.ibm.db2.jcc.am.SqlException: [jcc][t4][10126][10304][3.62.56] Invalid operation: setAutoCommit(true) is not allowed during Global Transaction. ERRORCODE=-4201, SQLSTATE=2D521
at com.ibm.db2.jcc.am.fd.a(fd.java:679)
at com.ibm.db2.jcc.am.fd.a(fd.java:60)
at com.ibm.db2.jcc.am.fd.a(fd.java:120)
at com.ibm.db2.jcc.am.jb.setAutoCommit(jb.java:960)
at com.ibm.db2.jcc.am.df.setAutoCommit(df.java:158)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:611)
at com.atomikos.jdbc.AtomikosConnectionProxy.invoke(AtomikosConnectionProxy.java:161)
at $Proxy38.setAutoCommit(Unknown Source)
at org.apache.openjpa.lib.jdbc.DelegatingConnection.setAutoCommit(DelegatingConnection.java:167)
I was able to fix it. The issue here is we need to tell openJpa to participate in Atomikos transactions. Here is a updated version of the additionalProperties() method:
#Bean
#DependsOn("transactionManager")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, JpaVendorAdapter jpaVendorAdapter,
TransactionManager transactionManager) {
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setJtaDataSource(dataSource);
em.setPackagesToScan("org.company.entity");
em.setJpaVendorAdapter(jpaVendorAdapter);
em.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
em.setSharedCacheMode(SharedCacheMode.ALL);
em.setJpaProperties(additionalProperties(dataSource, transactionManager));
return em;
}
final Properties additionalProperties(DataSource dataSource, TransactionManager transactionManager) {
final Properties openJpaProperties = new Properties();
openJpaProperties.put("javax.persistence.transactionType", "JTA");
openJpaProperties.put("openjpa.TransactionMode", "managed");
openJpaProperties.put("openjpa.ConnectionFactoryMode", "managed");
openJpaProperties.put("openjpa.ConnectionFactory", dataSource);
openJpaProperties.put("openjpa.ManagedRuntime", "invocation(TransactionManagerMethod=com.atomikos.icatch.jta.TransactionManagerImp.getTransactionManager)");
openJpaProperties.put("openjpa.MetaDataRepository", "Preload=true");
openJpaProperties.put("openjpa.Compatibility", "QuotedNumbersInQueries=true");
openJpaProperties.put("openjpa.ConnectionFactoryProperties", "PrettyPrint=true, PrettyPrintLineLength=80, PrintParameters=true");
return openJpaProperties;
}

Play Framework evolutions not working with Spring/Hibernate

I am using java-play-spring template (obtainable here: https://github.com/jamesward/play-java-spring#master )and currently I am trying to write some evolutions for it.
I am putting my script:
# --- !Ups
CREATE TABLE accounts
(
accountid INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
clientid INT NOT NULL,
credit DECIMAL(13,2)
);
# --- !Downs
drop table accounts;
into conf/evolutions/default/1.sql. Unfortunatelly, after application starts, nothing happens. I suppose that it may be Spring/Hibernate fault, so i disabled Hibernate validation:
#Configuration
#EnableTransactionManagement
public class DataConfig {
#Bean
public EntityManagerFactory entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setShowSql(true);
vendorAdapter.setGenerateDdl(false);
LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
entityManagerFactory.setPackagesToScan("models");
entityManagerFactory.setJpaVendorAdapter(vendorAdapter);
entityManagerFactory.setDataSource(dataSource());
entityManagerFactory.setValidationMode(ValidationMode.NONE);
entityManagerFactory.afterPropertiesSet();
return entityManagerFactory.getObject();
}
#Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager(entityManagerFactory());
return transactionManager;
}
#Bean
public DataSource dataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(Play.application().configuration().getString("db.default.driver"));
dataSource.setUrl(Play.application().configuration().getString("db.default.url"));
dataSource.setUsername(Play.application().configuration().getString("db.default.user"));
dataSource.setPassword(Play.application().configuration().getString("db.default.password"));
return dataSource;
}
}
But this didn't help. I have also added
play.modules.evolutions.enabled=true
To my application.conf. This does not help too.
Does anyone has any ideas what may be wrong?

Categories

Resources