简体   繁体   中英

MyBatis with Spring: Could not find result map

I cannot map the result of a query to a bean with MyBatis and Spring Boot using an xml file.

If I try to map the result with the annotation @ResultType(ResultBean.class) everything works, but I don't know how to map inner class, so I'm trying to map the result with the xml mapper.

I have this interface:

public interface MyMapper {
    @ResultMap("MyBean")
    @Select("SELECT myData as myData FROM myTable")
    public List<MyMapper> getMappedData();
}

And I have this MyMapper.xml file on the same package (the java class is in src/main/java/myPackage and the xml file is in /src/main/resources/myPackage).

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="myPackage.MyMapper">
    <resultMap id="MyBean" type="MyBean">
        <id property="myData " column="myData " />
    </resultMap>
</mapper>

This is the my SpringBootServletInitializer class:

@SpringBootApplication
@EnableTransactionManagement
@MapperScan("myPackage")
@PropertySource(value = "classpath:application.properties")
public class Application extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

    @Value("${spring.datasource.jndi-name}")
    private String jndiName;

    @Bean
    public DataSource dataSource() {
        final JndiDataSourceLookup dsLookup = new JndiDataSourceLookup();
        DataSource dataSource = dsLookup.getDataSource(jndiName);
        return dataSource;
    }

    @Bean
    public DataSource jndiObjectFactoryBean() {
        JndiObjectFactoryBean jofb = new JndiObjectFactoryBean();
        jofb.setJndiName(jndiName);
        return (DataSource) jofb.getObject();
    }

    @Bean
    public DataSourceTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean
    public ManagedTransactionFactory transactionFactory() {
        return new ManagedTransactionFactory();
    }

    @Bean
    public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setTypeAliasesPackage("beansPackage");
        return sessionFactory;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
      SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
      sqlSessionFactory.setDataSource(dataSource());
      return (SqlSessionFactory) sqlSessionFactory.getObject();
    }

}

The bean is

@Alias("MyBean")
public class MyBeanimplements Serializable {
    private static final long serialVersionUID = 3143220123058683967L;
    private String myData;
}

But it seems that MyBatis cannot find the xml mapper so it cannot map the result on the right bean. The error I receive is:

16:02:56,074 ERROR [org.springframework.boot.web.servlet.support.ErrorPageFilter] (default task-1) Forwarding to error page from request [/MyPage/getData] due to exception [Could not find result map myPackage.MyMapper.MyBean]: org.apache.ibatis.builder.IncompleteElementException: Could not find result map myPackage.MyMapper.MyBean

I'm missing some configuration? Maybe on the application.property file?

You have to put in < resultmap type the CanonicalName of the class

ex. MyBean pkg is: org.mypkg.MyBean:

 <resultMap id="MyBean" type="org.mypkg.MyBean">
    <id property="myData " column="myData " />
</resultMap>

Found the solution: I've used, for the xml mapper files, a dotted path (identical to the java mapper package name) but the path needs to be a normal path (with slashes and not dots).

1st thing is your bean class should have the getters and setters.

if you want to use an inner class as the bean, you have to use the $ sign to the path of your inner class like below.

<mapper namespace="myPackage.MyMapper">
    <resultMap id="MyBean" type="MainClass$MyBean">
        <id property="myData " column="myData " />
    </resultMap>
</mapper>
MainClassName$MyBean
public class MainClassName{
   
   public static class MyBean{
     private String myData;
     //getters
     //setters
   
   }
}

the reason is that Mybatits check your ben files after compiled. the MyBatis can't find a class file named MyBean.class . your class file name after compiling like this MainClassName$MyBean.class so we have to use the $ for that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM