How to implement Spring boot + Hibernate - java

I am getting this error:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field sessionFactory in com.demo.dao.EmployeeDAO required a bean of type 'org.hibernate.SessionFactory' that could not be found.
Action: Consider defining a bean of type 'org.hibernate.SessionFactory' in your configuration.
My HibernateUtil class is:
#Configuration
public class HibernateUtil {
#Autowired
private EntityManagerFactory factory;
#Bean
public SessionFactory getSessionFactory() {
if(factory.unwrap(SessionFactory.class) == null) {
throw new NullPointerException("Factory is not a hibernate factory.");
}
return factory.unwrap(SessionFactory.class);
}
}
my EmployeeDao class is:
#Repository
public class EmployeeDAO {
#Autowired
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sf){
this.sessionFactory = sf;
}
public void save(Employee emp) {
Session session = null;
try {
session = sessionFactory.openSession();
System.out.println("Session got.");
Transaction tx = session.beginTransaction();
session.save(emp);
tx.commit();
}catch(HibernateException he) {
he.printStackTrace();
}
}
}
application.properties file,
spring.mvc.view.prefix=/pages/
spring.mvc.view.suffix=.jsp
spring.datasource.url=jdbc:mysql://localhost:3306/manissh
spring.datasource.username=root
spring.datasource.password=admin
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext

try to create Autowired sessionFactory in your Repository
#Repository
public class EmployeeDAO {
private SessionFactory sessionFactory;
#Autowired
public EmployeeDAO(EntityManagerFactory entityManagerFactory) {
this.sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
}
}
or try this solution - https://stackoverflow.com/a/43895827/6582610

You need not create session. Just add the dependency spring-boot-starter-jpa in pom.xml to use hibernate.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
If you do so , then you can directly give the query in repository.

Related

My Injected sessionFactory instance is null

When I inject my sessionFactory Bean using Java based configuration for Hibernate my bean is null and I don't know why. I've scoured the internet for answers but couldn't find any. I've looked over my configuration and compared it against guides online. Any answers are greatly appreciated.
Here's the exact error
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "org.hibernate.SessionFactory.getCurrentSession()" because "com.example.demo.DemoApplication.sessionFactory" is null
Here's my code
HibernateConfiguration File, Annotation based.
#Configuration
#EnableTransactionManagement
public class HibernateConfig {
#Bean
#Scope //By default the scope is singleton which means that the IOC will only create a single instance of the bean and return that one reference for subsequent calls for that bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan( packagesToScan()); //Model packages to scan
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
//Direct Physical Connection Information
#Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/demo");
dataSource.setUsername("root");
dataSource.setPassword("password");
return dataSource;
}
#Bean
public PlatformTransactionManager hibernateTransactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
//List of Entities to scan
#Bean
public String [] packagesToScan() {
return new String [] { "com.example.demo.Entities.Student" };
}
//Configures properties of our hibernate configuration, dialect,
private final Properties hibernateProperties() {
Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", "create");
hibernateProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
hibernateProperties.setProperty("show_sql", "true");
hibernateProperties.setProperty("current_session_context_class", "thread");
return hibernateProperties;
}
}
My Main application where I'm attempting to inject my Session Factory singleton bean for use.
#SpringBootApplication
public class DemoApplication {
#Autowired
static SessionFactory sessionFactory;
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AnimalConfig.class, HibernateConfig.class); // Makes the sessionFactory bean known to the IOC
Session currentSession = sessionFactory.getCurrentSession();
(( ConfigurableApplicationContext )ctx).close(); //Close the applicationContext
SpringApplication.run(DemoApplication.class, args);
}
}
The container gets started when SpringApplication.run invokes. I think before all of this an injection and the usage of that bean does not makes sense. First you need to fire Springapplication and then the rest of the business logic.
Your bean isn't scanned and initialize at the moment of the injection.
Possible solution :
#Component
public class IOCAfterInitializationListener implements ApplicationListener<ContextRefreshedEvent> {
#Autowired
static SessionFactory sessionFactory;
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
Session currentSession = sessionFactory.getCurrentSession();
//do whatever you want
}
}

Spring 5 + Hibernate 5 : How SessionFactory is getting Autowired with LocalSessionFactoryBean

I am developing REST apis using Spring MVC 5.0.8 and Hibernate 5.2.11
I have created AppConfig class,in which I have created getSessionFactory() method with return type LocalSessionFactoryBean
#Bean
public LocalSessionFactoryBean getSessionFactory() {
LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
factoryBean.setDataSource(dataSource());
factoryBean.setPackagesToScan("saptarsi.auditdb.model");
factoryBean.setHibernateProperties(hibernateProperties());
return factoryBean;
}
And Inside DaoImpl class I have autowired SessionFactory
#Repository
public class LOcaldbDaoImpl implements LocaldbDao {
#Autowired
private SessionFactory sessionFactory;
private Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
#Override
public void getAllApiDetails(HttpRequestEntity<ApiDetailsFilterDto> requestEntityDto) {
}
}
And everything is working fine
But I want to know how SessionFactory is getting autowired.
Because I am not returning factoryBean.getObject(),which is responsible to return SessionFactory type object.
And #Autowire will look for SessionFactory type in Bean factory.
So how Autowiring is happening ?
Because after you initialized the LocalSessionFactoryBean, the buildSessionFactory method was called. Link to calling.
protected SessionFactory buildSessionFactory(LocalSessionFactoryBuilder sfb) {
return (this.bootstrapExecutor != null ? sfb.buildSessionFactory(this.bootstrapExecutor) :
sfb.buildSessionFactory());
}
After that, SessionFactory bean will be in the ApplicationContext.
All Spring beans was load in ApplicationContext. Try to read here more https://docs.spring.io/spring/docs/1.2.x/reference/beans.html

sessionFactory not being injected. It's always null

I'm sessionFactory on my service.
#Component
public class MyService {
#Autowired
private SessionFactory sessionFactory;
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
public void persistData(){
...
tx.commit();
session.close();
}
I call this service from
#Component
public class CommandLineApp implements CommandLineRunner {
#Autowired
private MyService MyService
public void run(String... args) throws Exception {
MyService.persistData();
}
}
My main class that start spring boot:
#SpringBootApplication
public class App{
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
When I call MyService it's getting the error nullPointException. When I debug the code I can see that the sessionFactory is null. Why is sessionFactory is not being injected on MyService?
The problem here is the SessionFactory bean is still not
available to the spring container for you to inject.
So first you need to bootstrap it.
Create an #configuration file
or add #Configuration to your Main.java and bootstrap your beans like below
#Configuration
public class HibernateSessionProvider {
#Bean // If using hibernate.cfg.xml
public void getSessionFactory() {
AnnotationSessionFactoryBean annotationSessionFactoryBean = new AnnotationSessionFactoryBean();
...
return annotationSessionFactoryBean()
}
#Bean // If using java based config to provide DataSource beans , hibernate config
public void getSessionFactory() {
LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
...
return localSessionFactoryBean()
}
}

Spring Hibernate not committing data

I have a Spring MVC application we're developing, using Spring 4.2.3 and Hibernate 5.0.6. In some of our testing we found that some of our data is not being saved to the database (Oracle). The code is as follows:
#Service
#Transactional
public class MyService {
#Autowired
private MyDao dao;
public void saveCustomer(Customer c) {
dao.saveCustomer(c);
}
}
#Repository
#Transactional
public class MyDao {
#Autowired
private SessionFactory sessionFactory; // Hibernate's SessionFactory
public void saveCustomer(Customer cust) {
sessionFactory.getCurrentSession().clear();
sessionFactory.getCurrentSession().flush();
sessionFactory.getCurrentSession().save(cust);
}
}
To be honest, I just saw that #Transactional on MyDao, as I'm writing this. That probably is wrong, since #Transactional is already on the service layer.
We're using Java Config....showing the relevant beans....
#Configuration
#EnableWebMvc
#EnableTransactionManagement
#ComponentScan({"my.package"})
public class Config extends WebMvcConfigurerAdapter {
#Bean(name = "sessionFactory")
public SessionFactory getSessionFactory(ComboPooledDataSource dataSource) {
LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(dataSource);
sessionBuilder.scanPackages("my.entities");
sessionBuilder.addProperties(getHibernateProperties());
return sessionBuilder.buildSessionFactory();
}
#Bean(name = "transactionManager")
public HibernateTransactionManager getTransactionManager(SessionFactory sessionFactory) {
HibernateTransactionManager transactionManager = new HibernateTransactionManager(sessionFactory);
return transactionManager;
}
}
My question is, other than the #Transactional on MyDao, which shouldn't be there, is there anything else that stands out to anyone as to why Customer does not save to the database? Are we even doing transactions correctly? I've never liked using Hibernate's SessionFactory, but that's the way we went. Are we using it correctly within a Spring Transaction?
Thanks!
Chris

JSF2+Hibernate4+Spring3 Integration

Hi Right now i am using JSF2+Hibernate in my web project but I know Spring is very popular and powerful framework(i am new in Spring) so i am thinking to integrate Spring and Hibernate4 in my project so i was looking for some demo example in google , but i noticed in maximum places people used below code for Session initialization
public class UserDAO implements IUserDAO {
private SessionFactory sessionFactory;
/**
* Get Hibernate Session Factory
*
* #return SessionFactory - Hibernate Session Factory
*/
public SessionFactory getSessionFactory() {
return sessionFactory;
}
/**
* Set Hibernate Session Factory
*
* #param SessionFactory - Hibernate Session Factory
*/
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
Is this good way to create SessionFactory object in each DAO class ? Or any better way to handle Database connection? So that no any chance for session mismanagement.Please help me to implement best way .
Thanks
Add BaseDAO
Extend each your DAO (extends BaseDAO)
Add sessionFactory only into BaseDAO and make protected SessionFactory sessionFactory.
And you will have access to sessionFactory from all DAOs which extend BaseDAO.
abstract public class BaseDAO {
protected SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}
public class UserDAO extends BaseDAO implements IUserDAO {
...
}
it will work.
#Transactional
public class ProductDaoImpl implements ProductDao {
private SessionFactory sessionFactory;
#Resource
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public void save(Product product) {
Session session = getSessionFactory().openSession();
try {
session.save(product);
} finally {
session.close();
}
}
}

Categories