mybatis spring mvc application, getting Invalid bound statement (not found)

Viewed 78973

this is my first mybatis spring mvc application using spring 3.2.4, mybatis-spring-1.2.1

When i try to call my webservice i get the error::

org.springframework.web.util.NestedServletException: Request processing failed; 
nested exception is org.apache.ibatis.binding.BindingException: Invalid bound 
statement (not found): 
org.mydomain.formulary.drugmaster.dao.DrugMasterDao.getDrugsWithAlert

I must be missing something obvious. Thanks for any help

Here are my associated files: applicationContext.xml

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="formularyDb" />
    <property name="configLocation"  value="file:/web/sites/drugformulary-spring/config/mybatis-config.xml" />
</bean>

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="org.mydomain.formulary.mappers" />
</bean>
<bean id="DrugMasterDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <property name="mapperInterface" value="org.mydomain.formulary.drugmaster.dao.DrugMasterDao" />
    <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg index="0" ref="sqlSessionFactory" />
</bean>

mapper file --> /classes/org/mydomain/formulary/mappers/drugmasterDao.xml

<mapper namespace="org.mydomain.formulary.drugmaster.dao.DrugMasterDao">

<select id="getDrugsWithAlert" parameterType="int" resultType="org.mydomain.formulary.drug_master.model.DrugMasters">
    Select drug_id,drug_name,drug_alert_date,drug_alert_source, rownum
    from (select drug_id,drug_name,to_char(drug_alert_datetime,'MM/DD/YYYY') as drug_alert_date ,drug_alert_source, rownum
    from drug_master
    where drug_status ='A' and length(drug_alert) > 0
    order by drug_alert_datetime DESC )
    where
    <if test="_parameter != null">
        rownum &lt; #{count}
    </if>
</select>
</mapper>

mapper file --> /classes/org/mydomain/formulary/drugmaster/dao/DrugMasterDao.java

public interface DrugMasterDao {
    public List<DrugMasters> getDrugsWithAlert(int count);
}

controller file --> /classes/org/mydomain/formulary/drugmaster/controller/DrugMasterController.java

@Controller
public class DrugMasterController {
@Autowired
DrugMasterService drugMasterService;


@RequestMapping(value = "/drugmaster/withalerts/count/{count}", method = RequestMethod.GET)
public String withAlerts(ModelMap model, @PathVariable int count) {

    List<DrugMasters> drugs = drugMasterService.getDrugsWithAlert(count);

    return null/*for now*/;

}
}    

service file --> /classes/org/mydomain/formulary/drugmaster/service/DrugMasterServiceImpl.java

@Service
public class DrugMasterServiceImpl implements DrugMasterService {

    @Autowired
    DrugMasterDao drugMasterDao;

    public List<DrugMasters> getDrugsWithAlert(int count){
        return drugMasterDao.getDrugsWithAlert(count);
    }
}

mybatis-configfile -->

<configuration>
<settings>
    <setting name="cacheEnabled" value="false" />
    <setting name="lazyLoadingEnabled" value="false" />
</settings>
</configuration>

enter image description here

17 Answers

In my case, I had multiple DataSource and should set mappler locations for each SessionFactory.

SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(mysqlDataSource);
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sessionFactory.setMapperLocations(resolver.getResources("classpath:mappers/**/*Mapper.xml"));

(There could be many reasons, my case is a bit rare & weird, it's hard to discover, so I'd like to add an answer here, just in case someone did the same thing as me.)

In my case, then reason is in IDEA, when create multi-level package for mapper file I input mybatis.mapper, which only create a single dir but with name contains ..

While I should actually input mybatis/mapper to create multi-level dir at once.

In these 2 cases, the dir are shown the same as mybatis.mapper in the project view of IDEA, so it took me quiet a while to figure out why ...

Except for @Dariusz mentioned above, I've also forgotten to add mapper location.

<property name="mapperLocations" value="classpath:mybatis/mappers/*.xml"/>

I have also encountered this problem in my development. In generall, if you are using xml configuration files for spring,myBatis and etc., then this problem is mostly caused by some mistake in your xml configuration files.

The most voted answer by Dariusz demonstrated that there maybe some problems in the myBatis xml configuration file, while in my case, I found that problems in spring xml configuration file can also result in this problem.

In the situation of this post, in the applicationContext.xml(which should be a configuration file of Spring), we can see a basePackage configuration for the MapperScannerConfigurer:

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="org.mydomain.formulary.mappers" /> </bean>

so if the value for this property is wrong(the package name is not right), it will also result in this problem.

2 Points to cover

  1. Check whether the method name is the same in both the XML and Java methods.
  2. Mapper:scan covers the required package. If you are using annotation then @MapperScan(com.xxx) must be in the defined path.

In my case, using a query in an annotation, i didn't give enough credit to the fact that the XML in the annotation gets interpreted as XML.

So if you have

@Select("select * from table where id <> 'blabla'")

The <> is messing up the XML. You need to put it in a CDATA section

@Select("select * from table where id <![CDATA[ <> ]]> 'blabla'")
Related