Oggi stavo preparando un esempio utilizzando Spring Boot e utilizzando MyBatis per la comunicazione di accesso ai dati accanto a Spring-MyBatis. Ecco la configurazione del progetto in questione (usando Maven):Perché il file di interfaccia e il file di mappatura xml devono essere nello stesso pacchetto e avere lo stesso nome?
src/main/java
- edu.home.ltmj.controller
+ CategoryController.java
- edu.home.ltmj.dao
+ CategoryDao.java
- edu.home.ltmj.domain
+ Category.java
src/main/resources
- edu.home.ltmj.dao
+ CategoryMapper.xml
contenuti rilevanti del file:
CategoryDao.java:
package edu.home.ltmj.dao;
public interface CategoryDao {
List<Category> getAllCategories();
}
CategoryMapper.xml:
<mapper namespace="edu.home.ltmj.dao.CategoryDao">
<resultMap id="categoryMap"
type="edu.home.ltmj.domain.Category">
<id property="id" column="id" />
<result property="name" column="name" />
</resultMap>
<select id="getAllCategories" resultMap="categoryMap">
SELECT id, nombre
FROM category
</select>
</mapper>
Quindi, inietto un'istanza di questo dao in un controller di richiesta (a scopo di test), in questo modo:
package edu.home.ltmj.controller;
@RestController
public class CategoryController {
@Autowired
private CategoryDao dao;
@RequestMapping(value="/category/all",
method=RequestMethod.GET,
produces=MediaType.APPLICATION_JSON_VALUE)
public List<Categoria> getAllCategories() {
return dao.getAllCategories();
}
}
eseguo il mio progetto e testare l'esecuzione utilizzando curl localhost:8080/category/all
e poi si aspettava di vedere i risultati in formato JSON, ma ho avuto questa eccezione invece:
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): edu.home.ltmj.dao.CategoryDao.getAllCategories
at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:189)
at org.apache.ibatis.binding.MapperMethod.<init>(MapperMethod.java:43)
at org.apache.ibatis.binding.MapperProxy.cachedMapperMethod(MapperProxy.java:58)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:51)
at com.sun.proxy.$Proxy45.getAllCategories(Unknown Source)
at edu.home.ltmj.controller.CategoryRestController.getAllCategories(CategoryRestController.java:27)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
(...)
Non capisco la causa di questo. C'è un'interfaccia CategoryDao
e ha il metodo corretto getAllCategories
che corrisponde a <select id="getAllCategories">
. Dopo un po 'di tempo con questo, ho cambiato il nome dell'interfaccia dao in CategoryMapper
e aggiornato lo spazio dei nomi in CategoryMapper.xml. Dopo averlo fatto, funzionava normalmente. Inoltre, dopo aver avuto lo stesso nome per la classe e xml, ho spostato la classe dao e il mapper xml in diversi pacchetti (stil usando lo stesso nome per entrambi: CategoryMapper.), Aggiornato lo spazio dei nomi nel file xml e ottenuto la stessa eccezione , con il messaggio aggiornato per mostrare il nome del pacchetto dell'interfaccia dao. Ma poi di nuovo, ho spostato entrambi i file nello stesso pacchetto e tutto ha funzionato di nuovo.
Quindi, la mia domanda è: perché MyBatis ha bisogno che l'interfaccia e il file di mappatura xml abbiano lo stesso nome e si trovino nello stesso pacchetto? Si tratta di MyBatis o di un problema in Spring MyBatis?
Io uso '@ MapperScan' e indicare i pacchetti di base in cui MyBatis può scansione di tutti i mapper di per sé. Questa annotazione funziona come ' ' per analizzare automaticamente i file e quindi non usare ' '. –
@LuiggiMendoza: '@ MapperScan' cerca interfacce. Vedi la mia modifica alla risposta. – Bogdan
Questo è interessante. Alla fine, è una cosa di MyBatis * l'intera separazione delle preoccupazioni tra l'interfaccia e il mappatore, mentre '@ MapperScan' aiuta nella raccolta automatica dei bean delle interfacce dao. Grazie per il link alla documentazione corretta e l'esempio. –