HibernateException: createQuery is not valid without active transaction - java

The programmatic configuration seems in place but for some reason the application throws exception:
org.springframework.orm.jpa.JpaSystemException: createQuery is not valid without active transaction; nested exception is org.hibernate.HibernateException: createQuery is not valid without active transaction
Code:
#Repository
public class FilmDAOImpl implements FilmDAO {
#Autowired
private HibernateUtil hibernateUtil;
#Autowired
private SessionFactory sessionFactory;
#Override
public List<Film> findFilms(int actorId, int categoryId, int languageId, int releaseYear) {
Query searchQuery = sessionFactory.getCurrentSession().createQuery("from Film " +
"join Actor " +
"join Category " +
"where Category.categoryId=:categoryId " +
"and Film.language.id=:languageId " +
"and Film.releaseYear=:releaseYear " +
"and Actor.actorId=:actorId");
searchQuery.setParameter("categoryId", categoryId);
searchQuery.setParameter("languageId", languageId);
searchQuery.setParameter("releaseYear", releaseYear);
searchQuery.setParameter("actorId", actorId);
return (List<Film>)searchQuery.list();
}
}
Configuration:
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories (basePackages = { "com.hibernate.query.performance.persistence" }, transactionManagerRef = "jpaTransactionManager")
#EnableJpaAuditing
#PropertySource({ "classpath:persistence-postgresql.properties" })
#ComponentScan(basePackages = { "com.hibernate.query.performance" })
public class ApplicationConfig {
#Autowired
private Environment env;
public ApplicationConfig() {
super();
}
#Bean
public LocalSessionFactoryBean sessionFactory() {
final LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(applicationDataSource());
sessionFactory.setPackagesToScan(new String[] { "com.hibernate.query.performance.persistence.model" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
final LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
emf.setDataSource(applicationDataSource());
emf.setPackagesToScan(new String[] { "com.hibernate.query.performance.persistence.model" });
final JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
emf.setJpaVendorAdapter(vendorAdapter);
emf.setJpaProperties(hibernateProperties());
return emf;
}
#Primary
#Bean
public DriverManagerDataSource applicationDataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName")));
dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url")));
dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user")));
dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass")));
return dataSource;
}
#Bean
#Primary
public PlatformTransactionManager hibernateTransactionManager() {
final HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
transactionManager.setDataSource(applicationDataSource());
return transactionManager;
}
#Bean
public PlatformTransactionManager jpaTransactionManager() {
final JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
private final Properties hibernateProperties() {
final Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
hibernateProperties.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
hibernateProperties.setProperty("hibernate.format_sql", env.getProperty("hibernate.format_sql"));
hibernateProperties.setProperty("hibernate.generate_statistics", env.getProperty("hibernate.generate_statistics"));
hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", env.getProperty("hibernate.cache.use_second_level_cache"));
hibernateProperties.setProperty("hibernate.cache.region.factory_class", env.getProperty("hibernate.cache.region.factory_class"));
hibernateProperties.setProperty("hibernate.cache.use_query_cache", env.getProperty("hibernate.cache.use_query_cache"));
hibernateProperties.setProperty("hibernate.current_session_context_class", "managed");
hibernateProperties.setProperty("hibernate.current_session_context_class", "org.hibernate.context.internal.ThreadLocalSessionContext");
return hibernateProperties;
}
}
UPDATE
#Service
#Transactional
public class FilmServiceImpl implements FilmService {
#Autowired
private FilmDAO filmDAO;
#Override
public int createFilm(Film film) {
return filmDAO.createFilm(film);
}
#Override
public Film updateFilm(Film film) {
return filmDAO.updateFilm(film);
}
#Override
public void deleteFilm(int id) {
filmDAO.deleteFilm(id);
}
#Override
public List<Film> getAllFilms() {
return filmDAO.getAllFilms();
}
#Override
public Film getFilm(int id) {
return filmDAO.getFilm(id);
}
#Override
public List<Film> findFilms(int actorId, int categoryId, int languageId, int releaseYear) {
return filmDAO.findFilms(actorId, categoryId, languageId, releaseYear);
}
}

Try using openSession() as below, Since getCurrentSession() just attaches to the current session:
Query searchQuery = sessionFactory.openSession().createQuery(...
Also, you need to surround code with proper try..catch..finally block and in finally close the session using session.close()

Related

Spring boot launch hibernate config not found

Hi there I am trying to create a student webapp with spring boot but i can't seem to get it to run as an error appears every time that hibernate sessionfactory can't be found and i should include a bean type of equal type in my configuration.
I thought I properly configured the webapp properly but i cant seem to get it to find my hibernate session factory which i configured in my DAO, any help on where i'm going wrong would be appreciated.
Here Spring boot launcher class
#SpringBootApplication(exclude = HibernateJpaAutoConfiguration.class)
#ComponentScan({"model", "controller", "dao", "service"})
public class StudentsApplication {
public static void main(String[] args) {
SpringApplication.run(StudentsApplication.class, args);
}
}
Here is my DAO class
#Repository
#Transactional
public class StudentDao {
#Autowired
SessionFactory sessionFactory;
public Student getStudent(final int id) {
#SuppressWarnings("unchecked")
TypedQuery<Student> q = sessionFactory.getCurrentSession().createQuery(
"from student where = id").setParameter("id", id);
return q.getSingleResult();
}
public List<Student> getAllStudents() {
#SuppressWarnings("unchecked")
TypedQuery<Student> q = sessionFactory.getCurrentSession().createQuery(
"from student");
return q.getResultList();
}
public void addStudent(final Student student) {
sessionFactory.getCurrentSession().save(student);
}
public void updateStudent(final Student student) {
sessionFactory.getCurrentSession().saveOrUpdate(student);
}
public void deleteStudent(final int id) {
sessionFactory.getCurrentSession().createQuery(
"delete from student where = id").setParameter("id", id)
.executeUpdate();
}
}
here is my configuration class
#Configuration
#PropertySource({"classpath:application.properties"})
public class DbConfig {
#Autowired
private Environment environment;
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(environment.getProperty("jdbc.driverClassName"));
dataSource.setUrl(environment.getProperty("jdbc.url"));
dataSource.setUsername(environment.getProperty("jdbc.username"));
dataSource.setPassword(environment.getProperty("jdbc.password"));
return dataSource;
}
#Bean
public LocalSessionFactoryBean getSessionFactory() {
LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
factoryBean.setDataSource(dataSource());
Properties props = new Properties();
props.put("format_sql", "true");
props.put("hibernate.show_sql", "true");
factoryBean.setHibernateProperties(props);
factoryBean.setPackagesToScan("com.alpheus.students.entity");
// factoryBean.setAnnotatedClasses(Student.class);
return factoryBean;
}
#Bean
public HibernateTransactionManager getTransactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(getSessionFactory().getObject());
return transactionManager;
}
}
here is my properties file
# Connection url for the database
spring.datasource.url=jdbc:mysql://localhost:3308/week04
spring.datasource.username=user
spring.datasource.password=pass
server.port=9999
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
#view resolver
spring.mvc.view.prefix=/views/
spring.mvc.view.suffix=.jsp
here is my controller class
#Controller
public class StudentController {
#Autowired
private StudentService studentService;
#GetMapping("/home")
public String getAllStudents(Model studentsModel) {
List<Student> listStudents = studentService.getAllStudents();
studentsModel.addAttribute("listStudents", listStudents);
return "student-list";
}
#GetMapping("/student/{id}")
public String editStudent(#PathVariable int id, Model studentModel) {
studentModel.addAttribute("student", studentService.getStudent(id));
return "student-form";
}
#PostMapping("/student/new")
public String saveStudent(#ModelAttribute("student")Student student) {
studentService.addStudent(student);
return "redirect:/";
}
#GetMapping("/student")
public String showNewForm() {
return "student-form";
}
#PostMapping("/student/update/{id}")
public String updateStudent(#ModelAttribute("student") Student student) {
studentService.updateStudent(student);
return "redirect:/";
}
#GetMapping(value = "/student/delete/{id}")
public String deleteStudent(#PathVariable int id) {
studentService.deleteStudent(id);
return "redirect:/";
}
}

Can't map class to Hibernate without xml with ".setAnnotatedClasses()" Getting "2QuerySyntaxException: FileEntity is not mapped" error

Hi everyone.
I am trying to map class (FileEntity) to Hibernate using .setAnnotatedClasses() or .setPackagesToScan() methods. But I get the same error over and over again.
org.hibernate.hql.internal.ast.QuerySyntaxException: FileEntity is not mapped
When I mapped the class with .xml all worked fine.
Please tell me, where is my mistake?
ApplicationContextConfig.java
#Configuration
#ComponentScan("com.group.appName")
#EnableTransactionManagement
#PropertySource("classpath:application.properties")
public class ApplicationContextConfig {
#Autowired
Environment environment;
#Bean(name = "viewResolver")
public InternalResourceViewResolver getViewResolver() {
return new InternalResourceViewResolver();
}
#Bean(name = "dataSource")
public DataSource getDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl(environment.getProperty("spring.datasource.url"));
dataSource.setUsername(environment.getProperty("spring.datasource.username"));
dataSource.setPassword(environment.getProperty("spring.datasource.password"));
return dataSource;
}
#Autowired
#Bean(name = "sessionFactory")
public SessionFactory getSessionFactory(#Qualifier("dataSource") DataSource dataSource) throws Exception {
Properties properties = new Properties();
properties.put("hibernate.dialect", environment.getProperty("spring.jpa.properties.hibernate.dialect"));
properties.put("hibernate.show_sql", environment.getProperty("spring.jpa.show-sql"));
properties.put("current_session_context_class", environment.getProperty("spring.jpa.properties.hibernate.current_session_context_class"));
LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setHibernateProperties(properties);
factoryBean.afterPropertiesSet();
factoryBean.setPackagesToScan("com.group.appName.model");
// or another method
factoryBean.setAnnotatedClasses(FileEntity.class);
return factoryBean.getObject();
}
#Autowired
#Bean(name = "transactionManager" )
public HibernateTransactionManager getTransactionManager(SessionFactory sessionFactory) {
HibernateTransactionManager transactionManager
= new HibernateTransactionManager(sessionFactory);
return transactionManager;
}
#Bean(name = "multipartResolver")
public CommonsMultipartResolver getCommonsMultipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(20971520); // 20MB
multipartResolver.setMaxInMemorySize(1048576); // 1MB
return multipartResolver;
}
}
FileEntity.java
#Entity
#Table(name ="files_upload")
public class FileEntity {
private String fileName;
private Byte[] fileData;
#Id
#Column(name = "file_name")
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
#Column(name = "file_data")
public Byte [] getFileData() {
return fileData;
}
public void setFileData(Byte [] fileData) {
this.fileData = fileData;
}
}
application.properties
server.port=9090
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/filedb?serverTimezone=Europe/Moscow
spring.datasource.username=root
spring.datasource.password=241299
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=none
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext
Ok. I fixed it.
The point is that in method getSessionFactory after creating an object of class LocalSessionFactoryBean the first line should be
factoryBean.setAnnotatedClasses(FileEntity.class);
So the correct creating an object of LocalSessionFactoryBean class is:
LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
factoryBean.setAnnotatedClasses(FileEntity.class); - first line.
factoryBean.setDataSource(dataSource);
factoryBean.setHibernateProperties(properties);
factoryBean.afterPropertiesSet();

Hibernate sessionFactory bean throwing java.lang.NullPointerException

I am migrating jdbc to hibernate and i have palced below hibernate configuration in my application.
public class HibernateConfiguration {
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "com.cm.models" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl(jdbcurl);
dataSource.setUsername(userName);
dataSource.setPassword(password);
return dataSource;
}
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
properties.put("hibernate.show_sql", true);
properties.put("hibernate.format_sql", true);
return properties;
}
#Bean
#Autowired
public HibernateTransactionManager transactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
}
my application interacting fine with database at application startup creating hibernate session successfully through session factory giving output also.
**#Autowired
private SessionFactory sessionFactory;**
protected Session getSession() {
return sessionFactory.getCurrentSession();
}
but after application startup when i hitting DAO by controller then session factory bean getting Null reference and throwing NullPointerException due to which unable to create or open hibernate session , i tried to find out solution but that's not working please let me know why above SessionFactory bean having nullPointer due to which issue created.
Just to test my DAO logic I am using this controller and This controller hitting to DAO where sessionFacory bean is null.
#RestController
#RequestMapping("/Emp")
public class myController {
#RequestMapping(value = "/findByChannelManager", method = RequestMethod.GET)
public void findemp() {
HotelDaoImpl hotelDaoImpl=new HotelDaoImpl();
List <HotelEntity> list = new ArrayList<>();
list = hotelDaoImpl.findByChannelManager (EnumCM.AR);
for (HotelEntity pro : list) {
System.out.println(pro);
}
}
}
#Repository
#Transactional
public class HotelDaoImpl extends AbstractDao implements IHotelDao {
#SuppressWarnings({ "unchecked", "unused" })
#Override
public List<HotelEntity> findByChannelManager(EnumCM cm) {
List<HotelEntity> list = null;
try {
Session s = getSession();
Criteria criteria=s.createCriteria(Hotel.class);
criteria.add(Restrictions.eq("channelManager", "cm.name()"));
list = criteria.list();
}catch(Exception e) {
LOGGER.debug("error " +e.getMessage());
e.printStackTrace();
}
return list;
}
public abstract class AbstractDao {
#Autowired
private SessionFactory sessionFactory;
protected Session getSession() {
return sessionFactory.getCurrentSession();
}
}
You cant access dao from your controller. You can access dao from service so add service class. Try this code
#RestController
#RequestMapping("/Emp")
public class myController {
#Autowired
HotelService service;
#RequestMapping(value = "/findByChannelManager", method = RequestMethod.GET)
public void findemp() {
List <HotelEntity> list = new ArrayList<>();
list = service.findByChannelManager (EnumCM.AR);
for (HotelEntity pro : list) {
System.out.println(pro);
}
}
}
#Service
#Transactional
public class HotelService {
#Autowired
private HotelDao dao;
public List<HotelEntity> findByChannelManager(EnumCM cm) {
return dao.findByChannelManager(EnumCM cm);
}
}
#Repository
public class HotelDaoImpl extends AbstractDao implements IHotelDao {
#SuppressWarnings({ "unchecked", "unused" })
#Override
public List<HotelEntity> findByChannelManager(EnumCM cm) {
List<HotelEntity> list = null;
try {
Session s = getSession();
Criteria criteria=s.createCriteria(Hotel.class);
criteria.add(Restrictions.eq("channelManager", "cm.name()"));
list = criteria.list();
}catch(Exception e) {
LOGGER.debug("error " +e.getMessage());
e.printStackTrace();
}
return list;
}
public abstract class AbstractDao {
#Autowired
private SessionFactory sessionFactory;
protected Session getSession() {
return sessionFactory.getCurrentSession();
}
}

Spring Java Config. Transaction problems

I have a spring application with java config:
#Controller
#RequestMapping("/")
public class MainController {
#Inject
#Named("dbDaoService")
IDaoService dbDaoService;
#RequestMapping(value="/saveNoteAsync", method = RequestMethod.POST)
public #ResponseBody String saveNoteAsync(#RequestBody CreateRequest createRequest, HttpServletRequest request) {
Notes newNote = new Notes(
createRequest.getTitle(),
createRequest.getNote(),
tagService.getTagMask(createRequest.getTags())
);
Long newId = dbDaoService.createNotes(newNote);
return ""+newId;
}
}
DBService:
#Service("dbDaoService")
public class DBDaoService implements IDaoService {
#PersistenceContext(unitName = "MyEntityManager")
private EntityManager entityManager;
private List<Tags> tags = null;
#Override
#Transactional
public Long createNotes(Notes data) {
entityManager.persist(data);
return data.getId();
}
}
Configuration class
#Configuration
#EnableWebMvc
#ComponentScan("ru.mypackage")
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/WEB-INF/views/**").addResourceLocations("/views/");
}
#Bean
public InternalResourceViewResolver getViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
}
#Bean
public BasicDataSource getBasicDataSource(){
BasicDataSource bds = new BasicDataSource();
bds.setDriverClassName("com.mysql.jdbc.Driver");
bds.setUrl("jdbc:mysql://localhost:3306/test");
bds.setUsername("root");
bds.setPassword("root");
return bds;
}
#Bean
public HibernateJpaVendorAdapter getHibernateJpaVendorAdapter(){
HibernateJpaVendorAdapter hjva = new HibernateJpaVendorAdapter();
hjva.setShowSql(true);
hjva.setGenerateDdl(true);
hjva.setDatabasePlatform("org.hibernate.dialect.MySQLDialect");
return hjva;
}
#Bean
public LocalContainerEntityManagerFactoryBean getEntityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setPersistenceUnitName("MyEntityManager");
em.setDataSource(getBasicDataSource());
em.setJpaVendorAdapter(getHibernateJpaVendorAdapter());
em.setPackagesToScan("ru.eastwind.persistance");
return em;
}
#Bean
public HibernateJpaDialect getHibernateJpaDialect(){
return new HibernateJpaDialect();
}
#Bean
public JpaTransactionManager getJpaTransactionManager(){
JpaTransactionManager jtm = new JpaTransactionManager();
jtm.setEntityManagerFactory(getEntityManagerFactory().getObject());
jtm.setJpaDialect(getHibernateJpaDialect());
return jtm;
}
}
In line entityManager.persist(data); I get the error:
javax.persistence.TransactionRequiredException: No transactional EntityManager available
But all select queries are woking correct! Please, help.
Use #EnableTransactionManagement on #Configuration class
#Configuration
#EnableWebMvc
#ComponentScan("ru.mypackage")
#EnableTransactionManagement
public class WebConfig extends WebMvcConfigurerAdapter {
// ... Your code
}
See Also : http://docs.spring.io/spring/docs/3.1.x/javadoc-api/org/springframework/transaction/annotation/EnableTransactionManagement.html

Add tenant dynamically in multitenant database application using Spring MVC and Hibernate

i am developing web application which uses multitenant database configuration.
I want to add tenant dynamically.
I added master controller to create master schema which hold tenant record created dynamically.
but problem is when i request to create tenant it went to MultitenantConnectionProvider i created database there but in database i want to scan package com.appointment.schedular.model.tenant and create table in ne database as well.
Source code
MasterDatabaseConfig.java
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(
basePackages = "com.appointment.schedular.dao.master",
entityManagerFactoryRef = "masterEntityManager",
transactionManagerRef = "masterTransactionManager"
)
#PropertySource("classpath:application.properties")
public class MasterDatabaseConfig {
#Autowired
private Environment springEnvironment;
#Bean(name="masterDataSource")
public DataSource masterDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(springEnvironment.getProperty("master.datasource.classname"));
dataSource.setUrl(springEnvironment.getProperty("master.datasource.url") + "?createDatabaseIfNotExist=true");
dataSource.setUsername(springEnvironment.getProperty("master.datasource.user"));
dataSource.setPassword(springEnvironment.getProperty("master.datasource.password"));
return dataSource;
}
#Bean(name = "masterEntityManager")
#Primary
public LocalContainerEntityManagerFactoryBean masterEntityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean
= new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(masterDataSource());
entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter);
entityManagerFactoryBean.setPackagesToScan(new String[]{"com.appointment.schedular.model.master"});
entityManagerFactoryBean.setJpaProperties(getHibernateProperties());
entityManagerFactoryBean.setPersistenceUnitName("master");
return entityManagerFactoryBean;
}
private Properties getHibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", springEnvironment.getProperty("hibernate.dialect","org.hibernate.dialect.MySQLDialect"));
properties.put("hibernate.show_sql", springEnvironment.getProperty("hibernate.show_sql", "true"));
properties.put("hibernate.format_sql", springEnvironment.getProperty("hibernate.format_sql", "true"));
properties.put("hibernate.hbm2ddl.auto", springEnvironment.getProperty("hibernate.hbm2ddl.auto", "update"));
return properties;
}
#Bean(name = "masterTransactionManager")
public JpaTransactionManager transactionManager(EntityManagerFactory masterEntityManager) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(masterEntityManager);
return transactionManager;
}
}
TenantDatabaseConfig.java
#Configuration
#EnableTransactionManagement
#ComponentScan("com.appointment.schedular.tenant")
#EnableJpaRepositories(
entityManagerFactoryRef = "tenantEntityManager",
transactionManagerRef = "tenantTransactionManager",
basePackages = {"com.appointment.schedular.dao.tenant"})
#PropertySource("classpath:application.properties")
public class TenantDatabaseConfig {
#Autowired
private Environment springEnvironment;
#Bean
public JpaVendorAdapter jpaVendorAdapter() {
return new HibernateJpaVendorAdapter();
}
#Bean(name = "tenantDataSource")
public DataSource tenantDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(springEnvironment.getProperty("tenant.datasource.classname"));
dataSource.setUrl(springEnvironment.getProperty("tenant.datasource.url")+"xy" + "?createDatabaseIfNotExist=true");
dataSource.setUsername(springEnvironment.getProperty("tenant.datasource.user"));
dataSource.setPassword(springEnvironment.getProperty("tenant.datasource.password"));
return dataSource;
}
#Bean(name = "tenantEntityManager")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
MultiTenantConnectionProvider connectionProvider,
CurrentTenantIdentifierResolver tenantResolver) {
LocalContainerEntityManagerFactoryBean emfBean = new LocalContainerEntityManagerFactoryBean();
emfBean.setDataSource(tenantDataSource());
emfBean.setPackagesToScan("com.appointment.schedular.model.tenant");
emfBean.setJpaVendorAdapter(jpaVendorAdapter());
Map<String, Object> properties = new HashMap<>();
properties.put(org.hibernate.cfg.Environment.MULTI_TENANT, MultiTenancyStrategy.SCHEMA);
properties.put(org.hibernate.cfg.Environment.MULTI_TENANT_CONNECTION_PROVIDER, connectionProvider);
properties.put(org.hibernate.cfg.Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, tenantResolver);
properties.put("hibernate.ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy");
properties.put("hibernate.dialect", springEnvironment.getProperty("hibernate.dialect"
, "org.hibernate.dialect.MySQLDialect"));
properties.put("hibernate.show_sql", springEnvironment.getProperty("hibernate.show_sql"
, "true"));
properties.put("hibernate.format_sql", springEnvironment.getProperty("hibernate.format_sql"
, "true"));
properties.put("hibernate.hbm2ddl.auto", springEnvironment.getProperty("hibernate.hbm2ddl.auto"
, "update"));
emfBean.setJpaPropertyMap(properties);
emfBean.setPersistenceUnitName("master");
return emfBean;
}
#Bean(name = "tenantTransactionManager")
public JpaTransactionManager transactionManager(EntityManagerFactory tenantEntityManager) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(tenantEntityManager);
return transactionManager;
}
}
MultitenantConnectionProviderImpl.java
#SuppressWarnings("serial")
#Component
#PropertySource("classpath:application.properties")
public class MultiTenantConnectionProviderImpl extends AbstractDataSourceBasedMultiTenantConnectionProviderImpl implements ApplicationListener<ContextRefreshedEvent> {
#Autowired
private Environment springEnvironment;
#Autowired
private TenantDao tenantDao;
#Autowired
#Qualifier("tenantDataSource")
DataSource masterDataSource;
/*#Autowired
#Qualifier("tenantEntityManager")
EntityManager*/
private final Map<String, DataSource> map = new HashMap<>();
#Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
init();
}
private void init() {
List<Tenant> tenants = tenantDao.findAll();
for (Tenant tenant : tenants) {
DataSource genDatasource = constructDataSource(tenant.getTenantKey());
map.put(tenant.getTenantKey(), genDatasource);
/*
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean
= new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(genDatasource);
entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter);
entityManagerFactoryBean.setPackagesToScan(new String[]{"com.appointment.schedular.model.tenant"});
Map<String, Object> properties = new HashMap<>();
properties.put("hibernate.ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy");
properties.put("hibernate.dialect", springEnvironment.getProperty("hibernate.dialect"
, "org.hibernate.dialect.MySQLDialect"));
properties.put("hibernate.show_sql", springEnvironment.getProperty("hibernate.show_sql"
, "true"));
properties.put("hibernate.format_sql", springEnvironment.getProperty("hibernate.format_sql"
, "true"));
properties.put("hibernate.hbm2ddl.auto", springEnvironment.getProperty("hibernate.hbm2ddl.auto"
, "update"));
entityManagerFactoryBean.setJpaPropertyMap(properties);
*/
}
}
private DataSource constructDataSource(String dbName) {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(springEnvironment.getProperty("tenant.datasource.classname"));
dataSource.setUrl(springEnvironment.getProperty("tenant.datasource.url") + dbName+ "?createDatabaseIfNotExist=true");
dataSource.setUsername(springEnvironment.getProperty("tenant.datasource.user"));
dataSource.setPassword(springEnvironment.getProperty("tenant.datasource.password"));
try {
dataSource.getConnection().createStatement().execute("CREATE DATABASE IF NOT EXISTS " + dbName);
} catch (Exception ex) {
System.out.println(ex);
}
return dataSource;
}
#Override
protected DataSource selectAnyDataSource() {
return masterDataSource;
}
#Override
protected DataSource selectDataSource(String key) {
return map.get(key);
}
public void addTenant(String tenantKey) {
map.put(tenantKey, constructDataSource(tenantKey));
}
}
TenantController.java
#Controller
#RequestMapping("/tenant")
public class TenantController {
#Autowired
TenantDao tenantRepo;
#Autowired
MultiTenantConnectionProviderImpl multiTenantConnectionProviderImpl;
#SuppressWarnings("rawtypes")
#CrossOrigin
#RequestMapping(value = "/",
method = RequestMethod.POST,
consumes = MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody String registerTenant(#RequestBody Map map) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
Tenant tenant = mapper.convertValue(map, Tenant.class);
String tenantKey = tenant.getName().replaceAll("[^a-zA-Z]+", "").toLowerCase().trim();
Optional<Tenant> previouslyStored = tenantRepo.findByTenantKey(tenantKey);
String response="Sorry your company name ("+tenant.getName()+")"+" is already taken";
if (!previouslyStored.isPresent()) {
tenant.setTenantKey(tenantKey);
tenantRepo.save(tenant);
multiTenantConnectionProviderImpl.addTenant(tenantKey);
response = "Successfully registered, your key is " + tenantKey;
return response;
}
return new ObjectMapper().writeValueAsString(response);
}
}
Replace your MultitenantConnectionProviderImpl.java with this code. Use inject service for creating your tables using configuration class.
#SuppressWarnings("serial")
#Component
#PropertySource("classpath:application.properties")
public class MultiTenantConnectionProviderImpl extends AbstractDataSourceBasedMultiTenantConnectionProviderImpl implements ApplicationListener<ContextRefreshedEvent>,ServiceRegistryAwareService {
#Autowired
private Environment springEnvironment;
#Autowired
private TenantDao tenantDao;
#Autowired
#Qualifier("dataSource1")
DataSource masterDataSource;
#Autowired
MultiTenantConnectionProvider connectionProvider;
#Autowired
CurrentTenantIdentifierResolver tenantResolver;
#Autowired
TenantDatabaseConfig tenantDatabaseConfig;
private final Map<String, DataSource> map = new HashMap<>();
#Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
init();
}
private void init() {
List<Tenant> tenants = tenantDao.findAll();
for (Tenant tenant : tenants) {
map.put(tenant.getTenantKey(), constructDataSource(tenant.getTenantKey()));
}
}
private DataSource constructDataSource(String dbName) {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(springEnvironment.getProperty("tenant.datasource.classname"));
dataSource.setUrl(springEnvironment.getProperty("tenant.datasource.url") + dbName+"?createDatabaseIfNotExist=true");
dataSource.setUsername(springEnvironment.getProperty("tenant.datasource.user"));
dataSource.setPassword(springEnvironment.getProperty("tenant.datasource.password"));
entityManagerFactory(dataSource,connectionProvider, tenantResolver);
return dataSource;
}
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource,
MultiTenantConnectionProvider connectionProvider,
CurrentTenantIdentifierResolver tenantResolver) {
LocalContainerEntityManagerFactoryBean emfBean = new LocalContainerEntityManagerFactoryBean();
emfBean.setDataSource(dataSource);
emfBean.setPackagesToScan("com.appointment.schedular.model.tenant");
emfBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
emfBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
Map<String, Object> properties = new HashMap<>();
properties.put(org.hibernate.cfg.Environment.MULTI_TENANT, MultiTenancyStrategy.DATABASE);
properties.put(org.hibernate.cfg.Environment.MULTI_TENANT_CONNECTION_PROVIDER, connectionProvider);
properties.put(org.hibernate.cfg.Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, tenantResolver);
properties.put("hibernate.ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy");
properties.put("hibernate.dialect", springEnvironment.getProperty("hibernate.dialect"
, "org.hibernate.dialect.MySQLDialect"));
properties.put("hibernate.show_sql", springEnvironment.getProperty("hibernate.show_sql"
, "true"));
properties.put("hibernate.format_sql", springEnvironment.getProperty("hibernate.format_sql"
, "true"));
properties.put("hibernate.hbm2ddl.auto", springEnvironment.getProperty("hibernate.hbm2ddl.auto"
, "update"));
emfBean.setJpaPropertyMap(properties);
emfBean.setPersistenceUnitName(dataSource.toString());
emfBean.afterPropertiesSet();
//emfBean.setEntityManagerFactoryInterface((EntityMana)emfBean);
//emfBean.setBeanName("srgsrohtak");
return emfBean;
}
public JpaTransactionManager transactionManager(EntityManagerFactory tenantEntityManager) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(tenantEntityManager);
transactionManager.afterPropertiesSet();
return transactionManager;
}
#Override
public void injectServices(ServiceRegistryImplementor serviceRegistry) {
Map lSettings = serviceRegistry.getService(ConfigurationService.class).getSettings();
DataSource localDs = (DataSource) lSettings.get("hibernate.connection.datasource");
masterDataSource = localDs;
}
#Override
protected DataSource selectAnyDataSource() {
return masterDataSource;
}
#Override
protected DataSource selectDataSource(String key) {
return map.get(key);
}
public void addTenant(String tenantKey) {
map.put(tenantKey, constructDataSource(tenantKey));
}
}

Categories