Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to perform insert/update/delete

I want to use a transaction manager in my application using Hibernate and JPA. I started by configuring applicationContext.xml (I also want to use c3p0 but i'll 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 look 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 is happening :( 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)
like image 421
Athanor Avatar asked Mar 20 '23 05:03

Athanor


1 Answers

You should remove this:

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

As you already provide a Datasource, of which Hibernate is already aware of:

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

I don't see the TransactionInterceptor in your stacktrace which indicates you have no transaction available.

Also there is no proxying involved:

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

The Service is called by the controller directly without using any proxy, like it's the case with any Spring Bean. This is why you don't see the TransactionInterceptor in your stacktrace.

How are you injecting the service in the web Controller? You should make sure you use dependency injection and not instantiate the bean manually or something.

like image 188
Vlad Mihalcea Avatar answered Apr 01 '23 20:04

Vlad Mihalcea