Failed to perform insert / update / delete

I want to use transaction manager in my application using Hibernate and JPA. I started by setting applicationContext.xml (I also want to use c3p0, but I will configure it later):

<?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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="dao,business" />
    <!-- Configuration du transaction manager -->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" value="entity" />

        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>
                <prop key="hibernate.hbm2ddl.auto">validate</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
                <prop key="current_session_context_class">thread</prop>
                <!-- <prop key="hibernate.cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</prop> -->
                <!-- used for debug -->
                <prop key="hibernate.show_sql">true</prop>
                <!-- EhCache -->
                <!-- <prop key="hibernate.cache.provider_configuration_file_resource_path" 
                    value="classpath:ehcache.xml</prop> -->
                <!-- <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
                <prop key="hibernate.cache.provider_class">org.hibernate.cache.SingletonEhCacheProvider</prop>
                <prop key="hibernate.cache.use_second_level_cache">true</prop>
                <prop key="hibernate.cache.use_query_cache">true</prop>
                <prop key="hibernate.generate_statistics">true</prop> -->
                <!-- configuration pool via c3p0, see https://community.jboss.org/wiki/HowToConfigureTheC3P0ConnectionPool -->
                <!-- <prop key="hibernate.connection.provider_class">org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider</prop> 
                    <prop key="hibernate.c3p0.acquire_increment">1</prop> <prop key="hibernate.c3p0.max_size">5</prop> 
                    <prop key="hibernate.c3p0.max_statements">100</prop> <prop key="hibernate.c3p0.min_size">1</prop> 
                    <prop key="hibernate.c3p0.timeout">100</prop> <prop key="hibernate.checkoutTimeout">1000</prop> 
                    <prop key="hibernate.c3p0.idleConnectionTestPeriod">30</prop> <prop key="hibernate.c3p0.preferredTestQuery">SELECT 
                    1</prop> -->
                <!-- <prop key="c3p0.testConnectionOnCheckout">true</prop> -->
                <!-- <prop name="eclipselink.jdbc.bind-parameters">false</prop> -->
            </props>
        </property>
    </bean>
    <!-- Configuration de la BDD -->
    <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/my_db?autoReconnect=true" />
        <property name="username" value="user" />
        <property name="password" value="password" />
    </bean>
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>
    <tx:annotation-driven />
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
</beans>

My DAO looks like this:

package dao.impl;
import dao.CategoryDao;
import entity.Category;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Repository
@Transactional
public class CategoryDaoJpa implements CategoryDao {
    @PersistenceContext
    private EntityManager em;
    @Override
    public int save(Category entity) {
        em.persist(entity);
        return entity.getId();
    }
    @Override
    public void remove(Category entity) {
        em.remove(entity);
    }
    @Override
    public void remove(int id) {
        em.createQuery("DELETE FROM Category WHERE id=:id").setParameter("id", id).executeUpdate();
    }
    @Override
    public void update(Category entity) {
        em.merge(entity);
    }
    @Override
    public Category load(int id) {
        return em.find(Category.class, id);
    }
    @Override
    public List<Category> loadAll() {
        return em.createQuery("FROM Category ORDER BY type,sortIndex", Category.class).getResultList();
    }
    @Override
    public void update(int id, String value) {
        em.createNativeQuery("UPDATE category SET titre=:t WHERE id=:id")
                .setParameter("t", value)
                .setParameter("id", id)
                .executeUpdate();
    }
}

I call it in my business object:

package business;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import dao.CategoryDao;
import entity.Category;

@Service
@Transactional
public class CategoryService {
    @Autowired
    private CategoryDao dao;

    public void update(int id, String title) {
        Category c=dao.load(id);
        c.setTitre(title);
        dao.update(c);
    }
}

When I call the update (category) function, nothing happens :( If I call update (int, String), I got this error:

Grave: Servlet.service() for servlet [mvc-dispatcher] in context with path [/my-app] threw exception [Request processing failed; nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query] with root cause
javax.persistence.TransactionRequiredException: Executing an update/delete query
    at org.hibernate.jpa.spi.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:71)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:333)
    at com.sun.proxy.$Proxy156.executeUpdate(Unknown Source)
    at dao.impl.CategoryDaoJpa.update(CategoryDaoJpa.java:53)
    at business.CategoryService.update(CategoryService.java:53)
    at controller.CategoryController.pageListe(CategoryController.java:31)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:175)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:446)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:434)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:870)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:108)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at filter.AuthFilter.doFilter(AuthFilter.java:36)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)
+4
source share
4 answers

: dao.impl.CategoryDaoJpa CategoryService CategoryService, CategoryController. , spring @Transactional CategoryDaoJpa CategoryService.

-, , dao , . , dao .

, spring @Transactional. spring : <tx:annotation-driven/> only looks for @Transactional on beans in the same application context it is defined in.. , applicationContext.xml beans, .

+1

:

<prop key="hibernate.connection.driver_class">com.mysql.jdbc.Driver</prop>

, Hibernate :

<property name="dataSource" ref="dataSource" />

TransactionInterceptor , .

:

    at dao.impl.CategoryDaoJpa.update(CategoryDaoJpa.java:53)
    at business.CategoryService.update(CategoryService.java:53)
    at controller.CategoryController.pageListe(CategoryController.java:31)

-, Spring Bean. TransactionInterceptor .

-? , , bean - .

+3

!

applicationContext.xml mvc-dispatcher-servlet.xml, -. , ,

<context:component-scan base-package="dao" />
<context:component-scan base-package="business" />

.

, beans ( , applicationContext.xml).

, , service dao beans -, , , , .

<context:component-scan base-package="dao" />
<context:component-scan base-package="business" />

from mvc-dispatcher-servlet.xml, , , beans (, , - ).

+3

, @Transactionnal

package filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Component //was missing
@Transactional(propagation=Propagation.REQUIRED) //was missing
public class AuthFilter implements Filter {
    @Override
    //no use so not implemented
    public void destroy() {
        //Ignore
    }
    @Override
    //no use so not implemented
    public void init(FilterConfig config) throws ServletException {
        //Ignore
    }
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        if(((HttpServletRequest)req).getSession().getAttribute("userAccount")==null) {
            HttpServletResponse response=(HttpServletResponse)resp;
            response.sendRedirect(((HttpServletRequest)req).getContextPath()+"/index.html");
            return;
        }
        chain.doFilter(req, resp);
    }


}
0

Source: https://habr.com/ru/post/1546116/


All Articles