abel533 / MyBatis-Spring-Boot

Spring Boot集成MyBatis的基础项目
3.37k stars 1.59k forks source link

Spring DevTools 在springboot 1.5.3和mapper-spring-boot-starter 1.1.1 #53

Open rucky2013 opened 7 years ago

rucky2013 commented 7 years ago

2017-06-19 14:51:20.754 [restartedMain] ERROR org.springframework.boot.SpringApplication - Application startup failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.github.pagehelper.autoconfigure.MapperAutoConfiguration': Invocation of init method failed; nested exception is tk.mybatis.mapper.MapperException: tk.mybatis.mapper.provider.EmptyProvider中缺少selectOne方法! at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:137) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:409) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1620) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542) at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370) at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) at com.marsmob.WebStart.main(WebStart.java:25) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) Caused by: tk.mybatis.mapper.MapperException: tk.mybatis.mapper.provider.EmptyProvider中缺少selectOne方法! at tk.mybatis.mapper.mapperhelper.MapperHelper.fromMapperClass(MapperHelper.java:160) at tk.mybatis.mapper.mapperhelper.MapperHelper.registerMapper(MapperHelper.java:174) at tk.mybatis.mapper.mapperhelper.MapperHelper.registerMapper(MapperHelper.java:180) at tk.mybatis.mapper.mapperhelper.MapperHelper.registerMapper(MapperHelper.java:180) at tk.mybatis.mapper.mapperhelper.MapperHelper.registerMapper(MapperHelper.java:180) at tk.mybatis.mapper.mapperhelper.MapperHelper.registerMapper(MapperHelper.java:180) at com.github.pagehelper.autoconfigure.MapperAutoConfiguration.addPageInterceptor(MapperAutoConfiguration.java:43) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:366) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:311) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:134) ... 23 common frames omitted

abel533 commented 7 years ago

你也用的通用dao?发一个你的Mapper接口看看。

rucky2013 commented 7 years ago

public interface BaseMapper extends Mapper, InsertListMapper,ConditionMapper,IdsMapper{

}

rucky2013 commented 7 years ago

public class BaseService {

@Autowired
private BaseMapper<T> baseMapper;

public List<T> select(T record) {
    return baseMapper.select(record);
}

public T selectByPrimaryKey(Object key) {
    return baseMapper.selectByPrimaryKey(key);
}

public List<T> selectAll() {
    return baseMapper.selectAll();
}

public T selectOne(T record) {
    return baseMapper.selectOne(record);
}

public int selectCount(T record) {
    return baseMapper.selectCount(record);
}

public int insertSelective(T record) {
    return baseMapper.insertSelective(record);
}

public int updateByPrimaryKeySelective(T record) {
    return baseMapper.updateByPrimaryKeySelective(record);
}

public int deleteByPrimaryKey(Object key) {
    return baseMapper.deleteByPrimaryKey(key);
}

public List<T> selectByConditionPropertiesAndDistinct(T record,String... properties) {
    Condition condition = new Condition(record.getClass(),false);
    Criteria criteria = condition.createCriteria();
    for(Map.Entry<String, Object> entry : record.entrySet()){
        if("".equals(entry.getValue())) continue;
        criteria.andEqualTo(entry.getKey(), entry.getValue());
    }
    if(properties.length > 0) condition.selectProperties(properties);
    condition.setDistinct(true);

    return baseMapper.selectByCondition(condition);
}

public T selectOneByCondition(T record,String... properties){
    List<T> list = this.selectByCondition(record, properties);
    if(list.size() > 1) throw new TooManyResultsException();
    return list.size() > 0 ? list.get(0):null;
}

public List<T> selectByCondition(T record,String... properties) {

    Condition condition = new Condition(record.getClass(),false);
    Criteria criteria = condition.createCriteria();
    for(Map.Entry<String, Object> entry : record.entrySet()){
        if("".equals(entry.getValue())) continue;
        criteria.andEqualTo(entry.getKey(), entry.getValue());
    }
    if(properties.length > 0) condition.selectProperties(properties);

    return baseMapper.selectByCondition(condition);
}

public List<T> selectByCondition(T record, String orderByClause) {
    Condition condition = new Condition(record.getClass(),false);
    Criteria criteria = condition.createCriteria();
    for(Map.Entry<String, Object> entry : record.entrySet()){
        if("".equals(entry.getValue())) continue;
        criteria.andEqualTo(entry.getKey(), entry.getValue());
    }
    condition.setOrderByClause(orderByClause);
    return baseMapper.selectByCondition(condition);
}

public int selectCountByCondition(Object condition) {
    return baseMapper.selectCountByCondition(condition);
}

public int updateByConditionSelective(T record, Object condition) {
    return baseMapper.updateByConditionSelective(record, condition);
}

public int deleteByCondition(Object condition) {
    return baseMapper.deleteByCondition(condition);
}

public int insertList(List<T> recordList) {
    return baseMapper.insertList(recordList);
}

public ModelPage<T> selectByConditionPage(T record,String orderByClause) {

    Condition condition = new Condition(record.getClass(),false);
    Criteria criteria = condition.createCriteria();
    for(Map.Entry<String, Object> entry : record.entrySet()){
        if("".equals(entry.getValue())) continue;
        criteria.andEqualTo(entry.getKey(), entry.getValue());
    }
    condition.setOrderByClause(orderByClause);

    PageHelper.startPage(record);
    List<T> list = baseMapper.selectByCondition(condition);

    return new ModelPage<T>(list, record);
}

public List<T> selectByIds(String ids) {
    return baseMapper.selectByIds(ids);
}

public int deleteByIds(String ids) {
    return baseMapper.deleteByIds(ids);
}

}

abel533 commented 7 years ago

需要提供如 UserMapper extends Mapper<User>这样的接口。

ccfish86 commented 6 years ago

最近也遇到这个问题,可能是spring的spring-boot-devtools导致mybatis/mapper/pagehelper什么的加载顺序或方式不一致,不用devtools有可能是正常的。 isAssignableFrom在执行的时候判断一直是false,导致本来应该 templateClass 本来应该是BaseSelectProvider的,被赋值为EmptyProvider。

// MapperHelper
if (templateClass == null || !MapperTemplate.class.isAssignableFrom(templateClass)) {
    templateClass = EmptyProvider.class;
...
guodidi commented 6 years ago

@ccfish86 你可以看下的我的issue, 我已经解决了那个问题了,我的问题主要在于打包时出现了问题,你可以看下是否问题和我相似。启动时报错tk.mybatis.mapper.provider.EmptyProvider中缺少selectOne方法

ccfish86 commented 6 years ago

@guodidi 我这儿是用jhipster建出来的,非dev环境下本来就没有这个问题,只是在开发时,eclipse下直接运行才有这事。有两种方式吧:

  1. 不用spring-boot-devtools
  2. META-INF\spring-devtools.properties里配置
    #业务包,依赖的其他业务组件
    restart.include.hifi=/hifi-[\\w-\\.\\d]+.jar
    restart.include.mybatis=/mybatis-[\\w-\\.\\d]+.jar
    restart.include.mapper=/mapper-[\\w-\\.\\d]+jar
    restart.include.pagehelper=/pagehelper-[\\w-\\.\\d]+jar

其中可以通过profile来配置devtools:

    <profiles>
        <profile>
            <id>swagger</id>
            <properties>
                <profile.swagger>,swagger</profile.swagger>
            </properties>
        </profile>
        <profile>
            <id>dev</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-undertow</artifactId>
                </dependency>
                <!-- 避免在开发环境下mapper和mybatis类加载方式不一致导致初始化顺序不 -->
                <!-- 需要配置spring-devtools.properties -->
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-devtools</artifactId>
                    <optional>true</optional>
                </dependency>
            </dependencies>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-war-plugin</artifactId>
                        <configuration>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
...
abel533 commented 6 years ago

@ccfish86 通用Mapper很早就自带这个配置了。

ccfish86 commented 6 years ago

可能吧,但我们有部分业务组件是发布jar到私有maven(nexus)上,这些jar可能并没有包含在spring-devtools.properties配置里,在devtools下会出这个错误。