mybatis的通用Mapper外掛以及分頁外掛(2018/1/17)
SSM框架 spring4.0.2+mybatis3.2.6 maven工程
不會搭建框架的小哥們請自行前往這個大神的部落格搭建,本博文只針對於通用mapper外掛廢話不多說
首先引入依賴(版本我用的都是最新的):
程式碼塊中有左邊這個span標籤,我不知道怎麼弄了去,你們引用的時候直接替換掉就行了。
<!-- 通用mapper --> <dependency> <groupId>tk.mybatis</groupId> <artifactId>mapper</artifactId> <version>3.5.0</version> </dependency> <!-- 分頁外掛 --> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.0.0</version> </dependency> <dependency> <groupId>javax.persistence</groupId> <artifactId>persistence-api</artifactId> <version>1.0</version> </dependency>
(有人可能會問為什麼不用這個<dependency>
<groupId>com.github.abel533</groupId>
<artifactId>mapper</artifactId>
<version>2.3.4</version>
</dependency> ,我最後再說一下網上90%的Demo都是這個但是我不用的原因)
第二個是分頁外掛,最新jar包前往這個地址:
同時這個外掛需要JPA註解,引入即可,jar包下載前往:
然後是配置檔案:不多說上程式碼:
spring-mybatis.xml 程式碼:
這兩個外掛順序其實我顛倒了是沒有影響查詢的,但是根據spring的載入順序或者mybatis的載入順序什麼的(我還只是個小白沒深入瞭解過原始碼和原理),網上那些大神寫的通用mapper和page和pagehelper是不能顛倒順序的(這個我最開始學確實是不能顛倒的)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd" default-lazy-init="true"> <!-- 自動掃描 --> <context:component-scan base-package="com.cn.hunst" /> <!-- 引入配置檔案 --> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="classpath:jdbc.properties" /> </bean> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${driver}" /> <property name="url" value="${url}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> <!-- 初始化連線大小 --> <property name="initialSize" value="${initialSize}"></property> <!-- 連線池最大數量 --> <property name="maxActive" value="${maxActive}"></property> <!-- 連線池最大空閒 --> <property name="maxIdle" value="${maxIdle}"></property> <!-- 連線池最小空閒 --> <property name="minIdle" value="${minIdle}"></property> <!-- 獲取連線最大等待時間 --> <property name="maxWait" value="${maxWait}"></property> </bean> <!-- DAO介面所在包名,Spring會自動查詢其下的類 --> <bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.cn.hunst.dao" /> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property> <property name="properties"> <value> <!-- 通用mapper --> mappers=tk.mybatis.mapper.common.Mapper </value> </property> </bean> <!-- spring和MyBatis完美整合,不需要mybatis的配置對映檔案 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <!-- 自動掃描mapping.xml檔案 --> <property name="mapperLocations" value="classpath:com/cn/hunst/mapping/*.xml"></property> <property name="typeAliasesPackage" value="com.cn.hunst.pojo"></property> <property name="plugins"> <array> <!-- 分頁外掛 --> <bean class="com.github.pagehelper.PageInterceptor"> <property name="properties"> <value> <!--使用預設配置即可 --> </value> </property> </bean> <!-- 分頁外掛 這個是不對的--> <!-- <bean class="com.github.pagehelper.PageInterceptor"> <property name="properties"> <value> helperDialect=mysql reasonable=true supportMethodsArguments=true params=count=countSql autoRuntimeDialect=true </value> </property> </bean> --> <!-- 通用mapper 這個通用mapper執行的時候報錯 --> <!-- <bean class="com.github.abel533.mapperhelper.MapperInterceptor"></bean> --> </array> </property> </bean> <!-- (事務管理)transaction manager, use JtaTransactionManager for global tx --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" /> </beans>
Mapper類必須繼承Mapper<T> 泛型為實體類
import tk.mybatis.mapper.common.Mapper;// 此為包名
public interface UserMapper extends Mapper<User>{}
以上是所有的配置
然後說下測試:
service層:
public List<User> getLists(User user) {
PageHelper.startPage(2, 10);
return userMapper.select(user);
}
查詢結果:
繼承了Mapper之後就有了這些方法,基本滿足了單表查詢
//根據實體類不為null的欄位進行查詢,條件全部使用=號and條件
List<T> select(T record);
//根據實體類不為null的欄位查詢總數,條件全部使用=號and條件
int selectCount(T record);
//根據主鍵進行查詢,必須保證結果唯一
//單個欄位做主鍵時,可以直接寫主鍵的值
//聯合主鍵時,key可以是實體類,也可以是Map
T selectByPrimaryKey(Object key);
//插入一條資料
//支援Oracle序列,UUID,類似Mysql的INDENTITY自動增長(自動回寫)
//優先使用傳入的引數值,引數值空時,才會使用序列、UUID,自動增長
int insert(T record);
//插入一條資料,只插入不為null的欄位,不會影響有預設值的欄位
//支援Oracle序列,UUID,類似Mysql的INDENTITY自動增長(自動回寫)
//優先使用傳入的引數值,引數值空時,才會使用序列、UUID,自動增長
int insertSelective(T record);
//根據實體類中欄位不為null的條件進行刪除,條件全部使用=號and條件
int delete(T key);
//通過主鍵進行刪除,這裡最多隻會刪除一條資料
//單個欄位做主鍵時,可以直接寫主鍵的值
//聯合主鍵時,key可以是實體類,也可以是Map
int deleteByPrimaryKey(Object key);
//根據主鍵進行更新,這裡最多隻會更新一條資料
//引數為實體類
int updateByPrimaryKey(T record);
//根據主鍵進行更新
//只會更新不是null的資料
int updateByPrimaryKeySelective(T record);
說一下POJO的配置(其實都是CP):
基於JPA註解
實體類按照如下規則和資料庫表進行轉換,註解全部是JPA中的註解:
-
表名預設使用類名,駝峰轉下劃線,如
UserInfo
預設對應的表名為user_info
. -
表名可以使用
@Table(name = "tableName")
進行指定,對不符合第一條預設規則的可以通過這種方式指定表名. -
欄位預設和
@Column
一樣,都會作為表字段,表字段預設為Java物件的Field
名字駝峰轉下劃線形式. -
可以使用
@Column(name = "fieldName")
指定不符合第3條規則的欄位名 -
使用
@Transient
註解可以忽略欄位,新增該註解的欄位不會作為表字段使用. -
建議一定是有一個
@Id
註解作為主鍵的欄位,可以有多個@Id
註解的欄位作為聯合主鍵. -
預設情況下,實體類中如果不存在包含
@Id
註解的欄位,所有的欄位都會作為主鍵欄位進行使用(這種效率極低). -
實體類可以繼承使用,可以參考測試程式碼中的
com.github.abel533.model.UserLogin2
類. -
由於基本型別,如int作為實體類欄位時會有預設值0,而且無法消除,所以實體類中建議不要使用基本型別.
除了上面提到的這些,Mapper還提供了序列(支援Oracle)、UUID(任意資料庫,欄位長度32)、主鍵自增(類似Mysql,Hsqldb)三種方式,其中序列和UUID可以配置多個,主鍵自增只能配置一個。
這三種方式不能同時使用,同時存在時按照 序列>UUID>主鍵自增
的優先順序進行選擇.下面是具體配置方法:
-
使用序列可以新增如下的註解:
//可以用於數字型別,字串型別(需資料庫支援自動轉型)的欄位 @SequenceGenerator(name="Any",sequenceName="seq_userid") @Id private Integer id;
-
使用UUID時:
//可以用於任意字串型別長度超過32位的欄位 @GeneratedValue(generator = "UUID") private String countryname;
-
使用主鍵自增:
//不限於@Id註解的欄位,但是一個實體類中只能存在一個(繼承關係中也只能存在一個) @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id;
說下為什麼寫這個文章:
從網上搜的那些基本上一直都在報錯,有的大神提供的根本就沒有這個通用mapper包,而且在spring整合分頁外掛中,提供的屬性也是一錯再錯,“方言”的key都是錯誤的!讓我折騰了一整天看原始碼,最後只能換了一個分頁外掛的包,並且屬性也是預設的,我的方言預設選擇的就是mysql。
而且最離譜的是,spring的sqlSessionFactory 這個Bean中plugins 屬性是攔截器陣列,很多大神提供的分頁外掛點進去根本就不是攔截器!我後來才發現。
(網上有不 在spring中整合,單獨寫在mybatis-config.xml 中的配置,然後在sqlSessionFactoryBean中用configLocation引用的沒試過,懶得去試了,畢竟現在沒有人不用spring了)
總之配置這個小小的通用mapper實在是挺鬧心的,其實我技術還是非常差勁的,如果我能看動原始碼就迎刃而解了。
特此紀念一下!
也歡迎同門提問互相勉勵
---------------------------------------二〇一八年一月三十一日 增加--------------------------------------------------
後期測試的時候發現我查詢的結果集有問題:發現有些欄位根本獲取不到數值,實體類欄位嚴格按照駝峰方式,但是就是獲取不到數值;後來發現是實體類資料型別的問題:
問題程式碼:
後來發現是資料型別只能使用包裝類,使用基本資料型別會報錯
更正後: