在Spring4中使用通用Mapper
Spring4增加了對泛型注入的支持,這個特性對通用Mapper來說,非常的有用,可以說有了這個特性,可以直接在Service中寫Mapper<UserInfo> mapper
,可以通過BaseService<T>
來實現通用的Service
。
這篇文檔主要講解通用Mapper在Spring4中的**最佳用法**。
一、在Spring4中配置通用Mapper
和其他里面配置的區別就是在Spring4中可以配置通用Mapper這個類,我們可以把通用Mapper中提供的Mapper<T>
配置到Spring中,如果你有自己實現的通用Mapper,也可以這么配置:
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.isea533.mybatis.mapper,com.isea533.mybatis.mapperhelper"/>
</bean>
這里在配置basePackage
的時候,將通用Mapper<T>
所在的包com.isea533.mybatis.mapperhelper
也配置上了。這樣就能在Spring4中直接注入Mapper<T>
。
另外就是通用Mapper自身的配置:
<bean class="com.isea533.mybatis.mapperhelper.MapperHelper" depends-on="sqlSession" init-method="initMapper" scope="singleton" lazy-init="false"> <property name="mappers"> <array> <value>com.isea533.mybatis.mapperhelper.Mapper</value> </array> </property> <property name="sqlSessions" ref="sqlSession"/> </bean>
這里的配置和Spring3沒什么區別,另外需要保證有sqlSession
,可以按如下配置:
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" scope="prototype"> <constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
其他的配置按照通常的方法進行配置即可,沒有特殊的地方,如果有人不明白完整的配置什么樣,可以看下面的例子:
二、繼承Mapper<T>
實現自己的實體接口類
這里以Country2Mapper
為例:
public interface Country2Mapper extends Mapper<Country2> { //省略其他自己增加的方法 }
如果你點進去上面的Country2Mapper
查看,會發現里面還有一些Example
的方法,這些是代碼生成器生成的,生成的方法不包含通用的CRUD,只有Example
的方法,還有一個對應的Country2Mapper.xml
。
這個例子主要說明,除了通用Mapper的方法外,你可以添加自己的方法,和原來的沒有區別。
這里的實體Country2
代碼如下:
@Table(name="country") public class Country2 { @Id private Integer id; private String countryname; private String countrycode; //省略getter和setter方法 }
這里配置對應的表名為country
。只有一個主鍵id
。
三、在Service中使用
在Service中的使用方式有很多種。
第一種、直接注入上面定義的Country2Mapper
@Service public class DemoService { @Autowired private Country2Mapper mapper; public List<Country2> selectPage(int pageNum,int pageSize){ PageHelper.startPage(pageNum, pageSize); //Spring4支持泛型注入 return mapper.select(null); } }
這種方式太常見,太普通,這里不多解釋。
第二種、泛型注入
這種方式用的就很少了,但是Spring4支持泛型注入,因此在第一種的基礎上,我們可以寫出如下的代碼:
@Service public class DemoService { @Autowired private Mapper<Country2> mapper; public List<Country2> selectPage(int pageNum,int pageSize){ //這里用到了分頁插件PageHelper PageHelper.startPage(pageNum, pageSize); //Spring4支持泛型注入 return mapper.select(null); } }
對於不了解泛型注入的,可能會不習慣Mapper<Country2> mapper
這種寫法,實際上這么寫的優勢並不明顯。還不如第一種明確。
但是通過第二種,我們可以引出第三種,也可能會是很常用的通用Service。
第三種、通用Service
一般操作數據庫都在Service
中進行,不可避免的就要寫出大量重復的CRUD方法,如果能有一個通用的Service
,肯定也會減少很多工作量。
這里通過簡單擴展來講,更復雜的封裝,各位可以根據自己的情況動手實踐。
如下簡單例子:
@Service public abstract class BaseService<T> { @Autowired protected Mapper<T> mapper; public int save(T entity){ return mapper.insert(entity); } public int delete(T entity){ return mapper.deleteByPrimaryKey(entity); } /** * 單表分頁查詢 * * @param pageNum * @param pageSize * @return */ public List<T> selectPage(int pageNum,int pageSize){ PageHelper.startPage(pageNum, pageSize); //Spring4支持泛型注入 return mapper.select(null); } }
創建如上所示的抽象類BaseService<T>
,這里封裝三個方法僅作為簡單的例子。需要更復雜邏輯的可以自行摸索。
然后修改剛才的DemoService
例子:
@Service public class DemoService extends BaseService<Country2>{ }
由於BaseService<T>
封裝了單表的分頁插件,因此目前的DemoService
中沒有任何代碼。
假如我們要增加一個包含校驗的保存方法。添加如下代碼:
@Service public class DemoService extends BaseService<Country2>{ public int save(Country2 country2) { if (country2 == null) { throw new NullPointerException("保存的對象不能為空!"); } if (country2.getCountrycode() == null || country2.getCountrycode().equals("")) { throw new RuntimeException("國家代碼不能為空!"); } if (country2.getCountryname() == null || country2.getCountryname().equals("")) { throw new RuntimeException("國家名稱不能為空!"); } return super.save(country2); } }
上面只是個例子,是否拋出異常各位不用計較。
從這個例子應該也能看到,當使用Spring4和通用Mapper的時候,是多么的方便。
關於繼承Mapper<T>
我一開始為什么要設計為必須繼承Mapper<T>
實現自己的Mapper
呢?
主要考慮到兩個方面。
-
通過
<T>
可以方便的獲取泛型的類型,在通用的方法中就不需要傳遞實體類型。 -
通過繼承的
Mapper
,例如Country2Mapper
,有獨立的Mapper
就意味着有獨立的命名空間,可以緩存結果,並且不需要攔截器就能實現。
現在有了Spring4后,又有了一個很重要的原因。
-
支持泛型注入,可以實現自己的通用Service,在通用Mapper基礎上再次簡化操作,加快開發效率。
最后
如果之前說通用Mapper不如Mybatis-Generator自動生成好,我也只能說看個人喜好,不需要通用Mapper的可以不用,通用Mapper只是為了滿足一部分的人需要。
現在來看,**如果還有人說通用Mapper不如Mybatis-Generator自動生成好**,我會建議他看看這篇文檔
實際上,不需要說那個更好,適合自己的才好。
另外看完這篇文檔后,不需要再說**通用Mapper不如Mybatis-Generator自動生成好**,因為我和一些朋友正在翻譯**Mybatis-Generator**,最后還會提供**Mybatis-Generator和通用Mapper的集成插件**,可以用**Mybatis-Generator**直接生成實體類、繼承通用Mapper的實體Mapper以及XML文件。
Mybatis-Generator中文文檔地址:http://generator.sturgeon.mopaas.com/
Mybatis-Generator官方英文地址:http://mybatis.github.io/generator/index.html
這個文檔還沒有翻譯完,而且譯者水平有限,如果發現翻譯錯誤或者不合適的地方,可以在下面的地址提ISSUE
上面這個地址只是生成后的項目文檔地址,並不是我們直接用來翻譯的項目。