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();
}
}
}
Related
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.
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
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()
}
}
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
I have a Spring application that connects to two databases at the same time. So I have for this two LocalSessionFactoryBean instances for each connection like this:
#Bean
public LocalSessionFactoryBean firstSessionFactory() {
final LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean();
lsfb.setPackagesToScan("ro.mycompany.myproject.classes");
lsfb.setDataSource(dataSourceOne);
lsfb.setEntityInterceptor(auditInterceptor1);
lsfb.setHibernateProperties(getHibernateProperties1());
return lsfb;
}
#Bean
public LocalSessionFactoryBean secondSessionFactory() {
final LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean();
lsfb.setPackagesToScan("ro.mycompany.myproject.classes2");
lsfb.setDataSource(dataSourceTwo);
lsfb.setEntityInterceptor(auditInterceptor2);
lsfb.setHibernateProperties(getHibernateProperties2());
return lsfb;
}
For the DAO layer I have a class that injects the SessionFactory object like this.
public class GenericDAOImpl extends HibernateDAOSupport implements GenericDAO {
#Autowired
private SessionFactory sessionFactory;
//Other methods goes here
}
I instantiate the beans in my config file like this:
#Bean
public GenericDAO firstGenericDAO() {
final GenericDAOImpl genericDAO = new GenericDAOImpl();
return genericDAO;
}
#Bean
public GenericDAO secondGenericDAO() {
final GenericDAOImpl genericDAO = new GenericDAOImpl();
return genericDAO;
}
How can I make the firstGenericDAO to use firstSessionFactory and secondGenericDAO to use secondSessionFactory without creating the setters method? I want to use both connection at the same time so also Spring profiles won't help me.
Thank you
Either use #Qualifier("...") in addition to #Autowired or just use #Resource(name = "..."). Personally I prefer using #Resource as it replaces the two Annotations with the single one.
In your case, #Resource(name = "firstSessionFactory") and #Resource(name = "secondSessionFactory") respectively.
For you following code,
public class GenericDAOImpl extends HibernateDAOSupport implements GenericDAO {
#Autowired
private SessionFactory sessionFactory;
//Other methods goes here
}
Spring should be known clearly which bean would be autowired. That means, there should be setter method or some other variable to distinguish your sessionFactory1 and sessionFactory2.
Just as you said, xml-based is still power than annotation. If you don't want to use XML based, and don't want setter method either, I think sessionFactory can be initialized by another variable to identify which bean used.
For example,
public class GenericDAOImpl extends HibernateDAOSupport implements GenericDAO {
private SessionFactory sessionFactory;
public GenericDAOImpl(boolean tag) {
super();
ApplicationContext apx = new AnnotationConfigApplicationContext(xxxx.class);
sessionFactory = tag ? (SessionFactory) apx.getBean("sessionFactory1")
: (SessionFactory) apx.getBean("sessionFactory1");
}
}
Of course, you need to specify the bean name for LocalSessionFactoryBean with #Bean(name = "sessionFactory1") and #Bean(name = "sessionFactory2")