ishan
ishan

Reputation: 1232

Can instantiate hibernate session Factory directly but cannot do it through spring

I have started learning hibernate and spring through an assignment in which i am trying to use session factory instance through spring. I understood the hibernate part but just cant go on with spring. I have tried numerous tutorials and examples but just cant get my spring working. Although it works when i instantiate it directly. Here are the problem related details of my project...

applicationContext.xml (inside WEB-INF)

<?xml  version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
        http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

<context:annotation-config />
<context:component-scan
    base-package="com.nagarro.training.assignment6.dao.entity.Student" />



<bean id="sessionFactory"
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="configLocation" value="classpath:hibernate.cfg.xml"></property>
    <property name="hibernateProperties">
        <value>
            hibernate.dialect=org.hibernate.dialect.HSQLDialect
        </value>
    </property>
</bean>
<bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<tx:annotation-driven />

<bean id="studentDAO"
    class="com.nagarro.training.assignment6.dao.impl.StudentDAOImplementation">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>


</beans>

Edit: including changes as suggested StudentDAOImplementaion.java (the file where it is being used )

public class StudentDAOImplementation implements StudentDAO {

    /**
     * single instance of hibernate session
     */
    @Autowired
    private SessionFactory sessionFactory;

    // HibernateUtil.getSessionFactory().openSession()

    /**
     * @param sessionFactory
     */
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    /**
     * @return the sessionFactory
     */
    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    private Session getSession() {
        return this.sessionFactory.getCurrentSession();
    }
        /**
     * @return list of all the students
     */
    public List<Student> getStudentList() {

        System.out.println(this.getSession().getStatistics());

        return (List<Student>) this.getSEssion.createQuery("from Student")
                .list();
    }

}

And here is the snip of my jar files in lib folder: enter image description here

I think that i dont need to include hibernate files and beans as it is working fine without spring. Its the spring i cant get to work.I have tried many different implementation from the web but i just cannot get it working. It just says null pointer exception on ** System.out.println(sessionFactory.getStatistics());** line in StudentDAOImplementation.

Test class that calls StudentDAO

public class Test {

public static void main(String[] args) {
    StudentDAOImplementation sd = new StudentDAOImplementation();

    List<Student> list = sd.getStudentList();

    for(Student s : list) {
        System.out.println(s.getName());
    }
}

}

Stack trace

Exception in thread "main" java.lang.NullPointerException
    at StudentDAOImplementation.getStudentList(StudentDAOImplementation.java:116)
    at Test.main(Test.java:13)

Upvotes: 2

Views: 5006

Answers (2)

Ryan Stewart
Ryan Stewart

Reputation: 128779

Your sessionFactory variable is misleadingly named, since the type is actually Session. Session != SessionFactory. You're getting a NPE on sessionFactory.getStatistics() because there's no way that Spring can autowire a Session into a DAO like that. If you're not seeing an error before the NPE, then you're not actually instantiating the DAO with Spring, or else you'd get an error about not being able to find a dependency of type Session. The appropriate way to use a Hibernate-based DAO is to inject it with a SessionFactory and call getCurrentSession() in your methods where you need a Session. See "Implementing DAOs based on plain Hibernate 3 API" and following for details about this approach and about setting up appropriate transaction management.

Update: On a second glance, I see that the package for your component-scan is set to com.nagarro.training.assignment6.dao.entity.Student, which looks exactly like a class, not a package. It's also not even close to anything you'd actually want to component-scan. Maybe you don't understand what component-scan is for. It's covered under "Annotation-based container configuration" in the reference guide.

Update 2: About your "test" code: you're not using Spring at all, so you might as well remove the XML and save yourself the trouble. On the other hand, if you'd like to actually use Spring, you'd need to create a context in your main method based on said XML file, such as:

ApplicationContext context = new FileSystemXmlApplicationContext(locationOfXmlFile);

Then if you want a Spring-managed DAO, you can't just create one with new. Spring isn't magic. It doesn't grab control away from you just because you have it loaded somewhere in the same JVM.* You have to ask Spring for the DAO that it created, like:

StudentDAO dao = context.getBean(StudentDAO.class);

Note that I used the interface type, not the concrete type. That's always an advisable practice for numerous reasons.

This (not starting Spring) is your first problem. As soon as you do this, you're going to run into other problems with your configuration. You should post a new question if you need help solving one of them.

*Unless you're using AspectJ weaving to inject arbitrary objects.

Upvotes: 2

Dhanush Gopinath
Dhanush Gopinath

Reputation: 5739

You are injecting a Session instead of SessionFactory with @Autowired private Session sessionFactory; in the DAO class. It needs to be a SessionFactory , like this @Autowired SessionFactory sessionFactory;

And then use it like this to do a DAO operations like save

Session session = sessionFactory.getCurrentSession()
session.persist(entity);

EDIT

Your testcase should be something like this

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:<path_to_your_appcontext.xml>" })
public class StudentDAOTest {

@Autowired
private StudentDAO studentDAO

@Test
public void test() {
      List<Student> list = studentDAO.getStudentList();
      assertNotNull(list)
}
}

Upvotes: 1

Related Questions