【待解决】SpringMVC+Hibernate4的Session问题
【待解决】SpringMVC+Hibernate4的Session问题
海岸Thirty 发表于6个月前
【待解决】SpringMVC+Hibernate4的Session问题
  • 发表于 6个月前
  • 阅读 9
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云实验室 1小时搭建人工智能应用,让技术更容易入门 免费体验 >>>   

摘要: 想法是:普通情况下使用OpenSessionInViewFilter解决http请求getCurrentSession问题,某些情况下不经过http的,比如自动任务、TCP请求等,使用OpenSessionInterceptor来解决。

写在前面的话:莫名奇妙的问题好了,但是没有按照我的想法来,测试了下最终生效的是

@EnableTransactionManagement。

先看看代码吧,以后有什么突破再更新!或者最好有大神帮我看看吧。

(两次搭项目都这样,哎。。。已经不是人品问题了我觉得)

 

OpenSessionInViewFilter,这个具好用,配置上HTTP就不报下面这个错了

Could not obtain transaction-synchronized Session for current thread

这里给份注解配置吧

/**
 * 所有实现了WebApplicationInitializer接口的类都会在容器启动时自动被加载运行,用@Order注解设定加载顺序
 * 这是servlet3.0+后加入的特性,web.xml中可以不需要配置内容,都硬编码到WebApplicationInitializer的实现类中
  * <ul>
 *  <li>处理URL上下文</li>
 *  <li>定义ServletMapping映射:.do,.json,.jsonp</li>
 *  <li>加载配置文件,相当于引入applicationContext.xml</li>
 * </ul>
 * @author lanxb
 * @create 2016年5月24日
 *
 */
@Order(2)
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
	
	/*****  省略无关的内容   *********/
 
    /*
	  * 注册过滤器,映射路径与DispatcherServlet一致,路径不一致的过滤器需要注册到另外的WebApplicationInitializer中
	  */
    @Override
    protected Filter[] getServletFilters() {
        // 请求编码转换
    	CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        characterEncodingFilter.setForceEncoding(true);
        
        // OpenSession
        OpenSessionInViewFilter hibernateSessionInViewFilter = new OpenSessionInViewFilter();
        return new Filter[] {characterEncodingFilter,hibernateSessionInViewFilter};
    }
  
  


}

 

因为有一个启动时到数据库加载配置的过程,由于不经过上面的filter,所以一直报错。

    @OpenSession
	@Transactional(readOnly=true)
	@Override
	public void afterPropertiesSet() throws Exception {
		List<AppConf> list = iwxMsgCryptDao.getListByHQL("from AppConf");
		logger.info("refres app configs begin : {}",mapConfig.size());
		if(list==null || list.isEmpty()){
			synchronized (mapConfig) {
				mapConfig.clear();
			}
		}else{
			Map<String,AppConf> mapConfig = new HashMap<>(); 
			for(AppConf conf:list){
				logger.info("\t add app config:{}",conf.getAppId());
				// 生成下keyData
				conf.setAesKey(conf.getAesKey());
				mapConfig.put(conf.getAppId(), conf);
			}
			this.mapConfig = mapConfig;
		}
		logger.info("refres app configs end : {}",mapConfig.size());
	}

于是查了查增加了下面的配置OpenSessionInterceptor:

想通过AspectJ代理带有@OpenSession注解的方法,在执行的时候获取HibernateSession

主要是:

openSessionPointcut()、openSessionInterceptor()然后openSessionAdvisor()、proxyConfig()


@Configuration
@EnableTransactionManagement
public class DBConfig implements TransactionManagementConfigurer{

	final static Logger logger = LoggerFactory.getLogger(DBConfig.class);
	
	@Value("${hibernate.dialect:org.hibernate.dialect.MySQL5Dialect}")
	String hibernate_dialect;
	
	@Value("${jdbc.driver}")  
    String driverClass;  
    @Value("${jdbc.url}")  
    String url;  
    @Value("${jdbc.username}")  
    String userName;  
    @Value("${jdbc.password}")  
    String passWord;
    
    @Value("${jdbc.initialSize:1}") 
    int initialSize=1; 
	//#定义最大连接数  
    @Value("${jdbc.maxActive:20}") 
	int maxActive=20;
	//#定义最大空闲  
    @Value("${jdbc.maxIdle:20}") 
	int maxIdle=20;
	//#定义最小空闲  
    @Value("${jdbc.minIdle:1}") 
	int minIdle=1;
	//#定义最长等待时间  
    @Value("${jdbc.maxWait:60000}") 
	int maxWait=60000;
	
    
    @Bean(name = "dataSource")  
    public DataSource dataSource() {
    	logger.info("初始化数据源开始……\n{}",url);
    	BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(driverClass);  
        dataSource.setUrl(url);  
        dataSource.setUsername(userName);  
        dataSource.setPassword(passWord);  
        dataSource.setInitialSize(initialSize);
        dataSource.setMaxActive(maxActive);
        dataSource.setMaxIdle(maxIdle);
        dataSource.setMinIdle(minIdle);
        dataSource.setMaxActive(maxActive);
        logger.info("初始化数据源结束");
        return dataSource; 
    } 
    
    
    @Bean(name = "sessionFactory")
	public LocalSessionFactoryBean localSessionFactoryBean()  {
		logger.info("sessionFactory");
		LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
		sessionFactory.setDataSource(dataSource());
		String[] packagesToScan = new String[] { "pub.thirty.tbk.module.**.domain" };
		sessionFactory.setPackagesToScan(packagesToScan);
		Properties hibernateProperties = new Properties();
		hibernateProperties.setProperty("hibernate.dialect", hibernate_dialect);
		hibernateProperties.setProperty("connection.autocommit", "false");
		
		hibernateProperties.setProperty(
				"hibernate.current_session_context_class",
				"org.springframework.orm.hibernate4.SpringSessionContext"
		);

		sessionFactory.setHibernateProperties(hibernateProperties);
		return sessionFactory;

	}
    
    @Bean(name = "transactionManager")
	public HibernateTransactionManager hibernateTransactionManager() {
		logger.info("transactionManager");
		HibernateTransactionManager hibernateTransactionManager = new HibernateTransactionManager();
		hibernateTransactionManager.setSessionFactory(localSessionFactoryBean().getObject());
		hibernateTransactionManager.setNestedTransactionAllowed(true);
		return hibernateTransactionManager;
	}

    
    @Bean
    public Pointcut openSessionPointcut(){
    	AspectJExpressionPointcut bean = new AspectJExpressionPointcut(); 
    	bean.setExpression("@annotation(pub.thirty.tbk.config.annotation.OpenSession)");
    	return bean;
    }
    
    @Bean
    public OpenSessionInterceptor openSessionInterceptor(){
    	OpenSessionInterceptor oi = new OpenSessionInterceptor();
    	oi.setSessionFactory(localSessionFactoryBean().getObject());
    	return oi;
    }
    
    @Bean
    public DefaultPointcutAdvisor openSessionAdvisor(){
    	DefaultPointcutAdvisor bean = new DefaultPointcutAdvisor();
    	bean.setAdvice(openSessionInterceptor());
    	bean.setPointcut(openSessionPointcut());
    	return bean;
    }
    @Bean 
   public ProxyConfig proxyConfig(){
	   AnnotationAwareAspectJAutoProxyCreator bean = new AnnotationAwareAspectJAutoProxyCreator();
	   bean.setProxyTargetClass(true);
	   return bean;
   }
    
	@Override
	public PlatformTransactionManager annotationDrivenTransactionManager() {
		return hibernateTransactionManager();
	}
   
}

 

1、目前生效的应该是:

@EnableTransactionManagement

(我的主Config应该时另一个类,这个注解似乎不用写在主Config里,虽然网上有人这么说)

2、OpenSessionInterceptor的想法是通过新建一个针对@OpenSession 切面,

  当调用带有@OpenSession的方法时,openSession或者getCurrentSession();

    bean.setProxyTargetClass(true); 这句时为了指定CGLIB代理,因为方法的接口是InitializingBean,感觉可能代理不到,不知道是不是必须。

PS:奇怪的是上周我加了@EnableTransactionManagement也不起作用,这周写完其他模块,回来重新放开启动模块居然发现神奇的好了,不知道什么鬼!!

     

 

共有 人打赏支持
粉丝 4
博文 8
码字总数 4346
×
海岸Thirty
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: