1. 程式人生 > >mybatis的通用Mapper外掛以及分頁外掛(2018/1/17)

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>
第一個是通用mapper的依賴,最新jar包下載前往:

(有人可能會問為什麼不用這個<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中的註解:

  1. 表名預設使用類名,駝峰轉下劃線,如UserInfo預設對應的表名為user_info.

  2. 表名可以使用@Table(name = "tableName")進行指定,對不符合第一條預設規則的可以通過這種方式指定表名.

  3. 欄位預設和@Column一樣,都會作為表字段,表字段預設為Java物件的Field名字駝峰轉下劃線形式.

  4. 可以使用@Column(name = "fieldName")指定不符合第3條規則的欄位名

  5. 使用@Transient註解可以忽略欄位,新增該註解的欄位不會作為表字段使用.

  6. 建議一定是有一個@Id註解作為主鍵的欄位,可以有多個@Id註解的欄位作為聯合主鍵.

  7. 預設情況下,實體類中如果不存在包含@Id註解的欄位,所有的欄位都會作為主鍵欄位進行使用(這種效率極低).

  8. 實體類可以繼承使用,可以參考測試程式碼中的com.github.abel533.model.UserLogin2類.

  9. 由於基本型別,如int作為實體類欄位時會有預設值0,而且無法消除,所以實體類中建議不要使用基本型別.

除了上面提到的這些,Mapper還提供了序列(支援Oracle)、UUID(任意資料庫,欄位長度32)、主鍵自增(類似Mysql,Hsqldb)三種方式,其中序列和UUID可以配置多個,主鍵自增只能配置一個。

這三種方式不能同時使用,同時存在時按照 序列>UUID>主鍵自增的優先順序進行選擇.下面是具體配置方法:

  1. 使用序列可以新增如下的註解:

    //可以用於數字型別,字串型別(需資料庫支援自動轉型)的欄位
    @SequenceGenerator(name="Any",sequenceName="seq_userid")
    @Id
    private Integer id;
    
  2. 使用UUID時:

    //可以用於任意字串型別長度超過32位的欄位
    @GeneratedValue(generator = "UUID")
    private String countryname;
    
  3. 使用主鍵自增:

    //不限於@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實在是挺鬧心的,其實我技術還是非常差勁的,如果我能看動原始碼就迎刃而解了。

特此紀念一下!

也歡迎同門提問互相勉勵

---------------------------------------二〇一八年一月三十一日 增加--------------------------------------------------

後期測試的時候發現我查詢的結果集有問題:發現有些欄位根本獲取不到數值,實體類欄位嚴格按照駝峰方式,但是就是獲取不到數值;後來發現是實體類資料型別的問題:

問題程式碼:


後來發現是資料型別只能使用包裝類,使用基本資料型別會報錯

更正後: