복붙노트

[SPRING] Spring @ 트랜잭션이 작동하지 않음

SPRING

Spring @ 트랜잭션이 작동하지 않음

이전에이 문제에 대한 게시물이 있었지만 해결되었습니다. 그러나 자동 유선 콩과 덜 XML 구성으로 프로젝트를 재구성 한 이래로이 문제를 다시 검토하고 있습니다. 이전 프로젝트에서 구현 한 방식대로 수행했지만 작동하지 않습니다. 왜 누군가가 나를 도와 줄 수 있습니까?

의도적으로 예외를 던지기 위해 삽입 사용자 세부 정보 메서드에 존재하지 않는 테이블 이름을 사용하고 있습니다. 그러나 사용자 삽입 및 사용자 역할 삽입 명령문은 롤백되지 않습니다. 도와주세요.

등록에 대한 나의 현재 디자인은 이렇습니다.

servlet.xml의 일부 :

<context:component-scan base-package="com.doyleisgod.golfer.controllers"/>
<context:component-scan base-package="com.doyleisgod.golfer.dao"/>
<context:component-scan base-package="com.doyleisgod.golfer.services"/>
<context:component-scan base-package="com.doyleisgod.golfer.validators"/>

응용 프로그램 컨텍스트의 일부 :

<context:annotation-config />
<tx:annotation-driven />    

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

등록 컨트롤러 :

package com.doyleisgod.golfer.controllers;

import javax.validation.Valid;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.doyleisgod.golfer.formdata.RegistrationForm;
import com.doyleisgod.golfer.services.IRegistrationService;
import com.doyleisgod.golfer.validators.RegistrationFormValidator;

/**
 * Description: Registration controller provides and processes the registration form.
 * @author Chris Doyle
*/
@Controller
@RequestMapping("/registration.htm")
public class RegistrationController {
    protected final Log logger = LogFactory.getLog(getClass());
    @Autowired private IRegistrationService iRegistrationService;
    @Autowired private RegistrationFormValidator registrationFormValidator;

    // sets a customer validator for the registration form
    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.setValidator(registrationFormValidator);
    }

    // Description: Method called by a get request to the registration controller. Returns the
    @RequestMapping(method=RequestMethod.GET)
    public String registration (Model model){
        model.addAttribute(new RegistrationForm());
        return "registration";
    }

     // Description: Method called by a post request to the registration controller. Method calls validation on the registration form using custom validator and returning 
     // any errors back to the user. 
    @RequestMapping(method=RequestMethod.POST)
    public String processRegistration (@Valid RegistrationForm registrationForm, BindingResult bindingResult, Model model){
        logger.info("Received the following registration form details");
        logger.info(registrationForm.toString());

        if (bindingResult.hasErrors()) {
            logger.warn("Registration Validation Failed");
            model.addAttribute("validationError", "Please correct the fields marked with errors");
            return "registration";
        }

        try {
            iRegistrationService.registerUser(registrationForm);
        } catch (Exception e) {
            logger.error("An Exception has occured processing the registration form");
            model.addAttribute("exceptionError", "An exception has occured, please try again.");
            e.printStackTrace();
            return "registration";
        }

        return "redirect:login.htm?registration=sucessful";
    }
}

등록 서비스 :

package com.doyleisgod.golfer.services;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.encoding.ShaPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import com.doyleisgod.golfer.dao.IRegistrationDAO;
import com.doyleisgod.golfer.formdata.RegistrationForm;

@Service("IRegistrationService")
public class RegistrationService implements IRegistrationService {
    @Autowired private IRegistrationDAO iRegistrationDAO;
    private final boolean enabled = true;
    private final String roles = "ROLE_USER";


    @Override
    @Transactional (rollbackFor = Exception.class)
    public void registerUser(RegistrationForm registrationForm) throws Exception {
        System.out.println("inside the registerUser method. is wrapped in transaction: "+TransactionSynchronizationManager.isActualTransactionActive());

        String username = registrationForm.getUsername();
        String password = registrationForm.getPassword();
        String firstname = registrationForm.getFirstname();
        String lastname = registrationForm.getLastname();
        String email = registrationForm.getEmail();
        int handicap = Integer.parseInt(registrationForm.getHandicap());
        String encryptedPassword = ((new ShaPasswordEncoder()).encodePassword(password, username));

        iRegistrationDAO.insertUser(username, encryptedPassword, enabled);
        iRegistrationDAO.insertRoles(username, roles);
        iRegistrationDAO.insertUserDetails(username, firstname, lastname, email, handicap);
    }

    @Override
    public boolean checkUser(String username) {
        return iRegistrationDAO.checkUserName(username);
    }
}

등록 DAO :

package com.doyleisgod.golfer.dao;

import javax.annotation.Resource;
import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.support.TransactionSynchronizationManager;

@Repository("iRegistrationDAO")
public class RegistrationDAO extends JdbcTemplate implements IRegistrationDAO {

    @Resource private BasicDataSource dataSource;

    @Override
    public boolean checkUserName(String username) {
        int db_user = queryForInt("select count(username) from users where username = ?", username);

        if (db_user == 1 ){
            return true;
        }

        return false;
    }

    @Override
    public void insertUser(String username, String password, boolean enabled) throws Exception {
        System.out.println("inside the insertuser method. is wrapped in transaction: "+TransactionSynchronizationManager.isActualTransactionActive());

        update("insert into users (username, password, enabled) VALUES (?,?,?)", username, password, enabled);
    }

    @Override
    public void insertRoles(String username, String roles) throws Exception {
        update("insert into user_roles (username, authority) VALUES (?,?)", username, roles);
    }

    @Override
    public void insertUserDetails(String username, String firstname, String lastname, String email, int handicap) throws Exception {
        update("insert into user_detailss (username, first_name, last_name, email_address, handicap)" + 
                "VALUES (?,?,?,?,?)", username, firstname, lastname, email, handicap);

    }

    public void setDataSource(BasicDataSource dataSource) {
        this.dataSource = dataSource;
    }

    public BasicDataSource getDataSource() {
        return dataSource;
    }
}

해결법

  1. ==============================

    1.은 @Transactional 어노테이션 된 bean 메소드를 트랜잭션을 처리하는 AOP 메소드 인터셉터로 래핑하는 포스트 프로세서이다. 행동. 스프링 포스트 프로세서는 정의 된 특정 애플리케이션 컨텍스트에서만 작동합니다.

    은 @Transactional 어노테이션 된 bean 메소드를 트랜잭션을 처리하는 AOP 메소드 인터셉터로 래핑하는 포스트 프로세서이다. 행동. 스프링 포스트 프로세서는 정의 된 특정 애플리케이션 컨텍스트에서만 작동합니다.

    @Transactional로 주석 된 bean은 서블릿 애플리케이션 컨텍스트에있는 반면, 애플리케이션 컨텍스트에서는 포스트 프로세서를 정의했다. 따라서 사후 처리기는 서블릿 컨텍스트 bean이 아닌 응용 프로그램 컨텍스트 bean에서만 작동합니다. 컨텍스트 : 구성 요소 스캔 태그가 응용 프로그램 컨텍스트로 이동하면 사후 처리기가 트랜잭션 방식을 적절히 감 았습니다.

    희망이 어떤 의미가 있습니다.

    [편집하다]

    Application Context와 Servlet Context의 차이점은 무엇입니까?

    Spring 후 처리기 란 무엇이며 어떻게 작동합니까?

    봄에 AOP는 무엇입니까?

  2. from https://stackoverflow.com/questions/10019426/spring-transactional-not-working by cc-by-sa and MIT license