美文网首页
手动开启hibernate的事务的问题

手动开启hibernate的事务的问题

作者: jarWorker | 来源:发表于2019-05-24 16:40 被阅读0次

    问题代码(监听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("关闭资源异常");
                    }
                }
    
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:手动开启hibernate的事务的问题

          本文链接:https://www.haomeiwen.com/subject/oqhnzqtx.html