2015-05-15 14 views
5

Hôm nay tôi đã chuẩn bị một ví dụ bằng cách sử dụng Spring Boot và sử dụng MyBatis cho giao tiếp truy cập dữ liệu bên cạnh Spring-MyBatis. Dưới đây là cấu hình dự án có liên quan (sử dụng maven):Tại sao giao diện và tệp bản đồ xml phải nằm trong cùng một gói và có cùng tên?

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 

nội dung có liên quan của các tập tin:

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> 

Sau đó, tôi tiêm một thể hiện của dao này trong một bộ điều khiển yêu cầu (cho mục đích thử nghiệm), như thế này:

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(); 
    } 
} 

tôi chạy dự án của tôi và kiểm tra việc thực hiện bằng cách sử dụng curl localhost:8080/category/all và sau đó dự kiến ​​để xem kết quả ở định dạng JSON, nhưng tôi có ngoại lệ này thay vì:

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) 
(...) 

Tôi không hiểu nguyên nhân điều này. Có một giao diện CategoryDao và nó có phương thức thích hợp getAllCategories khớp với <select id="getAllCategories">. Sau một thời gian chơi với điều này, tôi đã thay đổi tên giao diện dao thành CategoryMapper và cập nhật không gian tên trong CategoryMapper.xml. Sau khi tôi đã làm điều này, mọi thứ hoạt động bình thường. Ngoài ra, sau khi có cùng tên cho lớp và xml, tôi đã di chuyển lớp dao và trình ánh xạ xml thành các gói khác nhau (stil sử dụng cùng tên cho cả hai: CategoryMapper.), Cập nhật không gian tên trong tệp xml và có cùng ngoại lệ , với thông báo được cập nhật để hiển thị tên của gói của giao diện dao. Nhưng sau đó một lần nữa, tôi di chuyển cả hai tập tin vào cùng một gói và tất cả mọi thứ đã làm việc một lần nữa.

Vì vậy, câu hỏi của tôi là: tại sao MyBatis cần giao diện và tệp bản đồ xml có cùng tên và nằm trong cùng một gói? Đây có phải là thiết kế MyBatis hoặc sự cố trong Spring MyBatis không?

Trả lời

5

Bạn cũng có tệp Cấu hình MyBatis không?

Nếu tôi nhớ chính xác cùng một tên cùng một vị trí cho tệp XML như giao diện là khi bạn muốn có một thiết lập chỉ hoạt động mà không có cấu hình bổ sung.

Nếu bạn có trình ánh xạ XML ở một nơi khác, bạn có thể chỉ định đường dẫn lớp của các tệp XML theo cách thủ công bằng cách sử dụng phần tử <mappers> bên trong MyBatis configuration.

Từ Injecting Mappers documentation:

Nếu UserMapper có một file mapper MyBatis XML tương ứng ở vị trí classpath tương tự như giao diện lập bản đồ, nó sẽ được phân tích tự động bởi MapperFactoryBean. Không cần phải chỉ định trình ánh xạ trong tệp cấu hình MyBatis trừ khi các tệp XML của trình ánh xạ nằm trong một vị trí đường dẫn lớp khác. Xem thuộc tính configLocation của SqlSessionFactoryBean để biết thêm thông tin.

Vì vậy, cố gắng này:

  1. Tạo một file mybatis-config.xml bên src/main/resources với điều này trong đó:

    <?xml version="1.0" encoding="UTF-8" ?> 
    <!DOCTYPE configuration 
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 
        "http://mybatis.org/dtd/mybatis-3-config.dtd"> 
    <configuration> 
        <mappers> 
        <mapper resource="com/test/path/etc/etc/WhateverNameYouWant.xml"/> 
        </mappers> 
    </configuration> 
    

    đâu WhateverNameYouWant.xml chứa những gì CategoryMapper.xml của bạn chứa.

  2. đặt vị trí của tập tin cấu hình (cấu hình Java như bên dưới hoặc đậu trong file applicationContext):

    @Bean 
    public SqlSessionFactoryBean sqlSessionFactory() throws Exception { 
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); 
        // .... 
        sessionFactory.setConfigLocation(new ClassPathResource("mybatis-config.xml")); 
        // .... 
        return sessionFactory; 
    } 
    
+0

tôi sử dụng '@ MapperScan' và chỉ ra các gói cơ sở nơi MyBatis có thể quét tất cả các người vẽ bản đồ của chính nó. Chú thích này hoạt động như '' để tự động quét các tập tin và do đó không sử dụng ''. –

+0

@LuiggiMendoza: '@ MapperScan' tìm giao diện. Xem chỉnh sửa của tôi cho câu trả lời. – Bogdan

+0

Điều này thật thú vị. Cuối cùng, đó là một điều MyBatis * * toàn bộ sự phân tách mối quan tâm giữa giao diện và người lập bản đồ, trong khi '@ MapperScan' giúp cho việc tự động đậu các giao diện dao. Cảm ơn bạn đã liên kết đến tài liệu thích hợp và ví dụ. –

1

tôi đã sử dụng cách sau đây mà không @MapperScan như sau:

1) Thiết lập mybatis-config.xml giống như bước 2 ở trên

@Bean 
public SqlSessionFactoryBean sqlSessionFactory() throws Exception { 
    SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); 
    // .... 
    sessionFactory.setConfigLocation(new ClassPathResource("mybatis-config.xml")); 
    // .... 
    return sessionFactory; 
} 

2) Thiết lập CategoryDao

@Bean 
public CategoryDao getCategoryDao() throws Exception{ 
    SqlSessionTemplate sessionTemplate = new SqlSessionTemplate(sqlSessionFactoryBean()); 
    return sessionTemplate.getMapper(CategoryDao.class); 
} 

3) Cài đặt trong vòng mybatis-config.xml

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE configuration 
     PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 
     "http://mybatis.org/dtd/mybatis-3-config.dtd"> 

<configuration> 

    <settings> 
     <setting name="logImpl" value="COMMONS_LOGGING"/> 
    </settings> 

    <mappers> 

     <mapper class="CategoryMapper.xml"/> 
    </mappers> 

</configuration> 
Các vấn đề liên quan