#Transactional annotation not working in Spring MVC - java

#Transactional is not working in spring mvc. suppose i removed
#Transactional annotation data is reached to RepositoryClass.
Throwable targetException - org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(Object...)
i need to reach data to repository class.
please help me.,
Thank you.
ServiceImplClass
#Service("userService")
public class UserServiceImpl implements UserService{
#Autowired
UserRepository userRepository;
public String saveUserData(User user,HttpSession session) {
return userRepository.saveUserData(user);
}
}
RepositoryClass:
#Component
#Transactional
public class UserRepository {
#Autowired
protected SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public String saveUserData(User user) {
final Session session = (Session) getSessionFactory();
try {
session.beginTransaction();
Query query=session.createQuery("UPDATE User set user_Name =:userName,"
+ "reg_Date =:regDate,"
+ "img_Id=:imgId, emailId =:emailId");
query.setParameter("userName", user.getUserName());
query.setParameter("regDate", user.getRegDate());
query.setParameter("imgId", user.getImgId());
query.setParameter("emailId", user.getEmailId());
session.save(user);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
dispatcher-servlet.xml
<?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:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
">
<context:annotation-config />
<context:component-scan base-package="com.demo.app" />
<mvc:default-servlet-handler />
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes" value="text/plain;charset=UTF-8" />
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<bean id="jspViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/html/" />
<property name="suffix" value="html" />
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/UserDB" />
<property name="username" value="root" />
<property name="password" value="password" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.demo.app.model.User</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean
class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="java.lang.Exception">Error</prop>
</props>
</property>
</bean>
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="2097152" />
</bean>
</beans>

You're managing your transactions manually. That's the task of transaction manager. saveUserData should be like:
public User saveUserData(User user) {
return (User)sessionFactory.getCurrentSession().merge(user);
}
And that's it.
And you'll probably want to annotate your service with #Transactional and not repository.

Your Repository don`t use #component annotation. and you use
<jpa:repositories base-package="your.package.put.repository"></jpa:repositories>
so, you already used
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>

First of all all transaction and session should managed by spring container is good practice so please don't manage session at your own, just use the existing session for data base querying. Now, for only your situation, try #Transactional annotation at Controller level and if it will work then you require some modification as per given below.
For web MVC Spring app should #Transactional go on controller or service?

Use #Transactional at Service level and when one of the operations doesnt work as it should(for example, an update operation returns 0 which means it failed) throw new RuntimeException(). If one of the operation fails, all other operations which are part of the transaction will be rolled back.

You are trying to use both container managed transaction and User managed transaction at the same time. Try to use only one at a time.
Either remove #Transactional annotation or remove the transaction statements from your method.

Related

Dispacter Servelt xml file

I am working on project with Spring mvc and i want to use jpa features as well.
I have an 3 entity classes, their corresponding repository interfaces. I have their autowired objects in common service class. However I am facing issues while creating bean for this service class object which is used in controller.
The 3 model class are User, Appointment and Notification.
The repository interface extends CRUDRepository interface.
Service class :
#Service
public class EHealthService
{
#Autowired
UserRepository uRepo;
#Autowired
AppointmentRepository aRepo;
#Autowired
NotificationRepository nRepo;
public void registerUser(User u)
{
uRepo.save(u);
}
public boolean login(User u)
{
if(uRepo.findByemail(u.getEmail())!=null)
return true;
else
return false;
}
public List<User> getDoctorList()
{
return uRepo.findByisdoctor(true);
}
// some more functions
}
Controller class:
#Controller
public class EHealthController
{
#Autowired
EHealthService eservice;
//Some code
}
ehealth-dispacter-servlet.xml file:
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<context:component-scan base-package="com.cl3.controller" />
<context:component-scan base-package="com.cl3.model" />
<context:component-scan base-package="com.cl3.service" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
<property name="generateDdl" value="true"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<property name="packagesToScan" value="com.cl3.model"/>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
<jpa:repositories base-package="com.cl3.model"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql://localhost:5432/cl3" />
<property name="username" value="ucan" />
<property name="password" value="ucan" />
</bean>
<bean id="eservice" class="com.cl3.service.EHealthService">
<property name="uRepo" ref="uRepo"></property>
<property name="nRepo" ref="nRepo"></property>
<property name="aRepo" ref="aRepo"></property>
</bean>
<bean id="uRepo" class="com.cl3.model.UserRepository">
</bean>
<bean id="nRepo" class="com.cl3.model.NotificationRepository">
</bean>
<bean id="aRepo" class="com.cl3.model.AppointmentRepository">
</bean>
It says the class is an interface.
What will be the bean for eservice object and to enable jpa in dispacter servel xml file?
Thank you.
If you are using spring xml based configuration then add below bean's to configuration file :
<bean id="entityManagerFactoryBean" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- This makes /META-INF/persistence.xml is no longer necessary -->
<property name="packagesToScan" value="com.howtodoinjava.demo.model" />
<!-- JpaVendorAdapter implementation for Hibernate EntityManager.
Exposes Hibernate's persistence provider and EntityManager extension interface -->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">validate</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
</props>
</property>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/test" />
<property name="username" value="root" />
<property name="password" value="password" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoryBean" />
Register component scanning by adding this binding annotation in xml file :
<context:component-scan base-package="com.mycompany.projectname.demo" />
If your project is spring mvc the add below binding annotation to xl file
<!-- This allow for dispatching requests to Controllers -->
<mvc:annotation-driven />
For declarative transaction management add below piece in xml file.
<tx:annotation-driven />
Basically you no need to add service bean in xml configuration file if you are enabled component scanning feature in spring.
Add required dependencies to integrate jpa with spring.
Refer this link will help you more :
https://howtodoinjava.com/jpa/spring-hibernate-jpa-configuration-example/

Spring Transaction Hibernate #Transaction annotation not working with #Autowired

Spring Transaction Hibernate #Transaction annotation is not working with #Autowired correctly. If I create the Dao`` element byxml(UserDao2 userDao2)`,
the transactional anotation in the Service class is working, if its by #Repository annotation in the Dao class when tries to getCurrentSesion, says:
org.hibernate.HibernateException: No Session found for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97) ~[spring-orm-3.2.8.RELEASE.jar:3.2.8.RELEASE]
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:993) ~[hibernate-core-4.2.11.Final.jar:4.2.11.Final]
It appears that is not linking well the #Transactional annotation with the session factory
Library versions:
<jdk.version>1.6</jdk.version>
<spring.version>3.2.8.RELEASE</spring.version>
<spring.security.version>3.2.3.RELEASE</spring.security.version>
<hibernate.version>4.2.11.Final</hibernate.version>
spring-database.xml
<context:annotation-config />
<jee:jndi-lookup id="datasourcenn" jndi-name="java:/comp/env/nn_datasource" />
<bean id="sesionHibernate"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="datasourcenn"/>
<property name="packagesToScan" value="com.web.entity"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle9iDialect</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.show_sql">true</prop>
<!-- nuevas properties de configuraciĆ³n -->
<prop key="hibernate.c3p0.min_size">5</prop>
<prop key="hibernate.c3p0.max_size">50</prop>
<prop key="hibernate.c3p0.timeout">300</prop>
<prop key="hibernate.c3p0.max_statements">50</prop>
<prop key="hibernate.bytecode.provider">cglib</prop>
</props>
</property>
</bean>
<bean id="us" class="com.web.dao.UserDaoImpl">
<property name="sesionHibernate" ref="sesionHibernate" />
</bean>
<!-- -->
<bean id="userDao2" class="com.web.dao.UserDao2Impl">
<property name="sesionHibernate" ref="sesionHibernate" />
</bean>
<bean id="myUserDetailsService" class="com.web.service.UsuarioServiceImpl">
<property name="userDao" ref="us" />
</bean>
<!--
proxy-target-class="true" mode="aspectj"
-->
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sesionHibernate"></property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
UserDao2 (I remove #Repository if I create it by xml)
#Repository
public class UserDao2Impl implements UserDao2 {
private static Logger log = LoggerFactory.getLogger(UserDao2Impl.class);
#Autowired
#Qualifier("sesionHibernate")
private SessionFactory sesionHibernate;
#SuppressWarnings("unchecked")
public Usuario findByUserName(String username) {
try {
log.info("findByUserName" + sesionHibernate);
List<Usuario> users = new ArrayList<Usuario>();
System.out.println(sesionHibernate+"\n----------");
users = sesionHibernate.getCurrentSession().createQuery("from Usuario where nombre=?").setParameter(0, username).list();
// users = sesionHibernate.getCurrentSession().createQuery("from Usuario
// where nombre=?").setParameter(0, username).list();
if (users.size() > 0) {
return users.get(0);
} else {
return null;
}
} catch (Exception e) {
log.error("findByUserName ", e);
return null;
}
}
Usuario2ServiceImpl If have the service with #Transacional
#Service
#Transactional
public class Usuario2ServiceImpl implements Usuario2Service {
private static Logger log = LoggerFactory.getLogger(Usuario2ServiceImpl.class);
//Qualifier("userDaoImpl")
#Autowired
private UserDao2 userDao2;
#Override
public com.web.entity.Usuario getUsuariodetalles(final String nombreUsuario) throws UsernameNotFoundException {
log.info("getUsuariodetalles - 1");
System.out.println("ssss"+userDao2);
com.web.entity.Usuario usuario = userDao2.findByUserName(nombreUsuario);
log.info("getUsuariodetalles - 2");
return usuario;
}
Did you try putting #Transactional annotation at service layer method, you have placed it on class. I think it should work.
I solved in Tomcat the issue by putting in the spring-database.xml the next line:
<context:load-time-weaver aspectj-weaving="autodetect"/>
But it doesn't work in JBoss, which is where i need to deploy the final version. Other solution?
In Jboss i need to create both things in the xml(Service and Dao), keeping the transactional annotatations. But i doesn't work if create them(dao & service) with #Repository or #Service.
Solution, i add to mvc-dispatcher-servlet.xml, mvc:interceptors configuration to open session with org.springframework.orm.hibernate4.support.OpenSessionInViewInterceptor. Just need to define the sessionFactory in the properties.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
">
<context:annotation-config />
<context:component-scan base-package="com.web" />
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean name="OpenSessionInViewInterceptorCom" class="org.springframework.orm.hibernate4.support.OpenSessionInViewInterceptor">
<property name="sessionFactory">
<ref bean ="sesionHibernate" />
</property>
</bean>
</mvc:interceptor>
</mvc:interceptors>
<!-- Configures the #Controller programming model -->
<mvc:annotation-driven />
<mvc:resources mapping="/css/**" location="/css/" />
<mvc:resources mapping="/img/**" location="/img/" />
<mvc:resources mapping="/js/**" location="/js/" />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
</beans>

Unable autowire SessionFactory[null] into #Transactional bean

I have faced very strange issue with autowiring Hibernate SessionFactory bean into my Service.
I'm able to find SessionFactory bean in Spring Context object. So no issues with creating such bean.
But I can not autowire this bean into my service when it is marked with #Transactional annotation. Factory field is null.
Once I remove this annotation - everything works good.
Service Class:
#Service
#Transactional
public class ExampleRunner implements Runnable{
#Autowired
SessionFactory sessionFactory;
...
}
applicationContext.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:property-placeholder location="classpath:application.properties"
ignore-resource-not-found="true" />
<context:component-scan base-package="org.edu" />
<context:annotation-config />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"
value="${jdbc.driverClassName:org.hsqldb.jdbcDriver}" />
<property name="url" value="${jdbc.url:jdbc:hsqldb:mem:myAppDb}" />
<property name="username" value="${jdbc.username:sa}" />
<property name="password" value="$jdbc.password:}" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="org.edu" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
${hibernate.dialect:org.hibernate.dialect.HSQLDialect}
</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto:create-drop}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql:true}</prop>
<prop key="hibernate.format_sql">true</prop>
</props>
</property>
</bean>
<tx:annotation-driven transaction-manager="txManager"
proxy-target-class="true" />
<bean id="txManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
Usage:
public static void main(String[] args) {
Runnable runner = new ClassPathXmlApplicationContext("applicationContext.xml").getBean(ExampleRunner.class);
runner.run();
}
Seems like when I make #Transactional as class level annotation Spring creates CGLib proxy bean where SessionFactory field is null.
But when I use #Transational as method level annotation everything works good.
So I just want to understand such behavior.
What have I missed from Spring documentation?
I use Spring 4.1.4.RELEASE.
I got your error actually why you getting problem here because you not allowing container to auto-wired bean for you as you using java Main method it will not auto-wired bean that's why you getting error.

Spring AnnotationSessionFactoryBean NullPointerException

I am a newbie to Spring and trying to integrate Spring and Hibernate. But I am facing nullpointer in SessionFactory.
Error Description:
java.lang.NullPointerException
com.ume.dao.UserDaoImpl.openSession(UserDaoImpl.java:29)
com.ume.dao.UserDaoImpl.getUser(UserDaoImpl.java:34)
com.ume.LoginController.getUserCredentials(LoginController.java:39)
Another Error Description
org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63)
org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:544)
com.ume.dao.UserDaoImpl.openSession(UserDaoImpl.java:31)
com.ume.dao.UserDaoImpl.getUser(UserDaoImpl.java:37)
com.ume.service.UserServiceImpl.getUser(UserServiceImpl.java:23)
My dispatchar-servlet.xml
<?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:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:property-placeholder location="classpath:jdbc.properties" />
<context:component-scan base-package="com.nptest" />
<mvc:annotation-driven />
<bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean class="org.springframework.context.support.ResourceBundleMessageSource" id="messageSource">
<property name="basename" value="messages" />
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${database.driver}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.user}" />
<property name="password" value="${database.password}" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.nptest.pojo.UserPojo</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
</props>
</property>
</bean>
<bean id="hibernateTransactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
</beans>
My DAOImplementation class
#Repository
public class UserDaoImpl implements UserDao{
#Autowired
private SessionFactory sessionFactory;
private Session openSession()
{
return sessionFactory.getCurrentSession();
}
public UserPojo getUser(String username, String password)
{
List<UserPojo> userlist=new ArrayList<UserPojo>();
Query query=openSession().createQuery("from UserPojo u WHERE u.login=:username AND u.userpwd=:password");
query.setParameter("login",username);
query.setParameter("password",password);
System.out.println("MADAN Query "+ query);
userlist=query.list();
if(userlist.size()>0)
return userlist.get(0);
else return null;
}
}
My Service Interface
public interface UserService {
public UserPojo getUser(String username,String password);
}
My Service Implementation class
#Service
public class UserServiceImpl implements UserService {
#Autowired
private UserDao userDao;
#Transactional
public UserPojo getUser(String username, String password) {
return userDao.getUser(username, password);
}
My controller class from where I make these call, I have instantiated the Service class by this
#Autowired
private UserService userservice;
And in the method I called
UserPojo user=userservice.getUser(username, password);
looks like you have instantiated a UserDaoImpl manually, the sessionFactory didn't get wired, please post the code how you use UserDaoImpl
add annotation to UserDaoImpl and put it under package com.nptest
package com.nptest.dao;
#Repository public class UserDaoImpl implements UserDao
then autowired UserDaoImpl in your app
--edit--
to enable annotation based transcation, you have to add
<tx:annotation-driven transaction-manager="hibernateTransactionManager"/>
in the application context xml

Creating persistance layer with spring/hibernate

I'm trying to create a persistance project so it can be re-used by some other projects I'm building on top. I.e it will be used by a web service/spring mvc project and by standalone jar which does some file processing.
I've used hibernate with spring mvc before but never as a standalone executable java jar so I have everything setup and working(application context) :
<?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:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- Enable annotation style of managing transactions -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- Root Context: defines shared resources visible to all other web components -->
<!-- HIBERNATE -->
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:spring.properties" />
</bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driverClassName}" />
<property name="jdbcUrl" value="${jdbc.databaseurl}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="acquireIncrement" value="5" />
<property name="idleConnectionTestPeriod" value="60"/>
<property name="maxPoolSize" value="100"/>
<property name="maxStatements" value="50"/>
<property name="minPoolSize" value="10"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingResources">
<list> <value>com/project/utility/persistence/mapping/TestProp.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${jdbc.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- END HIBERNATE -->
</beans>
When I test it from main class everything looks ok with mapping/dependencies :
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("appCtx.xml");
}
What I want to do next is to build few dao classes which will get some data and I'd build some interface above that so it can be re-used by both webservice and processing tool as a jar(maven dependency).
In order to build dao classes I need sessionFactory to be != null always. How do I do this?
There are many approaches to this. One solution I use is to use the javax.persistence.PersistenceContext annotation. Spring will respect this annotation and inject a proxy to a thread local EntityManager. Provided your DAO is created by Spring this allows access to the entity manager from within your DAO.
public class DAO {
private EntityManager entityManager;
#PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
}
#Repository
public class MyDAO {
#Autowired
private SessionFactory sessionFactory;
// ...
}
and add the MyDAO bean to the context XML file, or simply add the following lines to this file:
<context:annotation-config />
<context:component-scan base-package="one.of.the.parent.packages.of.your.dao" />

Categories