3

Spring MVC アプリケーションで @Transactional を使用して原子性を獲得しようとしています。問題は、注釈付き関数が呼び出されるたびに、トランザクションが作成されないように見えることです。これが私の現在の設定です:

アプリケーションのコンテキスト:

<?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:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd" >

    <!-- Root Context: defines shared resources visible to all other web components -->

    <tx:annotation-driven transaction-manager="txManager"/>

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

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" >
        <property name="driverClassName" value="org.postgresql.Driver" />
        <property name="url" value="jdbc:postgresql://localhost:5432/qas" />
        <property name="username" value="postgres" />
        <property name="password" value="P0stgr3s" />   
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate" >
        <constructor-arg name="dataSource" ref="dataSource" />
    </bean>

</beans>

コントローラ ファイル:

package com.silverthorn.txtest;

import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {

    private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

    @Autowired
    private TagsDAO tagsDAO;

    /**
     * Simply selects the home view to render by returning its name.
     */
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String home(Locale locale, Model model) {
        logger.info("Welcome home! the client locale is "+ locale.toString());

        Date date = new Date();
        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);

        String formattedDate = dateFormat.format(date);

        model.addAttribute("serverTime", formattedDate );

        return "home";
    }

    @RequestMapping(value="/tags", method=RequestMethod.GET)
    public @ResponseBody ResponseDocument addTags(@RequestParam("tag") String[] tags) {
        ResponseDocument doc = new ResponseDocument();

        try {
            tagsDAO.addTags(tags);
        } catch ( RuntimeException e ) {
            doc.setError("Could not add tags");
        }

        return doc;
    }

}

およびDAOファイル:

package com.silverthorn.txtest;

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Repository("tagsDAO")
public class TagsDAO {

    @Autowired 
    private NamedParameterJdbcTemplate jdbcTemplate;

    @Transactional(propagation = Propagation.REQUIRED)
    public void addTags(String[] tags) {
        Map<String, Object> params = new HashMap<String, Object>();
        for(String tag : tags) {
            params.put("tag", tag);
            jdbcTemplate.update("INSERT INTO qas.tags (tag) VALUES (:tag)", params);
        }
    }

}

トランザクションが失敗すると想定される場合の出力ログの例を次に示します。

DEBUG: org.springframework.jdbc.core.JdbcTemplate - Executing prepared SQL update
DEBUG: org.springframework.jdbc.core.JdbcTemplate - Executing prepared SQL statement [INSERT INTO qas.tags (tag) VALUES (?)]
DEBUG: org.springframework.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource
DEBUG: org.springframework.jdbc.core.JdbcTemplate - SQL update affected 1 rows
DEBUG: org.springframework.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource
DEBUG: org.springframework.jdbc.core.JdbcTemplate - Executing prepared SQL update
DEBUG: org.springframework.jdbc.core.JdbcTemplate - Executing prepared SQL statement [INSERT INTO qas.tags (tag) VALUES (?)]
DEBUG: org.springframework.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource
DEBUG: org.springframework.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource
INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [org/springframework/jdbc/support/sql-error-codes.xml]
INFO : org.springframework.jdbc.support.SQLErrorCodesFactory - SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase]
DEBUG: org.springframework.jdbc.support.SQLErrorCodesFactory - Looking up default SQLErrorCodes for DataSource [org.apache.commons.dbcp.BasicDataSource@704fb]
DEBUG: org.springframework.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource
DEBUG: org.springframework.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource
DEBUG: org.springframework.jdbc.support.SQLErrorCodesFactory - Database product name cached for DataSource [org.apache.commons.dbcp.BasicDataSource@704fb]: name is 'PostgreSQL'
DEBUG: org.springframework.jdbc.support.SQLErrorCodesFactory - SQL error codes for 'PostgreSQL' found
DEBUG: org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator - Translating SQLException with SQL state '23505', error code '0', message [ERROR: duplicate key value violates unique constraint "tags_pkey"
  Detail: Key (tag)=(hello) already exists.]; SQL was [INSERT INTO qas.tags (tag) VALUES (?)] for task [PreparedStatementCallback]

ログ ファイルからわかるように、トランザクションは作成されていないようです。トランザクションが作成されていないため、更新をデータベースにロールバックする方法がないことは明らかです。私はこれで2日間壁に頭をぶつけていましたが、望ましい動作に近づくことができませんでした. これについて私が得ることができるどんな助けも大歓迎です。

4

1 に答える 1

2

念のために-パスにCGLIBライブラリがない場合、問題になる可能性があります。@Repository にはインターフェースがなく、その場合、Spring は @Transactional アノテーション付きクラスの CGLIB プロキシを作成するため、CGLIB が必要になります (CGLIB が存在しない場合は失敗します)。CGLIBまたはaspectjプロキシのいずれかを使用できます。

于 2012-07-05T19:07:16.793 に答える