在启动期间,Spring warn-logging显示创建例如
的错误
“名为'userRepositoryInterface'的bean ... init方法的调用失败;嵌套异常是java.lang.IllegalArgumentException:需要属性'sqlSessionFactory'或'sqlSessionTemplate'”
在接下来的几分钟内,每个RepositoryInterface重复多次,但最终问题解决了,应用程序正常运行。
但启动时间是不可接受的。此外,当我添加一个新的RepositoryInterface时,启动时间扩展到20分钟,直到服务器(weblogic 12c)内存不足。
这些RepositoryInterfaces的实现类是由Spring / Mybatis(spring 4.1.3,mybatis 3.2.8和mybatis-spring 1.2.2)编写的,它扫描(xml)mapper文件来执行此操作。
存储库(DAO)接口在调用它们的服务类中自动装配,例如,
@Autowired
private UserRepositoryInterface repository;
存储库接口使用@Repository
进行分配
我有一个@Configuration
和@MapperScan
带注释的PersistenceConfigurer,它包含两个@Bean
方法:
在启动过程结束之前,不会调用dataSource和sqlSessionFactory,这似乎是问题所在。
我试图通过向PersistenceConfigurer添加@Order(0)
来改变它,但这没有任何效果。将两个Bean移动到其他配置类也没有任何积极影响
对于Spring,我使用Java配置,没有xml
在回应评论时,这里是整个PersistenceConfigurer:
package org.xx.xxxxxxx.configuration;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.jndi.JndiTemplate;
import javax.naming.NamingException;
import javax.sql.DataSource;
/**
* This class configures the application's persistence layer.
*/
@Configuration
@MapperScan(basePackages = "org.xx.xxxxxxx.repository")
public class PersistenceConfigurer {
static Logger LOGGER = LogManager.getLogger(PersistenceConfigurer.class);
@Value("${jdbc.datasource}")
private String jdbcDatasource; // in jdbc.properties: jdbc.datasource=jdbc/OurDS
@Value("classpath*:sqlmapper/*.xml")
private Resource[] mapperFiles;
@Value("classpath:mybatisConfig.xml")
private Resource myBatisConfig;
/**
* @return The configured data source.
*/
@Bean
public DataSource dataSource() {
JndiTemplate jndiTemplate = new JndiTemplate();
DataSource dataSource = null;
LOGGER.debug("Configuring datasource creating datasource with jndiname " + jdbcDatasource);
try {
// this works for weblogic, but not for Tomcat
dataSource = (DataSource) jndiTemplate.lookup(jdbcDatasource);
LOGGER.debug("Configuring datasource successfully created datasource " + dataSource);
} catch (NamingException e) {
LOGGER.error("Configuring datasource error creating datasource NamingException " + jdbcDatasource);
} catch (Exception e) {
LOGGER.error("Configuring datasource error creating datasource " + jdbcDatasource);
e.printStackTrace();
}
return dataSource;
}
/**
* @param dataSource A configured data source.
* @return The SQL session factory bean for data management.
*/
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) {
LOGGER.debug("sqlSessionFactory making SqlSessionFactoryBean with datasource " + dataSource);
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setMapperLocations(mapperFiles);
factoryBean.setConfigLocation(myBatisConfig);
return factoryBean;
}
}
答案 0 :(得分:1)
我的一位同事找到了主要解决方案:不要返回SqlSessionFactoryBean
而是SqlSessionFactory
在此解决方案之前,启动时间取决于RepositoryInterfaces的数量:
5 RepositoryInterfaces:12秒,6:> 80秒; 7:9分钟以记忆问题结束
之后,总是9秒。
此解决方案无法立即生效,因为由于修复,现在创建时间过早,它先于在WebMvcConfigurerAdapter中声明的PropertySourcesPlaceholderConfigurer创建。 所以我们直接在PersistenceConfigurer中解析所需的属性。谢谢你,Karthik提出这个建议。
PersistenceConfigurer中更改的代码:
增加进口:
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
3更改了私有变量(现在所有3个都是简单的字符串,没有@Value
注释):
private String jdbcDatasource = "jdbc/OurDS"; // moved away from jdbc.properties (was only property left there)
private String mapperFilesLocation = "classpath*:sqlmapper/*.xml";
private String myBatisConfigLocation = "classpath:mybatisConfig.xml";
一个已更改的方法,主要更改是返回的对象。添加了三行属性解析。
/**
* @param dataSource A configured data source.
* @return The SQL session factory (org.apache.ibatis.session.defaults.DefaultSqlSessionFactory).
* @throws Exception on sqlSessionFactoryBean.getObject(), IOException on resolver.getResources
*/
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) {
LOGGER.debug("sqlSessionFactory making SqlSessionFactoryBean with datasource " + dataSource);
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] mapperFiles = resolver.getResources(mapperFilesLocation);
Resource myBatisConfig = resolver.getResource(myBatisConfigLocation);
factoryBean.setMapperLocations(mapperFiles);
factoryBean.setConfigLocation(myBatisConfig);
return factoryBean.getObject();
}