@Transaction не работает в весенней загрузке 2.x, и я получаю «Выполнение запроса на обновление / удаление» при обновлении таблицы - PullRequest
0 голосов
/ 10 июля 2019

Когда я использую session.beginTransaction(), таблица обновляется, но не может откатиться, когда она застряла.Удаляя session.beginTransaction(), я обнаружил, что таблица не обновляется, и я получаю исключение «Выполнение запроса на обновление / удаление» на консоли.Ниже приведена полная дорожка стека.

javax.persistence.TransactionRequiredException: Executing an update/delete query
    at org.hibernate.internal.AbstractSharedSessionContract.checkTransactionNeededForUpdateOperation(AbstractSharedSessionContract.java:398)
    at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1580)
    at com.skilrock.jackpot.dao.impl.JackpotDaoImpl.updateCurrentValue(JackpotDaoImpl.java:159)
    at com.skilrock.jackpot.dao.impl.JackpotDaoImpl.getSetDetail(JackpotDaoImpl.java:91)
    at com.skilrock.jackpot.dao.impl.JackpotDaoImpl.getJackpot(JackpotDaoImpl.java:47)
    at com.skilrock.jackpot.dao.impl.JackpotDaoImpl$$FastClassBySpringCGLIB$$bdef8e95.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
    at com.skilrock.jackpot.dao.impl.JackpotDaoImpl$$EnhancerBySpringCGLIB$$1280fb7b.getJackpot(<generated>)
    at com.skilrock.jackpot.service.impl.JackpotServiceImpl.getJackpot(JackpotServiceImpl.java:21)
    at com.skilrock.jackpot.service.impl.JackpotServiceImpl$$FastClassBySpringCGLIB$$6bee6d5b.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:295)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
    at com.skilrock.jackpot.service.impl.JackpotServiceImpl$$EnhancerBySpringCGLIB$$47a38826.getJackpot(<generated>)
    at com.skilrock.jackpot.controller.JackpotController.contribution(JackpotController.java:20)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:109)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:853)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)

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

    import com.company.jackpot.beans.RequestBean;
    import com.company.jackpot.beans.ResponseBean;
    import com.company.jackpot.dao.JackpotDao;
    import com.company.jackpot.service.JackpotService;
    @Service
    public class JackpotServiceImpl implements JackpotService {

        @Autowired
        private JackpotDao jackpotDao;
        @Override
        @Transactional
        public ResponseBean getJackpot(RequestBean requestBean) {

            ResponseBean responseBean = jackpotDao.getJackpot(requestBean);
            return responseBean;
        }

    }

package com.company.jackpot.util;

import java.util.Properties;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
public class HibernateUtilConfig {
    /*@Value("${db.driver}")
    private String DRIVER;*/

    @Value("${db.password}")
    private String PASSWORD;

    @Value("${db.url}")
    private String URL;

    @Value("${db.username}")
    private String USERNAME;

    @Value("${hibernate.dialect}")
    private String DIALECT;

    @Value("${hibernate.show_sql}")
    private String SHOW_SQL;

    @Value("${hibernate.hbm2ddl.auto}")
    private String HBM2DDL_AUTO;

    @Value("${entitymanager.packagesToScan}")
    private String PACKAGES_TO_SCAN;

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
       // dataSource.setDriverClassName(DRIVER);
        dataSource.setUrl(URL);
        dataSource.setUsername(USERNAME);
        dataSource.setPassword(PASSWORD);
        return dataSource;
    }

    @Bean
    public LocalSessionFactoryBean sessionFactory() {
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        sessionFactory.setPackagesToScan(PACKAGES_TO_SCAN);
        Properties hibernateProperties = new Properties();
        hibernateProperties.put("hibernate.dialect", DIALECT);
        hibernateProperties.put("hibernate.show_sql", SHOW_SQL);
        hibernateProperties.put("hibernate.hbm2ddl.auto", HBM2DDL_AUTO);
        sessionFactory.setHibernateProperties(hibernateProperties);

        return sessionFactory;
    }

    @Bean
    public HibernateTransactionManager transactionManager() {
        HibernateTransactionManager transactionManager = new HibernateTransactionManager();
        transactionManager.setSessionFactory(sessionFactory().getObject());
        return transactionManager;
    }
}




package com.company.jackpot.dao.impl;

import java.util.Date;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.company.jackpot.beans.RequestBean;
import com.company.jackpot.beans.ResponseBean;
import com.company.jackpot.dao.JackpotDao;
import com.company.jackpot.model.CurrentValue;
import com.company.jackpot.model.TransactionMaster;
import com.company.jackpot.model.TransactionWin;
import com.company.jackpot.model.enummodel.Level;
import com.company.jackpot.util.CommonOperation;

@Repository
//@Transactional(rollbackOn = {ArrayIndexOutOfBoundsException.class})
public class JackpotDaoImpl implements JackpotDao {

    @Autowired
    private SessionFactory sessionFactory;
    ResponseBean responseBean = new ResponseBean();

    @Override
    public ResponseBean getJackpot(RequestBean requestBean) {

        Session session = null;
        //Transaction tx = null;
        try {
            //session = sessionFactory.openSession();
            //tx = session.beginTransaction();

            String hql = "select setId from SetReference where serviceCode = '" + requestBean.getServiceCode()
                    + "' and gameCode = " + requestBean.getGameCode() + "";
            Query query = session.createQuery(hql);
            List<Integer> queryResultList = query.list();
            if (!queryResultList.isEmpty()) {

                int setId = queryResultList.get(0);
                getSetDetail(setId, requestBean, session);
                //int i = 2;

                //session.getTransaction().commit();
                //tx.commit();

                return responseBean;
            } else {
                responseBean.setErrorCode(401);
                responseBean.setErrorMsg("You are not eligible for jackpot");
//              session.getTransaction().commit();
                return responseBean;
            }
        } catch (RuntimeException e) {
            e.printStackTrace();
        }
        return null;
    }

    public void getSetDetail(int setId, RequestBean requestBean, Session session) {

        try {
            String setDetailQuery = "select setId, level, type, contributionPercentage, startRange, endRange from SetDetail where setId = "
                    + setId + "";
            Query query = session.createQuery(setDetailQuery);
            List<Object[]> setDetailQueryList = query.list();
            if (!setDetailQueryList.isEmpty()) {
                for (Object[] setDetail : setDetailQueryList) {
                    // SetDetail setDetail = (SetDetail)set;
                    Double start = (double) setDetail[4];
                    Double end = (double) setDetail[5];
                    int randomNumber = CommonOperation.getRandomNumber(start.intValue(), end.intValue());
                    Double contributionPercentage = (double) setDetail[3];
                    Double contributionValue = CommonOperation.getContributionValue(requestBean.getBetAmount(),
                            contributionPercentage.intValue());
                    if (setDetail[1].toString().equalsIgnoreCase("MACHINE")) {
                        /*
                         * from here take random and contribution and then update current_value table
                         * txn_master, txn_win
                         */
                        System.out.println(setDetail[1]);
                        updateCurrentValue((int) setDetail[0], setDetail[1].toString(), setDetail[2].toString(),
                                randomNumber, contributionValue, requestBean.getMachineId(), requestBean, session);

                    }

                }
            }

        } catch (RuntimeException e) {
            e.printStackTrace();
        }
    }

    public void updateCurrentValue(int setId, String level, String type, int randomNumber, double contributionValue,
            String levelId, RequestBean requestBean, Session session) {
            long transactionId;

        try {
            String hql = "from CurrentValue where setId = " + setId + " and level = '" + level + "' and levelId = '"
                    + levelId + "'";
            Query query = session.createQuery(hql);
            List<CurrentValue> currentValueList = query.list();
            for (CurrentValue currentValue : currentValueList) {
                System.out.println(currentValue);

                if (currentValue.getEligiblePrice() == null) {
                    responseBean.setJackpotType(null);
                    responseBean.setWinningAmount(null);
                    String updateHQl = "update CurrentValue set eligiblePrice = :price, totalContributionValue = :value where setId = "
                            + setId + " and level = '" + level + "' and levelId = '" + levelId + "'";

                    Query updateQuery = session.createQuery(updateHQl);
                    updateQuery.setParameter("price", (double) randomNumber);
                    updateQuery.setParameter("value", (currentValue.getTotalContributionValue() + contributionValue));
                    int rowsAffected = updateQuery.executeUpdate();
                    if (rowsAffected > 0) {
                        System.out.println(rowsAffected + " Affected");
                        // now update txn_master, txn_win
                        transactionId = updateTransactionMaster(setId, requestBean, session);
                        System.out.println(5/0);



                }   }
            }
        } catch (RuntimeException e) {
            e.printStackTrace();
        }

    }

}

Я ожидаю обновления таблиц и, если произойдет какое-либо исключение, все записи должны быть откатены с помощью @Transaction.

Ответы [ 3 ]

1 голос
/ 10 июля 2019

Вы используете @Transactional, который управляется контейнером, но также запускает сеанс вручную в @Repository. Это все портит.

Не открывайте сеанс явно в этом случае. По умолчанию все RuntimeExceptions приведет к откату. Если вы хотите откатить проверенное исключение, вам нужно настроить его на уровне аннотации @Transactional.

0 голосов
/ 11 июля 2019

Я получил решение проблемы в движке базы данных MySQL. Мой движок был MYIsam, который не поддерживает транзакции отката. Я изменил свой движок БД на InnoDB, и теперь он работает нормально.

изменить таблицу table_name ENGINE = INNODB;

0 голосов
/ 10 июля 2019

Вы используете Spring Boot (согласно добавленным тэгам), однако ваш код и конфигурация показывают, что вы очень стараетесь обойти фреймворк.

Отбросьте свой HibernateUtilConfig и вместо этого добавьте следующее: application.properties.

spring.datasource.url= // value of current db.url
spring.datasource.username= // value of current db.username
spring.datasource.password= // value of current db.password

spring.jpa.database-platform= // value of hibernate.dialect
spring.jpa.show-sql= // value of hibernate.show_sql
spring.jpa.hibernate.ddl-auto= // value of hibernate.hbm2ddl.auto

Это замена вашего HibernateUtilConfig и предполагает, что ваш @SpringBootApplication аннотированный классв пакете верхнего уровня.Если нет, добавьте @EntityScan (хотя рекомендуется поместить его в пакет верхнего уровня).

Тогда вместо SessionFactory и Session используйте JPA с EntityManager в вашем хранилище.

@Repository
public class JackpotDaoImpl implements JackpotDao {

    @PersistenceContext
    private EntityManager em;

Теперь вы можете использовать EntityManager вместо Session.

Ваш код также имеет недостатки

  1. Вы используете String Concat для создания запросов, никогда Используйте Concat для создания запросов, используйте именованный параметр при использовании Hibernate / JPA
  2. Ваш дао не является потокобезопасным, поскольку вы повторно используете уровень класса ResponseBean, удалите его из класса и создайте его, когда это необходимо, в самом методе.
  3. Вы используете Hibernate / JPA, но используете простые запросы для запуска обновлений, что в основном превосходит цель использования ORM.Обновите сущности и дайте Hibernate беспокоиться об остальном.
  4. Вы выполняете попытку / перехват в вашем методе репозитория, это нарушит правильное управление tx.
...