Exception - createQuery is not valid without active transaction [duplicate] - java

This question already has answers here:
Java and Spring. Transactional annotation #Transactional
(3 answers)
Closed 7 years ago.
I need to use Transactional annotation. How it should be done?
Now , exception is org.hibernate.HibernateException: createQuery is not valid without active transaction.
If I remove thread, that will be exception - No Session found for current thread.
What else should I do?
CoursesDAO.java
public interface CoursesDAO {
public Course createCourse(Course course);
public Course findCourseById(Integer key);
public Course updateCourse(Course course);
public void deleteCourse(Course course);
public List<Course> getAllCourses();
public List<Course> getAllCoursesByCategory(String category);
public List<Course> getAllCoursesWhichNoProposal( );
}
CoursesDAOImpl.java
#Repository
public class CoursesDAOImpl implements CoursesDAO {
#Autowired
private SessionFactory sessionFactory;
public Course createCourse(Course course) {
Session session = sessionFactory.getCurrentSession();
Integer id = (Integer) sessionFactory.getCurrentSession().save(course);
course.setId(id);
return course;
};
public Course findCourseById(Integer id) {
Session session = sessionFactory.getCurrentSession();
Course course = (Course) session.get(Course.class, id);
return course;
}
public Course updateCourse(Course course) {
Session session = sessionFactory.getCurrentSession();
session.merge(course);
return course;
};
public void deleteCourse(Course course) {
Session session = sessionFactory.getCurrentSession();
session.delete(course);
};
public List<Course> getAllCourses() {
Session session = sessionFactory.getCurrentSession();
List listCourses = session.createQuery("from Course").list();
return listCourses;
}
public List<Course> getAllCoursesByCategory(String category) {
Session session = sessionFactory.getCurrentSession();
List listCoursesByCategory = session.createQuery("from Course c where c.category='"+category+"'").list();
return listCoursesByCategory;
}
public List<Course> getAllCoursesWhichNoProposal( ) {
Session session = sessionFactory.getCurrentSession();
List listCoursesNoProposal = session.createQuery("from Course c where c.state not like 'Proposal' and c.state not like 'Rejected'").list();
return listCoursesNoProposal;
}
}
CourseService.java
public interface CourseService {
public Course findCourseById(Integer id);
public Course updateCourse(Course course);
public Course createCourse(Course course);
public void deleteCourse(Course course);
public List<Course> getAllCourses();
public List<Course> getAllCoursesByCategory(String category);
public List<Course> getAllCoursesWhichNoProposal( );
}
CourseServiceImpl.java
#Service
public class CourseServiceImpl implements CourseService {
#Autowired
private CoursesDAO coursesDAOImpl;
#Transactional
public Course findCourseById(Integer id) {
Course course = coursesDAOImpl.findCourseById(id);
return course;
}
#Transactional
public Course updateCourse(Course course) {
course = coursesDAOImpl.updateCourse(course);
return course;
}
#Transactional
public Course createCourse(Course course) {
course = coursesDAOImpl.createCourse(course);
return course;
}
#Transactional
public List<Course> getAllCourses() {
List<Course> listCourses = coursesDAOImpl.getAllCourses();
return listCourses;
}
#Transactional
public List<Course> getAllCoursesByCategory(String category) {
List<Course> listCoursesByCategory = coursesDAOImpl
.getAllCoursesByCategory(category);
return listCoursesByCategory;
}
#Transactional
public List<Course> getAllCoursesWhichNoProposal( ) {
List<Course> listCoursesNoProposal = coursesDAOImpl
.getAllCoursesWhichNoProposal( );
return listCoursesNoProposal;
}
#Transactional
public void deleteCourse(Course course) {
coursesDAOImpl.deleteCourse(course);
};
application-contex.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:security="http://www.springframework.org/schema/security"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<mvc:annotation-driven />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
p:driverClassName="org.h2.Driver"
p:url="jdbc:h2:tcp://localhost:9092/~/QWE;INIT=create schema if not exists QWE\;"
p:username="sa"
p:password="" />
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.default_schema">QWE</prop>
</props>
</property>
<property name="annotatedClasses">
<list>
<value>com.epam.edu.jtc.entity.User</value>
<value>com.epam.edu.jtc.entity.Category</value>
<value>com.epam.edu.jtc.entity.Course</value>
<value>com.epam.edu.jtc.entity.UserCourse</value>
<value>com.epam.edu.jtc.entity.ManagerCourse</value>
</list>
</property>
</bean>
<!-- FreeMarker Configuration -->
<bean id="freemarkerEmailConfig" class="freemarker.template.Configuration">
<property name="directoryForTemplateLoading" value="WEB-INF/pages/templates" />
<property name="objectWrapper">
<bean class="freemarker.template.DefaultObjectWrapper"/>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<context:component-scan base-package="com.epam.edu.jtc" />
</beans>

The problem as per my understanding lies with the way you are dealing with the session
getCurrentSession() : Obtains the current session.
openSession() : Creates a new session
Also using the below link is not recommended unless you have a strong reason
<prop key="hibernate.current_session_context_class">thread</prop>

Related

Making hibernate project with spring-rest

I am trying to make a simple spring rest project with hibernate.
I have made DAO and service layer. I have also configured beans in dispatcher-servlet and autowired in controller class with service and in service DAO session factory and transactions.
But I am continuously getting errors.
I have also uploaded a photo of error.
dispatcher-servlet.xml:
<?xml version="1.0" encoding="UTF-8"?>
beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- <mvc:annotation-driven /> -->
<!-- <resources mapping="/resources/**" location="/resources/" /> -->
<!--JDBC ko properties-->
<beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<beans:property name="driverClassName" value="com.mysql.jdbc.Driver" />
<beans:property name="url" value="jdbc:mysql://localhost:3306/student_database" />
<beans:property name="username" value="root" />
<beans:property name="password" value="" />
</beans:bean>
<!-- Hibernate ko SessionFactory Bean definition part -->
<beans:bean id="hibernate5AnnotatedSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<beans:property name="dataSource" ref="dataSource" />
<!-- <beans:property name="annotatedClasses">
<beans:list>
<beans:value>com.mycompany.SpringRestMaven.bean</beans:value>
</beans:list>
</beans:property> -->
<beans:property name="hibernateProperties">
<beans:props>
<beans:prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect
</beans:prop>
<beans:prop key="hibernate.show_sql">true</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<context:component-scan base- package="com.mycompany.SpringRestMaven.controller"/>
<tx:annotation-driven transaction-manager="transactionManager"/>
<beans:bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" />
</beans:bean>
controller class:
package com.mycompany.SpringRestMaven.controller;
/* I have not included imports*/
#RestController
public class StudentController {
#Autowired
ServiceLayer studentService;
#RequestMapping(value = "/insert", method = RequestMethod.POST, headers = "Accept=application/json")
public void insert(#RequestBody Student student) {
studentService.insert(student);
}
#RequestMapping(value = "/update", method = RequestMethod.PUT, headers = "Accept=application/json")
public void update(#RequestBody Student student) {
studentService.update(student);
}
#RequestMapping(value = "/delete", method = RequestMethod.DELETE, headers = "Accept=application/json")
public void delete(#PathVariable("id") int id) {
studentService.delete(id);
}
#RequestMapping(value = "/getAll", method = RequestMethod.GET, headers = "Accept=application/json")
public List<Student> getAll() {
List<Student> listOfStudent = studentService.getAll();
return listOfStudent;
}
#RequestMapping(value = "/searchById/{id}", method = RequestMethod.GET, headers = "Accept=application/json")
public Student searchById(#PathVariable int id) {
return studentService.searchById(id);
}
}
This is my service layer implementation:
package com.mycompany.SpringRestMaven.Service;
#Service("studentService")
public class ServiceImpl implements ServiceLayer {
#Autowired StudentDAO studentDao;
#Transactional
#Override
public void insert(Student s) {
studentDao.insert(s);
}
#Transactional
#Override
public void update(Student s) {
studentDao.update(s);
}
#Transactional
#Override
public void delete(int id) {
studentDao.delete(id);
}
#Transactional
#Override
public List<Student> getAll() {
return studentDao.getAll();
}
#Transactional
#Override
public Student searchById(int id) {
return studentDao.searchById(id);
}
}
This is my DAO implementation:
package com.mycompany.SpringRestMaven.DAO;
#Repository
public class StudentDAOImpl implements StudentDAO {
#Autowired
private SessionFactory sessionFactory;
private Session session;
private Transaction trans;
#Override
public void insert(Student s) {
session = sessionFactory.openSession();
trans = session.beginTransaction();
session.save(s);
trans.commit();
session.close();
}
#Override
public void update(Student s) {
session = sessionFactory.openSession();
trans = session.beginTransaction();
session.saveOrUpdate(s);
trans.commit();
session.close();
}
#Override
public void delete(int id) {
session = sessionFactory.openSession();
trans = session.beginTransaction();
Student sObject = (Student) session.get(Student.class, id);
session.delete(sObject);
trans.commit();
session.close();
}
#Override
public List<Student> getAll() {
return session.createQuery("SELECT s FROM Student s").list();
}
#Override
public Student searchById(int id) {
return (Student) session.get(Student.class, id);
}
}
I am getting this error:
Change your configuration
<context:component-scan base- package="com.mycompany.SpringRestMaven.controller"/>
To
<context:component-scan base- package="com.mycompany.SpringRestMaven"/>
Then Spring scans all your classes beneath the SpringRestMaven package and creates beans from the annotated classes.
In your current configuration Spring only scans and creates beans from beneath the .controller package. Your ServiceLayer isn't in this package and therefore Spring couldn't find the class, doesn't create a bean and could not autowire the field.

How to create emdedded H2 DB with spring(transactional) and hibernate in java desktop application?

I am trying to create a project with embedded h2 db, and using spring framework with hibernate. My database will be created in initialize time if not exist. My development platform is intellij.
Problem is that when i run the application
#Autowired
private IPersonService personService; // comes null?
here is my classes and config files.
myDB.sql:
CREATE TABLE IF NOT EXISTS personel(
id IDENTITY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
age VARCHAR(100));
hibernate.properties:
db.driverClassName=org.h2.Driver
db.url=jdbc:h2:~/h2SpringProject/database/SpringSample;mv_store=false;mvcc=false
db.username=admin
db.password=
here is my hibernate-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="com.springapp"/>
<context:annotation-config/>
<context:property-placeholder location="hibernate.properties"/>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.SingleConnectionDataSource">
<property name="driverClassName" value="${db.driverClassName}"></property>
<property name="url" value="${db.url}"></property>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
<property name="suppressClose" value="true"/>
</bean>
<jdbc:initialize-database data-source="dataSource" ignore-failures="DROPS">
<jdbc:script location="myDb.sql"/>
</jdbc:initialize-database>
<bean id="hibernateCfgProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="properties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="hibernate.use_sql_comments">true</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.region.factory_class">
org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
</prop>
</props>
</property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties" ref="hibernateCfgProperties"/>
<property name="packagesToScan" value="com.springapp.model"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
</beans>
Person class
#Entity
#Table(name = "personel")
public class Personel {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private long id;
#Column(name = "name")
private String name;
#Column(name = "age")
private String age;
.......
An IPersonDao interface and here is implemented class
#Component
public class PersonelDaoImpl implements IPersonelDao {
#Autowired
private SessionFactory sessionFactory;
public Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
#Override
public void savePersonel(Personel personel) {
getCurrentSession().saveOrUpdate(personel);
}
#Override
public void deletePersonel(long id) {
getCurrentSession().delete(id);
}
#Override
public List<Personel> getPersonels() {
return getCurrentSession().createQuery("from Personel").list();
}
}
There is an IPersonService interface and here is implemented class
#Service("PersonelService")
public class PersonelServiceImpl implements IPersonelService {
#Autowired
private IPersonelDao personelDao;
#Override
#Transactional
public void savePersonel(Personel personel) {
personelDao.savePersonel(personel);
}
#Override
#Transactional
public void deletePersonel(long id) {
personelDao.deletePersonel(id);
}
#Override
#Transactional
public List<Personel> getPersonels() {
return personelDao.getPersonels();
}
}
here is my main class
public class MainApp {
private static ApplicationContext applicationContext;
public static void main(String[] args) {
applicationContext = new ClassPathXmlApplicationContext("hibernate-config.xml");
ForExample a = new ForExample();
a.execute();
}
}
#Component
public class ForExample {
#Autowired
private IPersonelService personelService;
public void execute(){
Personel p = new Personel();
p.setName("thats Ok!");
p.setAge("614345");
personelService.savePersonel(p);
}
}
public class MainApp {
public static ApplicationContext applicationContext;
private static IPersonelService personelService;
public static void main(String[] args) {
applicationContext = new ClassPathXmlApplicationContext("hibernate-config.xml");
personelService = applicationContext.getBean(IPersonelService.class);
Personel p = new Personel();
p.setName("thatsOK!");
p.setAge("614345");
personelService.savePersonel(p);
}
}
Because of spring does not recognise new operator in run time..

HibernateException: saveOrUpdate is not valid without active transaction

Perhaps this question has been asked severally but am not able to find a solution to this. I am new to Spring and trying to working on a simple project to integrate Spring with Hibernate 4 using annotations. Whenever i click the user form to save to DB it throws this exception:
HTTP Status 500 - Request processing failed; nested exception is org.hibernate.HibernateException: saveOrUpdate is not valid without active transaction
What am I doing wrong? My code is below:
User.java
#Entity
#Table(name="SpringUsers")
public class User implements Serializable{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "userId")
private int id;
#Column(name = "username")
private String username;
#Column(name = "password")
private String password;
#Column(name = "email")
private String email;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
UsDAOImpl.java
#Repository
public class UserDAOImpl implements UserDAO{
#Autowired
private SessionFactory sessionFactory;
public UserDAOImpl(){}
public UserDAOImpl( SessionFactory sessionFactory){
this.sessionFactory= sessionFactory;
}
#Override
#Transactional
public List<User> list() {
List<User> listUser = sessionFactory.getCurrentSession()
.createCriteria(User.class).list();
return listUser;
}
#Override
#Transactional
public void saveOrUpdate(User user) {
sessionFactory.getCurrentSession().saveOrUpdate(user);
}
#Override
#Transactional
public void delete(int id) {
User userToDelete = new User();
userToDelete.setId(id);
sessionFactory.getCurrentSession().delete(userToDelete);
}
#Override
#Transactional
public User get(int i) {
String hql = "from User where id=" + i;
Query query = sessionFactory.getCurrentSession().createQuery(hql);
List<User> listUser = (List<User>) query.list();
if (listUser != null && !listUser.isEmpty()) {
return listUser.get(0);
}
return null;
}
}
user-servlet.xml
<context:component-scan base-package="com.myspringapp.controller"/>
<mvc:annotation-driven/>
<context:annotation-config />
<!-- <tx:annotation-driven />-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:#localhost:1521:XE"/>
<property name="username" value="system"/>
<property name="password" value="henry"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
</props>
</property>
<property name="annotatedClasses">
<list>
<value>com.myspringapp.model.User</value>
</list>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<constructor-arg ref="sessionFactory"/>
</bean>
<bean id="userDao" class="com.myspringapp.dao.UserDAOImpl">
<constructor-arg ref="sessionFactory"/>
</bean>
<!-- <tx:annotation-driven transaction-manager="transactionManager"/>-->
<bean id="viewResolver" 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>
Uncomment this line and it should work:
<tx:annotation-driven />

Java and Spring. Transactional annotation #Transactional

I want to Remove begin and commit transactions from DAO class , and I need to use Transactional annotation. How it should be done?
Now , exception is org.hibernate.HibernateException: createQuery is not valid without active transaction
CoursesDAO.java
public interface CoursesDAO {
public Course createCourse(Course course);
public Course findCourseById(Integer key);
public Course updateCourse(Course course);
public void deleteCourse(Course course);
public List<Course> getAllCourses();
public List<Course> getAllCoursesByCategory(String category);
public List<Course> getAllCoursesWhichNoProposal( );
}
CoursesDAOImpl.java
#Repository
public class CoursesDAOImpl implements CoursesDAO {
#Autowired
private SessionFactory sessionFactory;
public Course createCourse(Course course) {
Session session = sessionFactory.getCurrentSession();
//session.beginTransaction();
Integer id = (Integer) sessionFactory.getCurrentSession().save(course);
course.setId(id);
//session.getTransaction().commit();
return course;
};
public Course findCourseById(Integer id) {
Session session = sessionFactory.getCurrentSession();
//session.beginTransaction();
Course course = (Course) session.get(Course.class, id);
//session.getTransaction().commit();
return course;
}
public Course updateCourse(Course course) {
Session session = sessionFactory.getCurrentSession();
//session.beginTransaction();
session.merge(course);
//session.getTransaction().commit();
return course;
};
public void deleteCourse(Course course) {
Session session = sessionFactory.getCurrentSession();
//session.beginTransaction();
session.delete(course);
//session.getTransaction().commit();
};
public List<Course> getAllCourses() {
Session session = sessionFactory.getCurrentSession();
//session.beginTransaction();
List listCourses = session.createQuery("from Course").list();
//session.getTransaction().commit();
return listCourses;
}
public List<Course> getAllCoursesByCategory(String category) {
Session session = sessionFactory.getCurrentSession();
//session.beginTransaction();
List listCoursesByCategory = session.createQuery("from Course c where c.category='"+category+"'").list();
//session.getTransaction().commit();
return listCoursesByCategory;
}
public List<Course> getAllCoursesWhichNoProposal( ) {
Session session = sessionFactory.getCurrentSession();
//session.beginTransaction();
List listCoursesNoProposal = session.createQuery("from Course c where c.state not like 'Proposal' and c.state not like 'Rejected'").list();
//session.getTransaction().commit();
return listCoursesNoProposal;
}
}
CourseService.java
public interface CourseService {
public Course findCourseById(Integer id);
public Course updateCourse(Course course);
public Course createCourse(Course course);
public void deleteCourse(Course course);
public List<Course> getAllCourses();
public List<Course> getAllCoursesByCategory(String category);
public List<Course> getAllCoursesWhichNoProposal( );
}
CourseServiceImpl.java
#Service
public class CourseServiceImpl implements CourseService {
#Autowired
private CoursesDAO coursesDAOImpl;
#Transactional
public Course findCourseById(Integer id) {
Course course = coursesDAOImpl.findCourseById(id);
return course;
}
#Transactional
public Course updateCourse(Course course) {
// Course.openCurrentSessionwithTransaction();
course = coursesDAOImpl.updateCourse(course);
// Course.closeCurrentSessionwithTransaction();
return course;
}
#Transactional
public Course createCourse(Course course) {
//Course.openCurrentSessionwithTransaction();
course = coursesDAOImpl.createCourse(course);
//Course.closeCurrentSessionwithTransaction();
return course;
}
#Transactional
public List<Course> getAllCourses() {
// Course.openCurrentSessionwithTransaction();
List<Course> listCourses = coursesDAOImpl.getAllCourses();
// Course.closeCurrentSessionwithTransaction();
return listCourses;
}
#Transactional
public List<Course> getAllCoursesByCategory(String category) {
// Course.openCurrentSessionwithTransaction();
List<Course> listCoursesByCategory = coursesDAOImpl
.getAllCoursesByCategory(category);
// Course.closeCurrentSessionwithTransaction();
return listCoursesByCategory;
}
#Transactional
public List<Course> getAllCoursesWhichNoProposal( ) {
// Course.openCurrentSessionwithTransaction();
List<Course> listCoursesNoProposal = coursesDAOImpl
.getAllCoursesWhichNoProposal( );
// Course.closeCurrentSessionwithTransaction();
return listCoursesNoProposal;
}
#Transactional
public void deleteCourse(Course course) {
coursesDAOImpl.deleteCourse(course);
};
application-contex.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:security="http://www.springframework.org/schema/security"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<mvc:annotation-driven />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
p:driverClassName="org.h2.Driver"
p:url="jdbc:h2:tcp://localhost:9092/~/QWE;INIT=create schema if not exists QWE\;"
p:username="sa"
p:password="" />
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="connection.pool_size">1</prop>
<prop key="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.default_schema">QWE</prop>
</props>
</property>
<property name="annotatedClasses">
<list>
<value>com.epam.edu.jtc.entity.User</value>
<value>com.epam.edu.jtc.entity.Category</value>
<value>com.epam.edu.jtc.entity.Course</value>
<value>com.epam.edu.jtc.entity.UserCourse</value>
<value>com.epam.edu.jtc.entity.ManagerCourse</value>
</list>
</property>
</bean>
<!-- FreeMarker Configuration -->
<bean id="freemarkerEmailConfig" class="freemarker.template.Configuration">
<property name="directoryForTemplateLoading" value="WEB-INF/pages/templates" />
<property name="objectWrapper">
<bean class="freemarker.template.DefaultObjectWrapper"/>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<context:component-scan base-package="com.epam.edu.jtc" />
</beans>
I think here you have a problem of concept.
The proper architecture would be to have a transactional service that invoke a repository. Something like this.
#Service
public class CoursesServiceImpl implements CoursesService {
#Autowired
private CoursesDAO coursesDAO;
#Override
#Transactional
public void insertCourses(Course courses) {
coursesDAO.createCourse(courses);
}
}
Then your repository
#Repository
public class CoursesDAOImpl implements CoursesDAO {
#Autowired
private SessionFactory sessionFactory;
public Course createCourse(Course course) {
Session session = sessionFactory.getCurrentSession();
//session.beginTransaction();
Integer id = (Integer) session.save(course);
course.setId(id);
//session.getTransaction().commit();
return course;
};
After setting a correct transaction manager, just tried to move the #Transactional annotation to the method on the implemented class
#Repository
public class CoursesDAOImpl implements CoursesDAO {
#Autowired
private SessionFactory sessionFactory;
#Transactional
public Course createCourse(Course course) {
There are 2 flaws in your configuration.
First when using #Transactional you also have to make this clear to your configuration by including a <tx:annotation-driven /> tag in your application context file. If not your #Transactional is going to do nothing.
Simple add <tx:annotation-driven transaction-manager="txManager/>, as you named it different then transactionManager (the default name). Of course you would also have to add the correct xsd to the header to make the tx namespace available.
xmlns:tx="http://www.springframework.org/schema/tx"
and add this to your schemaLocation attribute.
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
Second you have configured the hibernate.current_session_context_class property in your hibernate configuration. This breaks proper integration with spring which sets it to a custom Spring class, however your setting overrides this. Remove this property.
Another thing to consider is that the actual transactional boundary should be your service layer and not your data access layer. Your service method is an all or nothing operation, if you have 3 database calls they should all participate in the same transaction. With your setup you will get 3 individual transactions, which can leave your database in an undesired state when doing multiple updates for instance. I suggest to move the #Transactional to your service layer instead of the data access layer.

GenericDAO method does (such as save)not work with Hibernate and Spring

I use Spring 3 and Hibernate 4. I try to save a Users entity in database but it's not working. When i call the method finUsersByUsername(String username) it's work well. But when i use the save method defined in GenericDao it's does not work. I don't understand it. If someone could help me ?
Domain class users:
#Entity
#Table(name="USERS")
public class Users{
#Id
#Column(name="USERNAME", length=50,nullable=false )
private String username;
#Column(name="PASSWORD",length=50, nullable=false)
private String password;
#Column(name="ENABLED", nullable=false)
private Boolean enabled;
#Column(name="LASTNAME",length=50)
private String lastName;
#Column(name="FIRTSNAME",length=50)
private String firstName;
#Column(name="DATEOFBIRTH")
private Date dateOfBirth;
#Column(name="EMAIL",length=50, nullable=false)
private String email;
#Column(name="PHONENUMBER",length=50)
private String phoneNumber;
... getters and setters
}
Generic DAO interface :
public interface GenericDao<T, PK extends Serializable> {
PK create(T newInstance);
T read(PK id);
List<T> readAll();
List<T> readByCriteria(Criterion criterion);
void update(T transientObject);
void delete(T persistentObject);
}
DAO implementation:
#Repository
public class GenericDaoImpl<T, PK extends Serializable> implements GenericDao<T, PK> {
#Autowired
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
private Class<T> type;
public GenericDaoImpl() {
super();
}
public GenericDaoImpl(Class<T> type) {
this.type = type;
}
#Transactional
#SuppressWarnings("unchecked")
public PK create(T object) {
return (PK) getSession().save(object);
}
#SuppressWarnings("unchecked")
public T read(PK id) {
return (T) getSession().get(type, id);
}
public List<T> readAll() {
return readByCriteria();
}
#SuppressWarnings("unchecked")
public List<T> readByCriteria(Criterion... criterion) {
Criteria crit = getSession().createCriteria(type);
for (Criterion c : criterion) {
crit.add(c);
}
return crit.list();
}
#Transactional
public void update(T object) {
getSession().update(object);
}
#Transactional
public void delete(T object) {
getSession().delete(object);
}
public Session getSession() {
return sessionFactory.openSession();
}
}
Users DAO Interface:
public interface UserDao extends GenericDao<Users, Long> {
Users finUsersByUsername(String username);
}
Users Dao implementations
#Repository
#Transactional
public class UserDaoImpl extends GenericDaoImpl<Users, Long> implements UserDao{
#Autowired
private SessionFactory sessionFactory;
public UserDaoImpl(){}
#SuppressWarnings("unused")
private Class<Users> type;
public UserDaoImpl(Class<Users> type) {
super(type);
}
#Override
public Users finUsersByUsername(String username) {
return (Users) sessionFactory.getCurrentSession().load(Users.class,username);
}
}
Spring configuration file:
?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:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<!-- Configuration des annotations -->
<context:annotation-config />
<!-- Activation du scan des annotations Spring MVC -->
<context:component-scan base-package="com.nexthome.app"/>
<bean id="userDao" class="com.nexthome.app.dao.hibernate.UserDaoImpl">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver"/>
<property name="url" value="jdbc:postgresql://localhost:5432/home"/>
<property name="username" value="postgres"/>
<property name="password" value="database"/>
</bean>
<tx:annotation-driven />
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.nexthome.app.dao.entities.Users</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<!-- Resolveur de vues -->
<bean id="jspViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsps/"
p:suffix=".jsp" />
</beans>
Thanks for your help
This method is probably the root cause:
public Session getSession() {
return sessionFactory.openSession();
}
Spring instantiates a session at start of the Transaction. When opening your own session, it won't be managed by Springs Transaction abstraction. Use the existing session instead of creating a new one. Probably changing method to this does the trick:
public Session getSession() {
return sessionFactory.getCurrentSession();
}
See also: http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/orm.html#orm-hibernate

Categories

Resources