手动开启hibernate的事务的问题

0.096字数 36阅读 166

问题代码(监听redis过期的key)

package com.aaa.bbb.listen;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.transaction.Transactional;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import com.aaa.bbb.common.Exceptions;
import com.aaa.bbb.common.SpringContextHolder;
import com.aaa.bbb.dao.util.Daoutil;

public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
    private static final Logger logger = LoggerFactory.getLogger(RedisKeyExpirationListener.class);
    @Autowired
    private Daoutil daoutil;

    public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }
    /**
     *
     * 监听redis过期失效的key
     */
    @Override
    public void onMessage(Message message, byte[] pattern){
        //手动开启hibernate的事务
        HibernateTransactionManager transactionManager = SpringContextHolder.getBean("txManager");
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 事物隔离级别,开启新事务,这样会比较安全些。
        TransactionStatus status = transactionManager.getTransaction(def); // 获得事务状态
        String redisKey = message.toString();
        logger.info("即将要失效的Key:" + redisKey);
        //System.out.println("即将要失效的Key:" + redisKey);
        if (StringUtils.isNotBlank(redisKey)) {
            String countSql = "select count(*) from slogintbl where tradeno =? ";
            List<String> countParams = new ArrayList<>();
            countParams.add(redisKey);
            try {
                int count = daoutil.queryCountSql(countSql, countParams);
                if (0 == count) {
                    return;//这里return了,导致问题。
                } else {
                    List<String> params = new ArrayList<>();
                    SimpleDateFormat sf=new SimpleDateFormat("yyyyMMdd HH:mm:ss");
                    
                    params.add(sf.format(new Date()));
                    params.add(redisKey);
                    String sql = "update slogintbl set logoutdate=? where tradeno=?";
                    daoutil.updateOrSaveSql(sql, params);
                    transactionManager.commit(status);

                }
            } catch (Exception e) {
                // TODO Auto-generated catch block
                logger.debug(Exceptions.getStackTraceAsString(e));
                transactionManager.rollback(status);
            }

        }
    }
}

结果

没有关闭资源导致连接池耗尽

解决方式

  • 方式一
package com.aaa.bbb.listen;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.transaction.Transactional;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import com.aaa.bbb.common.Exceptions;
import com.aaa.bbb.common.SpringContextHolder;
import com.aaa.bbb.dao.util.Daoutil;

public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
    private static final Logger logger = LoggerFactory.getLogger(RedisKeyExpirationListener.class);
    @Autowired
    private Daoutil daoutil;

    public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }
    /**
     *
     * 监听redis过期失效的key
     */
    @Override
    public void onMessage(Message message, byte[] pattern){
        //手动开启hibernate的事务
        HibernateTransactionManager transactionManager = SpringContextHolder.getBean("txManager");
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 事物隔离级别,开启新事务,这样会比较安全些。
        TransactionStatus status = transactionManager.getTransaction(def); // 获得事务状态
        String redisKey = message.toString();
        logger.info("即将要失效的Key:" + redisKey);
        //System.out.println("即将要失效的Key:" + redisKey);
        if (StringUtils.isNotBlank(redisKey)) {
            String countSql = "select count(*) from slogintbl where tradeno =? ";
            List<String> countParams = new ArrayList<>();
            countParams.add(redisKey);
            try {
                int count = daoutil.queryCountSql(countSql, countParams);
                if (0 != count) {
                    List<String> params = new ArrayList<>();
                    SimpleDateFormat sf=new SimpleDateFormat("yyyyMMdd HH:mm:ss");
                    
                    params.add(sf.format(new Date()));
                    params.add(redisKey);
                    String sql = "update slogintbl set logoutdate=? where tradeno=?";
                    daoutil.updateOrSaveSql(sql, params);
                    transactionManager.commit(status);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                logger.debug(Exceptions.getStackTraceAsString(e));
                transactionManager.rollback(status);
            }
        }
    }
}
  • 方式二
package com.aaa.bbb.listen;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.transaction.Transactional;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import com.aaa.bbb.common.Exceptions;
import com.aaa.bbb.common.SpringContextHolder;
import com.aaa.bbb.dao.util.Daoutil;


public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {
    private static final Logger logger = LoggerFactory.getLogger(RedisKeyExpirationListener.class);
    @Autowired
    private Daoutil daoutil;

    public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }
    /**
     *
     * 监听redis过期失效的key
     */
    @Override
    public void onMessage(Message message, byte[] pattern){
        //手动开启hibernate的事务
        HibernateTransactionManager transactionManager = SpringContextHolder.getBean("txManager");
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 事物隔离级别,开启新事务,这样会比较安全些。
        TransactionStatus status = transactionManager.getTransaction(def); // 获得事务状态
        String redisKey = message.toString();
        logger.info("即将要失效的Key:" + redisKey);
        //System.out.println("即将要失效的Key:" + redisKey);
        if (StringUtils.isNotBlank(redisKey)) {
            String countSql = "select count(*) from slogintbl where tradeno =? ";
            List<String> countParams = new ArrayList<>();
            countParams.add(redisKey);
            try {
                int count = daoutil.queryCountSql(countSql, countParams);
                if (0 == count) {
                    return;//使用return
                } else {
                    List<String> params = new ArrayList<>();
                    SimpleDateFormat sf=new SimpleDateFormat("yyyyMMdd HH:mm:ss");
                    
                    params.add(sf.format(new Date()));
                    params.add(redisKey);
                    String sql = "update slogintbl set logoutdate=? where tradeno=?";
                    daoutil.updateOrSaveSql(sql, params);
                    transactionManager.commit(status);
                }
            } catch (Exception e) {
                // TODO Auto-generated catch block
                logger.debug(Exceptions.getStackTraceAsString(e));
                transactionManager.rollback(status);
            }finally {
                try {
                transactionManager.getSessionFactory().getCurrentSession().close();
                }catch(Exception e){
                    logger.debug("关闭资源异常");
                }
            }

        }
    }
}