I am trying to configure two EntityManagerFactory for one spring boot application. Each of those EntityManagerFactorys should work with different databases. Also would be great if one of them would be used as a default (e.g. when not explicit information was provided during on which one should be used).
Here is my code:
pkg/Application.java
package pkg;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).run(args);
}
}
pkg/PrimaryDbConfig.java
package pkg;
import org.h2.jdbcx.JdbcDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
#Configuration
public class PrimaryDbConfig {
public static final String DB = "primary";
#Bean
#Primary
public DataSource primaryDataSource() {
JdbcDataSource ds = new JdbcDataSource();
ds.setURL("jdbc:h2:file:~\\db\\test;AUTO_SERVER=TRUE");
ds.setUser("sa");
ds.setPassword("sa");
return ds;
}
#Bean
#Primary
public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactoryBean() {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setPersistenceUnitName(DB);
factoryBean.setDataSource(primaryDataSource());
factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
factoryBean.setPackagesToScan("pkg.entities");
return factoryBean;
}
#Bean
#Primary
public PlatformTransactionManager primaryTransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(primaryEntityManagerFactoryBean().getObject());
return transactionManager;
}
}
pkg/SecondaryDbConfig.java
package pkg;
import org.h2.jdbcx.JdbcDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
#Configuration
public class SecondaryDbConfig {
public static final String DB = "secondary";
#Bean
public DataSource secondaryDataSource() {
JdbcDataSource ds = new JdbcDataSource();
ds.setURL("jdbc:h2:file:~\\db\\test2;AUTO_SERVER=TRUE");
ds.setUser("sa");
ds.setPassword("sa");
return ds;
}
#Bean
public LocalContainerEntityManagerFactoryBean secondaryEntityManagerFactoryBean() {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setPersistenceUnitName(DB);
factoryBean.setDataSource(secondaryDataSource());
factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
factoryBean.setPackagesToScan("pkg.entities");
return factoryBean;
}
#Bean
public PlatformTransactionManager secondaryTransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(secondaryEntityManagerFactoryBean().getObject());
return transactionManager;
}
}
pkg/repositories/PrimaryRepository.java
package pkg.repositories;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import pkg.entities.SomeEntity;
import javax.persistence.EntityManager;
#Repository
#Transactional
public class PrimaryRepository {
private final EntityManager entityManager;
public PrimaryRepository(EntityManager entityManager) {
this.entityManager = entityManager;
}
public SomeEntity find(Integer id) {
return entityManager.find(SomeEntity.class, id);
}
}
pkg/repositories/SecondaryRepository.java
package pkg.repositories;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import pkg.entities.SomeEntity;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
#Repository
#Transactional("secondaryTransactionManager")
public class SecondaryRepository {
#PersistenceContext(unitName = "secondary")
private final EntityManager entityManager;
public SecondaryRepository(EntityManager entityManager) {
this.entityManager = entityManager;
}
public SomeEntity find(Integer id) {
return entityManager.find(SomeEntity.class, id);
}
}
build.gradle
plugins {
id 'org.springframework.boot' version '1.5.7.RELEASE'
}
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile "com.h2database:h2:1.4.193"
compile "org.hibernate:hibernate-core:5.2.10.Final"
compile ("org.springframework.boot:spring-boot-starter-data-jpa:1.5.2.RELEASE") {
exclude module: 'tomcat-jdbc'
}
}
Running this app I am getting next error:
Description:
Parameter 0 of constructor in pkg.repositories.PrimaryRepository required a single bean, but 2 were found:
- org.springframework.orm.jpa.SharedEntityManagerCreator#0: defined by method 'createSharedEntityManager' in null
- org.springframework.orm.jpa.SharedEntityManagerCreator#1: defined by method 'createSharedEntityManager' in null
Related
I am implementing a read-only db source but although there is no conflicting bean, it got bean error.
How can I fix the below issue ?
The bean 'routingDataSource', defined in class path resource [io/api/masterSlave/datasources/DataSourcesConfiguration.class], could not be registered. A bean with that name has already been defined in file [/Users/neslihan.bozer/Codes/api-backend/target/classes/io/api/masterSlave/routing/RoutingDataSource.class] and overriding is disabled.
package io.api.masterSlave.datasources;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import io.api.masterSlave.properties.Properties;
import io.api.masterSlave.routing.RoutingDataSource;
#Configuration
#ComponentScan
#EnableJpaRepositories("io.api.persistence.repository")
public class DataSourcesConfiguration {
#Autowired
private Properties props;
#Bean(name = "masterDataSource1")
#Primary
public DataSource masterDataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(props.getProperty("spring.datasource.master.driver-class-name"));
dataSource.setDefaultAutoCommit(false);
dataSource.setUsername(props.getProperty("spring.datasource.master.username"));
dataSource.setPassword(props.getProperty("spring.datasource.master.password"));
dataSource.setUrl(props.getProperty("spring.datasource.master.url"));
return dataSource;
}
#Bean
public RoutingDataSource routingDataSource() {
RoutingDataSource dataSource = new RoutingDataSource();
dataSource.setDefaultTargetDataSource(masterDataSource());
Map<Object, Object> targets = new HashMap<>();
targets.put(DataSourceType.MASTER, masterDataSource());
targets.put(DataSourceType.SLAVE, slaveDataSource());
dataSource.setTargetDataSources(targets);
dataSource.afterPropertiesSet();
return dataSource;
}
#Bean(name = "slaveDataSource2")
public DataSource slaveDataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(props.getProperty("spring.datasource.slave.driver-class-name"));
dataSource.setDefaultAutoCommit(false);
dataSource.setUsername(props.getProperty("spring.datasource.slave.username"));
dataSource.setPassword(props.getProperty("spring.datasource.slave.password"));
dataSource.setUrl(props.getProperty("spring.datasource.slave.url"));
return dataSource;
}
#Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(masterDataSource());
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder) {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(Boolean.parseBoolean(props.getProperty("spring.jpa.generate-ddl")));
Map<String, String> additionalProperties = new HashMap<>();
additionalProperties.put("hibernate.dialect", props.getProperty("spring.jpa.dialect"));
LocalContainerEntityManagerFactoryBean factory = builder.dataSource(routingDataSource())
.packages("io.api.persistence.entity").persistenceUnit("routingEntityMF").properties(additionalProperties)
.build();
factory.setJpaVendorAdapter(vendorAdapter);
factory.afterPropertiesSet();
return factory;
}
}
RoutingDataSource.java
package io.api.masterSlave.routing;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.stereotype.Service;
#Service
public class RoutingDataSource extends AbstractRoutingDataSource {
#Autowired
private DbHolder dbHolder;
#Override
protected Object determineCurrentLookupKey() {
return dbHolder.getDbType();
}
}
I'm trying to implement multi-tenancy architecture in my project. I am referring "http://anakiou.blogspot.com/2015/08/multi-tenant-application-with-spring.html" example. Everything is working fine in this example. But problem in this example is whenever new datasource to be add then we should add it manually. But i want something like adding datasource dynamically without application restart.
This is my application.properties
spring.jpa.hibernate.ddl-auto=none
spring.thymeleaf.cache=false
spring.datasource.datasource1.url=jdbc:mysql://localhost:3306/tenant_1
spring.datasource.datasource1.username=root
spring.datasource.datasource1.password=root
spring.datasource.datasource1.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.datasource2.url=jdbc:mysql://localhost:3306/tenant_2
spring.datasource.datasource2.username=root
spring.datasource.datasource2.password=root
spring.datasource.datasource2.driver-class-name=com.mysql.jdbc.Driver
This is DataSourceConfig.java
package com.anakiou.mt.config;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
#Configuration
public class DataSourceConfig {
#Autowired
private MultitenancyProperties multitenancyProperties;
#Bean(name = { "dataSource", "dataSource1" })
#ConfigurationProperties(prefix = "spring.datasource.datasource1")
public DataSource dataSource1() {
DataSourceBuilder factory = DataSourceBuilder
.create(this.multitenancyProperties.getDatasource1().getClassLoader())
.driverClassName(this.multitenancyProperties.getDatasource1().getDriverClassName())
.username(this.multitenancyProperties.getDatasource1().getUsername())
.password(this.multitenancyProperties.getDatasource1().getPassword())
.url(this.multitenancyProperties.getDatasource1().getUrl());
return factory.build();
}
#Primary
#Bean(name = "dataSource2")
#ConfigurationProperties(prefix = "spring.datasource.datasource2")
public DataSource dataSource2() {
DataSourceBuilder factory = DataSourceBuilder
.create(this.multitenancyProperties.getDatasource2().getClassLoader())
.driverClassName(this.multitenancyProperties.getDatasource2().getDriverClassName())
.username(this.multitenancyProperties.getDatasource2().getUsername())
.password(this.multitenancyProperties.getDatasource2().getPassword())
.url(this.multitenancyProperties.getDatasource2().getUrl());
return factory.build();
}
}
MultitenancyProperties.java
package com.anakiou.mt.config;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
#ConfigurationProperties("spring.datasource")
public class MultitenancyProperties {
#NestedConfigurationProperty
private DataSourceProperties datasource1;
#NestedConfigurationProperty
private DataSourceProperties datasource2;
public DataSourceProperties getDatasource1() {
return datasource1;
}
public void setDatasource1(DataSourceProperties datasource1) {
this.datasource1 = datasource1;
}
public DataSourceProperties getDatasource2() {
return datasource2;
}
public void setDatasource2(DataSourceProperties datasource2) {
this.datasource2 = datasource2;
}
}
DataSourceBasedMultiTenantConnectionProviderImpl.java
package com.anakiou.mt.util;
import org.hibernate.engine.jdbc.connections.spi.AbstractDataSourceBasedMultiTenantConnectionProviderImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
#Component
public class DataSourceBasedMultiTenantConnectionProviderImpl extends
AbstractDataSourceBasedMultiTenantConnectionProviderImpl {
private static final long serialVersionUID = 8168907057647334460L;
private static final String DEFAULT_TENANT_ID = "tenant_1";
#Autowired
private DataSource dataSource1;
#Autowired
private DataSource dataSource2;
private Map<String, DataSource> map;
#PostConstruct
public void load() {
map = new HashMap<>();
map.put("tenant_1", dataSource1);
map.put("tenant_2", dataSource2);
}
#Override
protected DataSource selectAnyDataSource() {
return map.get(DEFAULT_TENANT_ID);
}
#Override
protected DataSource selectDataSource(String tenantIdentifier) {
return map.get(tenantIdentifier);
}
}
The two database have some same name tables, for example the table with name summary, when I create repository, an error occurred! what should i do? the error is:
#Autowired
SummaryDao summaryDao;
RROR o.s.b.d.LoggingFailureAnalysisReporter -
*************************** APPLICATION FAILED TO START
Description:
Field summaryDao in
com.tc.spider.schedule.logic.combination.CombinationDailyNetLogic
required a bean of type 'com.tc.spider.dao.user.SummaryDao' that could
not be found.
Action:
Consider defining a bean of type 'com.tc.spider.dao.user.SummaryDao'
in your configuration.
the datasource config file is below:
`
package com.tc.spider.config.db;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
#Configuration
public class DataSourceConfig {
#Bean(name = "primaryDataSource")
#Qualifier("primaryDataSource")
#Primary // 该数据源为主数据源
#ConfigurationProperties(prefix = "spring.datasource.tct")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
#Bean(name = "secondaryDataSource")
#Qualifier("secondaryDataSource")
#ConfigurationProperties(prefix = "spring.datasource.market")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
#Bean
#Primary // jdbc默认的主数据源
public JdbcTemplate primaryJdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
#Bean(name = "marketJdbcTemplate")
public JdbcTemplate marketJdbcTemplate(#Qualifier("secondaryDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}
`
primary datasource
`
package com.tc.spider.config.db;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManager;
import javax.sql.DataSource;
import java.util.Map;
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(
entityManagerFactoryRef = "entityManagerFactoryPrimary", // 配置连接工厂 entityManagerFactory
transactionManagerRef = "transactionManagerPrimary", // 配置 事物管理器 transactionManager
basePackages = {"com.tc.spider.dao.user"}) // 设置Repository所在位置
public class PrimaryConfig {
#Autowired
#Qualifier("primaryDataSource")
private DataSource primaryDataSource;
#Bean(name = "entityManagerPrimary")
#Primary
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
}
#Bean(name = "entityManagerFactoryPrimary")
#Primary
public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary(EntityManagerFactoryBuilder builder) {
return builder
// 设置数据源
.dataSource(primaryDataSource)
// 设置数据源属性
.properties(getVendorProperties(primaryDataSource))
// 设置实体类所在位置.扫描所有带有 #Entity 注解的类
.packages("com.tc.spider.model.user")
// Spring会将EntityManagerFactory注入到Repository之中.有了 EntityManagerFactory之后,
// Repository就能用它来创建 EntityManager 了,然后 EntityManager 就可以针对数据库执行操作
.persistenceUnit("primaryPersistenceUnit")
.build();
}
#Autowired
private JpaProperties jpaProperties;
private Map getVendorProperties(DataSource dataSource) {
return jpaProperties.getHibernateProperties(dataSource);
}
/**
* 配置事物管理器
*
* #param builder
* #return
*/
#Bean(name = "transactionManagerPrimary")
#Primary
public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
}
}
`
SecondaryConfig.java this is the second datasource config
`
package com.tc.spider.config.db;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManager;
import javax.sql.DataSource;
import java.util.Map;
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(
entityManagerFactoryRef = "entityManagerFactorySecondary", // 配置连接工厂 entityManagerFactory
transactionManagerRef = "transactionManagerSecondary", // 配置 事物管理器 transactionManager
basePackages = {"com.tc.spider.dao.market"}) // 设置Repository所在位置
public class SecondaryConfig {
#Autowired
#Qualifier("secondaryDataSource")
private DataSource secondaryDataSource;
#Bean(name = "entityManagerSecondary")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactorySecondary(builder).getObject().createEntityManager();
}
#Bean(name = "entityManagerFactorySecondary")
public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary(EntityManagerFactoryBuilder builder) {
return builder
// 设置数据源
.dataSource(secondaryDataSource)
// 设置数据源属性
.properties(getVendorProperties(secondaryDataSource))
// 设置实体类所在位置.扫描所有带有 #Entity 注解的类
.packages("com.tc.spider.model.market") //设置实体类所在位置
// Spring会将EntityManagerFactory注入到Repository之中.有了 EntityManagerFactory之后,
// Repository就能用它来创建 EntityManager 了,然后 EntityManager 就可以针对数据库执行操作
.persistenceUnit("secondaryPersistenceUnit")
.build();
}
#Autowired
private JpaProperties jpaProperties;
private Map getVendorProperties(DataSource dataSource) {
return jpaProperties.getHibernateProperties(dataSource);
}
/**
* 配置事物管理器
*
* #param builder
* #return
*/
#Bean(name = "transactionManagerSecondary")
public PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());
}
}
`
I am working with Spring 4.3.x and Hibernate 5.2.x. Since hibernate 5 JPA is standard way to user ORM with spring, I created a config to use Hibernate with JPA.
My spring configuration is,
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.orm.hibernate5.HibernateExceptionTranslator;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.zaxxer.hikari.HikariDataSource;
#Configuration
#ComponentScan(basePackages = { "com.example.reports" })
#EnableTransactionManagement
#PropertySource(value = { "classpath:application.properties" })
public class SuperUserReportSpringConfiguration {
#Autowired
Environment environment;
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, JpaVendorAdapter jpaVendeorAdapter) {
LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
entityManagerFactory.setDataSource(dataSource);
entityManagerFactory.setJpaVendorAdapter(jpaVendeorAdapter);
entityManagerFactory.setPackagesToScan("com.example.reports.domain");
entityManagerFactory.setPersistenceUnitName("onlineDB");
return entityManagerFactory;
}
#Bean
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setShowSql(false);
adapter.setDatabasePlatform("org.hibernate.dialect.DB2400Dialect");
return adapter;
}
#Bean
DataSource dataSource() {
HikariDataSource ds = new HikariDataSource();
ds.setPoolName("hikariCP");
ds.setDriverClassName(this.environment.getProperty("jdbc.as400.db2.db.driver.classname"));
ds.setJdbcUrl(this.environment.getProperty("jdbc.as400.db2.db.url"));
ds.setUsername(this.environment.getProperty("jdbc.as400.db2.db.username"));
ds.setPassword(this.environment.getProperty("jdbc.as400.db2.db.password"));
ds.setMaximumPoolSize(10);
return ds;
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new JpaTransactionManager(emf);
return transactionManager;
}
#Bean
public HibernateExceptionTranslator hibernateExceptionTranslator() {
return new HibernateExceptionTranslator();
}
}
And I try to use #Transactional from javax.transaction.Transactional and org.springframework.transaction.annotation.Transactional
In both the case, transaction manager is not working and I am getting error when trying to get child element from User entity,
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.reports.domain.User.userInetAddrs, could not initialize proxy - no Session
I am not sure if I am missing any configuration.
Hibernate entity,
#OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
private Set<UserInetAddr> userInetAddrs = new HashSet<UserInetAddr>(0);
Service class with #Transactional
User user = superUserReportDao.getUserSecurityRoles(id);
user.getUserInetAddrs().forEach(inetAddress -> {
});
And DAO Method with #Transactional
public User getUser(int userSeqId) {
return entityManager.find(User.class, userSeqId);
}
DAO Class transaction,
#Repository("superUserReportDao")
#Slf4j
#Transactional
public class SuperUserReportDaoImpl implements SuperUserReportDao {
#PersistenceContext(unitName="onlineDB")
private EntityManager onlineEntityManager;
And Service Class,
#Service("superUserReportService")
#Slf4j
public class SuperUserReportServiceImpl implements SuperUserReportService {
#Resource(name = "superUserReportDao")
private SuperUserReportDao superUserReportDao;
public void generateSuperUserReport() throws SQLException {
// -- generate Customer Super user report
generateSuperUserEmail(UserType.CUSTOMER);
}
#Transactional
private void generateSuperUserEmail(UserType userType) throws SQLException {
...
And my main class,
#Slf4j
#Component
public class SuperUserReportMain {
#Resource(name = "superUserReportService")
SuperUserReportService superUserReportService;
/**
* #param args
* #throws SQLException
*/
public static void main(String[] args) throws SQLException {
ApplicationContext context = new AnnotationConfigApplicationContext(SuperUserReportSpringConfiguration.class);
SuperUserReportMain reportMain = context.getBean(SuperUserReportMain.class);
reportMain.generateSuperUserReport();
((AnnotationConfigApplicationContext)context).close();
}
public void generateSuperUserReport() throws SQLException {
superUserReportService.generateSuperUserReport();
}
}
i am beginner in java,spring&hibernate. when i using sessionFactory.getCurrentSession().saveOrUpdate(employee); igot error. but when i use sessionFactory.openSession().saveOrUpdate(employee); database insertion is possible. i want to use getCurrentSession() instead of open session .
mycode
myservice is
package com.simplecrud.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.simplecrud.dao.EmployeeDao;
import com.simplecrud.model.Employee;
#Service("employeeService")
#Transactional
public class EmployeeService {
#Autowired
EmployeeDao dao;
#Transactional
public String create(Employee employee)
{
System.out.println("service"+employee);
dao.create(employee);
return null;
}
}
my dao is
package com.simplecrud.dao;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import com.simplecrud.model.Employee;
#Component
#Repository
public class EmployeeDao {
#Autowired
SessionFactory sessionFactory;
public void create(Employee employee){
sessionFactory.openSession().saveOrUpdate(employee);
/*sessionFactory.getCurrentSession().saveOrUpdate(employee);*/
/* protected Session getSession(){
return sessionFactory.getCurrentSession();
}*/
}
}
config file
package com.simplecrud.configuration;
import java.util.Properties;
import javax.sql.DataSource;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.orm.hibernate4.LocalSessionFactoryBuilder;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.JstlView;
import org.springframework.web.servlet.view.UrlBasedViewResolver;
#Configuration //Marks this class as configuration
//Specifies which package to scan
#ComponentScan("com.simplecrud")
//Enables Spring's annotations
#EnableWebMvc
public class Config {
#Bean
public UrlBasedViewResolver setupViewResolver() {
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
}
#Bean(name = "dataSource")
public DriverManagerDataSource dataSource() {
DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
driverManagerDataSource.setDriverClassName("com.mysql.jdbc.Driver");
driverManagerDataSource.setUrl("jdbc:mysql://localhost:3306/employee_db");
driverManagerDataSource.setUsername("root");
driverManagerDataSource.setPassword("mysql");
return driverManagerDataSource;
}
private Properties getHibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.show_sql", "true");
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
// properties.put("hibernate.hbm2ddl.auto", "update");
properties.put("hibernate.c3p0.minPoolSize", "5");
properties.put("hibernate.c3p0.maxPoolSize", "10");
properties.put("hibernate.c3p0.idleTestPeriod", "300");
properties.put("hibernate.c3p0.timeout", "600");
properties.put("hibernate.c3p0.max_statement", "50");
properties.put("hibernate.c3p0.testConnectionOnCheckout", "false");
properties.setProperty("timeZone", "serverTimezone");
properties.put("hibernate.c3p0.preferredTestQuery", "select 1");
return properties;
}
#Autowired
#Bean(name = "sessionFactory")
public SessionFactory getSessionFactory(DataSource dataSource) {
LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(dataSource);
sessionBuilder.addProperties(getHibernateProperties());
sessionBuilder.scanPackages("com.simplecrud.model");
//sessionBuilder.setInterceptor(new MySQLCalcFoundRowsInterceptor());
return sessionBuilder.buildSessionFactory();
}
#Autowired
#Bean(name = "transactionManager")
public HibernateTransactionManager getTransactionManager(SessionFactory sessionFactory) {
HibernateTransactionManager transactionManager = new HibernateTransactionManager(sessionFactory);
return transactionManager;
}
}
help me anyone..