Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call

No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call

when I do a test with JUnit, persist method works and I see that my object is inserted, but when I call the method via my Controller doesn't work

here is my Project :

applicationContext.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:tx="http://www.springframework.org/schema/tx"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:task="http://www.springframework.org/schema/task"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.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-4.2.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">



<!--    <bean id="notification" class="com.app.sqli.notification.NotificationTask" /> -->

<!--    <task:scheduled-tasks> -->
<!--        <task:scheduled ref="notification" method="notifier" cron="*/2 * * * * *"/> -->
<!--    </task:scheduled-tasks> -->

<context:component-scan base-package="com.app.sqli" />  

    <mvc:annotation-driven />
    <bean id="entityManagerFactoryBean" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
      <property name="dataSource" ref="dataSource" />
       <property name="packagesToScan" value="com.app.sqli.entities" />
      <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>


   <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/sqli" />
      <property name="username" value="root" />
      <property name="password" value="" />
   </bean>


    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
      <property name="entityManagerFactory" ref="entityManagerFactoryBean" />
   </bean>


   <tx:annotation-driven />


</beans>

my Model Class:

package com.app.sqli.models;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Collaborateur {

    @Id
    private int id;
    private String nom;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getNom() {
        return nom;
    }

    public void setNom(String nom) {
        this.nom = nom;
    }

}

my DAO Class

package com.app.sqli.dao;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.stereotype.Repository;

import com.app.sqli.models.Collaborateur;

@Repository
public class CollaborateurDao implements IcollaborateurDao{

    @PersistenceContext
    private EntityManager em;

    @Override
    public void addCollaborateur(Collaborateur c) {
    em.persist(c);

    }

}

My Service Class

package com.app.sqli.services;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.app.sqli.dao.IcollaborateurDao;
import com.app.sqli.models.Collaborateur;

@Service
@Transactional
public class CollaborateurService implements IcollaborateurService{

    @Autowired
    private IcollaborateurDao cdao;

    @Override
    public void addCollaborateur(Collaborateur c) {
        cdao.addCollaborateur(c);

    }


}

And My Controller

package com.app.sqli.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.app.sqli.models.Collaborateur;
import com.app.sqli.services.IcollaborateurService;

@org.springframework.stereotype.Controller
public class Controller {
    @Autowired
    private IcollaborateurService cserv;

    @RequestMapping(value = "/index")
    public String index(Model m) {
        System.out.println("insertion ...");
        Collaborateur c = new Collaborateur();
        c.setId(11);
        c.setNom("nom");
        cserv.addCollaborateur(c);
        return "index";
    }

}
like image 988
Mohamed Nabli Avatar asked Nov 18 '15 13:11

Mohamed Nabli


People also ask

What does @transactional annotation do?

The @Transactional annotation is the metadata that specifies the semantics of the transactions on a method. We have two ways to rollback a transaction: declarative and programmatic. In the declarative approach, we annotate the methods with the @Transactional annotation.

What is persistence context in JPA?

The persistence context is the first-level cache where all the entities are fetched from the database or saved to the database. It sits between our application and persistent storage. Persistence context keeps track of any changes made into a managed entity.

How does transaction work in spring?

So when you annotate a method with @Transactional , Spring dynamically creates a proxy that implements the same interface(s) as the class you're annotating. And when clients make calls into your object, the calls are intercepted and the behaviors injected via the proxy mechanism.

What is EntityManager flush?

The EntityManager. flush() operation can be used the write all changes to the database before the transaction is committed. By default JPA does not normally write changes to the database until the transaction is committed. This is normally desirable as it avoids database access, resources and locks until required.


2 Answers

thank you @mechkov for your time and help, My problem is resolved by changing my configuration file, so I have used a Configuration Class with annotations and its works so fine, I still Don't know where the problem was

    @Configuration
    @ComponentScan(basePackages = "your package")
    @EnableTransactionManagement
    public class DatabaseConfig {

        protected static final String PROPERTY_NAME_DATABASE_DRIVER = "com.mysql.jdbc.Driver";
        protected static final String PROPERTY_NAME_DATABASE_PASSWORD = "password";
        protected static final String PROPERTY_NAME_DATABASE_URL = "jdbc:mysql://localhost:3306/databasename";
        protected static final String PROPERTY_NAME_DATABASE_USERNAME = "login";

        private static final String PROPERTY_PACKAGES_TO_SCAN = "where your models are";
        @Bean
        public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(DataSource dataSource, JpaVendorAdapter jpaVendorAdapter){
            LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
            entityManagerFactoryBean.setDataSource(dataSource);
            entityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter);
            entityManagerFactoryBean.setPackagesToScan(PROPERTY_PACKAGES_TO_SCAN);
            return entityManagerFactoryBean;
        }

        @Bean
        public BasicDataSource dataSource(){
            BasicDataSource ds = new BasicDataSource();
            ds.setDriverClassName(PROPERTY_NAME_DATABASE_DRIVER);
            ds.setUrl(PROPERTY_NAME_DATABASE_URL);
            ds.setUsername(PROPERTY_NAME_DATABASE_USERNAME);
            ds.setPassword(PROPERTY_NAME_DATABASE_PASSWORD);
            ds.setInitialSize(5);
            return ds;
        }

        @Bean
        public JpaVendorAdapter jpaVendorAdapter(){
            HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
            adapter.setDatabase(Database.MYSQL);
            adapter.setShowSql(true);
            adapter.setGenerateDdl(true);

//I'm using MySQL5InnoDBDialect to make my tables support foreign keys
adapter.setDatabasePlatform("org.hibernate.dialect.MySQL5InnoDBDialect");
            return adapter;
        }

        @Bean
        public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
            return new JpaTransactionManager(entityManagerFactory);
        }


    }
like image 159
Mohamed Nabli Avatar answered Jun 06 '23 18:06

Mohamed Nabli


I do not know if anyone who is reading this (today) has the same case as mine, but I had the same problem. Luckly, I could fix it by simply putting the following in my spring-conf.xml:

<beans xmlns="http://www.springframework.org/schema/beans"
...
xmlns:tx="http://www.springframework.org/schema/tx"
...
xsi:schemaLocation="
...
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">

<bean id="tManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf" />
</bean>

<!-- This does the trick! -->
<tx:annotation-driven transaction-manager="tManager" />

Note: I'm using declarative transactions through annotations. So, if you do, annotating your method with @Transactional can also solve your problem.

REFERENCE:

  1. http://blog.jhades.org/how-does-spring-transactional-really-work/
  2. http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/transaction.html
like image 39
Loa Avatar answered Jun 06 '23 19:06

Loa