xiaokang520
2010-01-11 15:16
浏览 182
已采纳

Spring2.5事务管理没有运行起来,哪里错了咧?

基于泛型、反射,使用jdbcTemplate写了一个公共DAO,作为小例子前提测试一下业务层的事务,用的注解@Transactional
DAO代码片断:
[code="java"]
public boolean insertSingleData(final List datas) throws Exception{
if (null == datas || datas.size()==0)
return false;
...

    String sql = String.format("INSERT INTO %s %s VALUES %s",
            type.getSimpleName().toLowerCase(),
            fieldList.toString().replace('[', '(').replace(']', ')'),
            paramList.toString().replace('[', '(').replace(']', ')') );

    BatchPreparedStatementSetter setter = new BatchPreparedStatementSetter() {
        public void setValues(PreparedStatement arg0, int arg1) throws SQLException {
                final T currentVo = datas.get(arg1);
                for(int v=0;v<targetFields.size();v++){
                    try {
                        arg0.setObject(v+1, getBeanFieldValues(currentVo,targetFields.get(v).toLowerCase()));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
        }

        public int getBatchSize() {
            return datas.size();
        }
    };

    int[] result = jdbcTemplate.batchUpdate(sql, setter);
    return (result.length == datas.size())?true:false;
}

[/code]

然后有一个业务层Services的方法片段
[code="java"]
@Transactional(rollbackFor=Exception.class)
public void TestTrans() throws Exception{
vo =xxx;
pvo = xxxx;
commonDbService.insertSingleData(vo);
commonDbService.insertSingleData(pvo);
}
[/code]

pvo我模拟插入一个超长字段值,引起了异常。预期结果应该是两个都要回滚,可是vo的值却插入到数据库中了,并没有回滚?
哪里有问题咧?
[b]问题补充:[/b]
To:lovewhzq

是基于注解的方式

想法是在业务层实现事务控制,DAO只是最小的数据处理单元,我在业务层做的事务定义
@Transactional(rollbackFor=Exception.class)

public void TestTrans() throws Exception

至于Dao这一层,做不做以下配置
@Transactional(propagation=Propagation.REQUIRED)
都不起作用,一次insertSingleData还是一个事务,二个一起跑第二个错了第一个没有回滚...
[b]问题补充:[/b]

感谢各位

TO:sunlightcs
DAO里面没有用@Trans...只在业务层使用了。

To:lovewhzq:
DAO只是做了一个反射,使用的jdbcTemplate,本身并没有使用与事务相关的东东

实在很郁闷...
[b]问题补充:[/b]
贴出源代码,以更新举例吧
[quote]
/**
* 根据主键ID更新
*/
public int updateDataById(T vo) throws RuntimeException{
try{
final Class<?> type = vo.getClass();
String fieldName = "";
ArrayList fieldList = new ArrayList();
ArrayList fieldNames = new ArrayList();
for(Field field : type.getDeclaredFields()){
fieldName = field.getName();
//结果值不为null并且字段名称不以_结束,即虚字段
if (null!=getBeanFieldValues(vo,fieldName) && !fieldName.endsWith("_")){
fieldList.add(fieldName.concat("=?"));
fieldNames.add(fieldName);
}
}
String sql = String.format("UPDATE %s SET %s WHERE id=?",
type.getSimpleName().toLowerCase(),
fieldList.toString().replace('[', ' ').replace(']', ' ') );
showLog(sql);
Object[] params = new Object[fieldNames.size()+1];
for(int m=0;m<fieldNames.size();m++){
params[m] = getBeanFieldValues(vo, fieldNames.get(m));
}
params[params.length-1] = getBeanFieldValues(vo, "id");
return jt.update(sql, params);
}catch (Exception e){
throw new RuntimeException();
}
}
[/quote]
业务层测试源代码
[code="java"]
@Transactional
public void TestTrans() throws RuntimeException{
Person vo=null;
Products pvo = null;
try{
vo = commonDbService.queryDataById(Person.class, null, null, "101",null);
vo.setName("aaa");
pvo = commonDbService.queryDataById(Products.class, null, null, 1, null);

    pvo.setProductname("jackjackjackjackjackjackjackjackjackjackjackjackjackjackjackjackjackjack");//这里引发异常
    commonDbService.updateDataById(vo); // 他居然提交了,没有回滚
    commonDbService.updateDataById(pvo);
    }catch (Exception e){
        throw new RuntimeException(){};
    }
}

[/code]
Spring配置
[code="java"]
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

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

<bean id="mainbean" class="net.duoer.MainBean" autowire="byName" />

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource">
        <ref bean="dataSource" />
    </property>
</bean>

<bean id="commonDbService" class="net.duoer.service.impl.MySQLCommonDBServiceImpl">
    <property name="jt" ref="jdbcTemplate" />
    <property name="isDebug" value="true"></property>
</bean>

[/code]
不晓得哪里出了问题...

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

7条回答 默认 最新

  • xkuff 2010-01-12 12:58
    已采纳

    从你的配置看,你应该是使用mysql数据库,mysql数据库表有区分支持事务和不支持事务的,MyISAM是不支持事务的,InnoDB才支持事务,请先检查你的数据库表是否支持事务。

    MyISAM和InnoDB的异同:
    [url]http://www.iteye.com/topic/547379[/url]

    点赞 打赏 评论
  • wanghaolovezlq 2010-01-11 15:45

    commonDbService.insertSingleData这个方法有配置事务吗?

    看看你的配置文件

    点赞 打赏 评论
  • wanghaolovezlq 2010-01-11 16:39

    这种情况很可能就是insertSingleData本身也有事务管理的感觉,导致这样就出问题了

    点赞 打赏 评论
  • wanghaolovezlq 2010-01-11 17:00

    你的声明式事务配置是到底是@Transactional 还是@Transactional(rollbackFor=Exception.class)

    rollbackFor
    一组 Class 类的实例,必须是Throwable 的子类 一组异常类,

    遇到时 必须 进行回滚。默认情况下checked exceptions不进行回滚,仅unchecked exceptions(即RuntimeException的子类)才进行事务回滚。

    点赞 打赏 评论
  • wanghaolovezlq 2010-01-11 17:09

    对了,你的commonDbService是由哪注入的?

    点赞 打赏 评论
  • CaiHuajiang 2010-01-11 17:12

    我要我的一个帖子里讲过一个类似的问题,在使用ibatis时,因为直接使用的连接池功能,而连接池通常都是默认autocommit的,所以事务都是自动提交的。
    [url]http://huajiang.iteye.com/blog/549047[/url]

    点赞 打赏 评论
  • CaiHuajiang 2010-01-11 18:43

    我看业务层方法是正确的,,而测试用的方法是错的,因为测试方法是没有捕获runtimeexception异常的。

    点赞 打赏 评论

相关推荐 更多相似问题