最近項目使用了SpringBoot+TKMytis框架,期間遇到一些問題,順便記一下。
一、框架配置
配置的話非常簡單,我用的是SpringBoot,直接引入:
-
<dependency>
-
<groupId>tk.mybatis
</groupId>
-
<artifactId>mapper-spring-boot-starter
</artifactId>
-
<version>2.0.3-beta1
</version>
-
</dependency>
-
-
<dependency>
-
<groupId>tk.mybatis
</groupId>
-
<artifactId>mapper
</artifactId>
-
<version>4.0.0
</version>
-
</dependency>
Mybatis的以及分頁插件等就不寫了。
創建一個BaseMapper
-
public
interface BaseMapper<T> extends tk.mybatis.mapper.common.BaseMapper<T>, MySqlMapper<T>, IdsMapper<T>, ConditionMapper<T>,ExampleMapper<T> {
-
-
}
這5個Mapper待會我會詳細講解。
創建BaseService<T>繼承自BaseMapper<T>
-
public
interface BaseService<T> extends BaseMapper<T> {
-
}
以及BaseService的實現類BaseServiceImpl<T> implements BaseService<T>
-
public
abstract
class BaseServiceImpl<T> implements BaseService<T> {
-
}
Service里需實現部分方法,詳細代碼在后邊。
這樣我們就基本完成了配置。
二、類配置方法
1、實體類
創建一個實體類與數據庫進行映射,此時我們使用JPA的注解:
-
package
com
.capol
.entity;
-
-
import
java
.sql
.Timestamp;
-
-
import
javax
.persistence
.Column;
-
import
javax
.persistence
.Id;
-
import
javax
.persistence
.Table;
-
import
javax
.persistence
.Transient;
-
-
import
com
.capol
.base
.BaseEntity;
-
-
import
lombok
.Data;
-
import
lombok
.EqualsAndHashCode;
-
/**
-
* @author lizihao
-
* @version 2018年07月31日
-
* 用戶角色
-
*/
-
@
Data
-
@EqualsAndHashCode(callSuper=false)
-
@Table(name=
"t_sys_user_role")//設置數據庫中表名字
-
public class UserRole extends BaseEntity{
-
-
/**
-
* 主鍵
-
*/
-
@
Column(
name =
"f_id")
-
@Id
-
private String fId;
-
-
/**
-
* 用戶ID
-
*/
-
@
Column(
name =
"f_user_id")
-
private String fUserId;
-
-
/**
-
* 用戶名
-
*/
-
@
Transient
-
private String fUserName;
-
-
}
其中@Table即數據表表名,@Column即列名,@Id作為主鍵,需要注意,@Id注解不可有多個,@Transient即冗余字段,不與數據庫任何字段對應。
分享一個小技巧,實際項目中我們可能存在多數據源的情況,如果使用的是sqlserver,且多個數據庫均在同一台服務器下且配置的賬號均擁有權限,
則@Table注解中可以寫成“{數據庫名}.{架構名}.{表名}”,如:@Table(name="db.dbo.tableName")
而不需要再額外配置數據源
2、Service類
這里主要是實現了上邊BaseMapper中繼承的5個Mapper的方法,
tk.mybatis.mapper.common.BaseMapper<T>中有較多方法,均需要繼承實現:
-
/**
-
* 保存一個實體,null屬性也會保存
-
*
-
* @param record
-
* @return
-
*/
-
int insert(T record);
-
-
/**
-
* 保存一個實體,null屬性不會保存
-
*
-
* @param record
-
* @return
-
*/
-
int insertSelective(T record);
-
-
/**
-
* 根據實體屬性作為條件進行刪除,查詢條件使用等號
-
*/
-
int delete(T record);
-
-
/**
-
* 根據主鍵更新屬性不為null的值
-
*/
-
int updateByPrimaryKeySelective(T record);
-
-
/**
-
* 根據實體中的屬性值進行查詢,查詢條件使用等號
-
*/
-
List<T> select(T record);
-
-
/**
-
* 查詢全部結果,select(null)方法能達到同樣的效果
-
*/
-
List<T> selectAll();
-
-
/**
-
* 根據實體中的屬性進行查詢,只能有一個返回值,有多個結果是拋出異常,查詢條件使用等號
-
*/
-
T selectOne(T record);
-
-
/**
-
* 根據實體中的屬性查詢總數,查詢條件使用等號
-
*/
-
int selectCount(T record);
以上所有方法的查詢條件均為實體類record中的非空屬性。
MySqlMapper<T>中的方法如下:
-
/**
-
* 批量插入,支持批量插入的數據庫可以使用,例如MySQL,H2等,另外該接口限制實體包含`id`屬性並且必須為自增列
-
*/
-
public int insertList(List<T> recordList);
-
-
/**
-
* 插入數據,限制為實體包含`id`屬性並且必須為自增列,實體配置的主鍵策略無效
-
*/
-
public int insertUseGeneratedKeys(T record);
這兩個方法就比較坑了,限制了主鍵必須為自增列,如果是自己生成主鍵則不能使用該方法。
IdsMapper<T>中的方法如下:
-
/**
-
* 根據主鍵@Id進行查詢,多個Id以逗號,分割
-
* @param id
-
* @return
-
*/
-
List<T> selectByIds(String ids);
-
-
/**
-
* 根據主鍵@Id進行刪除,多個Id以逗號,分割
-
* @param id
-
* @return
-
*/
-
int deleteByIds(String ids);
這兩個方法就很好理解了,不再解釋。
ConditionMapper<T>中的方法如下:
-
/**
-
* 根據Condition條件進行查詢
-
*/
-
public List<T> selectByCondition(Object condition);
-
-
/**
-
* 根據Condition條件進行查詢
-
*/
-
public int selectCountByCondition(Object condition);
-
-
/**
-
* 根據Condition條件刪除數據,返回刪除的條數
-
*/
-
public int deleteByCondition(Object condition);
-
-
/**
-
* 根據Condition條件更新實體`record`包含的全部屬性,null值會被更新,返回更新的條數
-
*/
-
public int updateByCondition(T record, Object condition);
-
-
/**
-
* 根據Condition條件更新實體`record`包含的全部屬性,null值會被更新,返回更新的條數
-
*/
-
public int updateByConditionSelective(T record, Object condition);
傳入的Object condition應為tk.mybatis.mapper.entity.Condition,具體使用方法后續會說明。
ExampleMapper<T>中的方法如下:
-
/**
-
* 根據Example條件進行查詢
-
*/
-
public List<T> selectByExample(Object example);
-
-
/**
-
* 根據Example條件進行查詢,若有多條數據則拋出異常
-
*/
-
public T selectOneByExample(Object example);
-
-
/**
-
* 根據Example條件進行查詢總數
-
*/
-
public int selectCountByExample(Object example);
-
-
/**
-
* 根據Example條件刪除數據,返回刪除的條數
-
*/
-
public int deleteByExample(Object example);
-
-
/**
-
* 根據Example條件更新實體`record`包含的全部屬性,null值會被更新,返回更新的條數
-
*/
-
public int updateByExample(T record, Object example);
-
-
/**
-
* 根據Example條件更新實體`record`包含的不是null的屬性值,返回更新的條數
-
*/
-
public int updateByExampleSelective(T record, Object example);
同上,傳入的Object example應為tk.mybatis.mapper.entity.Example,具體使用方法后續會說明。
3、實現類
各個方法的實現大同小異,此處以一個為例:
-
public
abstract
class BaseServiceImpl<T> implements BaseService<T> {
-
-
protected abstract BaseMapper<T> getMapper();
-
-
@Override
-
public int insert(T record) {
-
return getMapper().insert(record);
-
}
-
}
getMapper()方法需要在具體的業務代碼中實現,其余不再贅述。
三、使用方法
1、tk.mybatis.mapper.common.BaseMapper<T>, IdsMapper<T>, MySqlMapper<T>內方法使用說明:
從接口中我們可以看到傳入的方法基本均為T record,即實體類,查詢時會根據實體類中的屬性值進行where語句構建,查詢條件為等號,這里沒有什么特殊的。
不過需要注意,若傳入實例化的實體類,且其中包含int屬性,則構建sql語句中會將該屬性包含進去,如下代碼:
-
@Data
-
@EqualsAndHashCode(callSuper=
false)
-
@Table(name=
"t_sys_user_role")
//設置數據庫中表名字
-
public
class UserRole extends BaseEntity{
-
-
/**
-
* 主鍵
-
*/
-
@Column(name =
"f_id")
-
@Id
-
private String fId;
-
-
/**
-
* 類型(1.系統管理員)
-
*/
-
@Column(name =
"f_type")
-
private
int fType;
-
}
-
-
@RunWith(SpringJUnit4ClassRunner.class)
-
@SpringBootTest(classes=StartApp.class)
-
@WebAppConfiguration
-
public
class TestService {
-
-
@Autowired
-
private IUserRoleService userRoleService;
-
-
@Test
-
public void testUserRole() throws Exception{
-
UserRole userRole =
new UserRole();
-
List<UserRole> userRoleList = userRoleService.select(userRole);
-
System.out.println(userRoleList);
-
}
-
}
從日志中我們可以看到:
-
2018
-08
-12
17:
31:
10.768 DEBUG
12172 --- [ main] com.capol.mapper.UserRoleMapper.
select : ==> Preparing:
SELECT f_id,f_user_id,f_type,f_status,f_description,f_creator_id,f_create_time,f_last_updator_id,f_last_update_time
FROM t_sys_user_role
WHERE f_type = ?
-
2018
-08
-12
17:
31:
10.776 DEBUG
12172 --- [ main] com.capol.mapper.UserRoleMapper.
select : ==> Parameters:
0(
Integer)
-
2018
-08
-12
17:
31:
10.787 DEBUG
12172 --- [ main] com.capol.mapper.UserRoleMapper.
select : <== Total:
0
很明顯,這不是我們要的結果。將int類型改為Integer類型即可,或使用Condition、Example方法進行查詢。
2、ExampleMapper<T>內方法使用說明:
所有方法均需要傳入tk.mybatis.mapper.entity.Example,
首先進行實例化:
-
Example example =
new Example(UserRole.class);
//實例化
-
Example.Criteria criteria = example.createCriteria();
Criteria是Example中的一個內部類,在最終sql構建時以括號呈現,Criteria里帶了較多構建查詢條件的方法,如
andEqualTo(String property, Object value),
orEqualTo(String property, Object value),
andGreaterThan(String property, Object value),
orGreaterThan(String property, Object value)
傳入的property為實體類中的屬性名,非數據度字段名。
舉例說明,如orEqualTo(String property, Object value),代碼如下:
-
Example example =
new Example(UserRole.class);
//實例化
-
Example.Criteria criteria = example.createCriteria();
-
criteria.orEqualTo(
"fUserId",
"15693a6e509ee4819fcf0884ea4a7c9b");
-
criteria.orEqualTo(
"fUserId",
"15ccaf3e89376f7b109eec94d10b7988");
-
List<UserRole> userRoleList = userRoleService.selectByExample(example);
最終的where語句則為:
( f_user_id = "15693a6e509ee4819fcf0884ea4a7c9b" or f_user_id = "15ccaf3e89376f7b109eec94d10b7988" )
其余方法同理。
其中andCondition(String condition)方法支持手寫條件,傳入的字符串為最終的查詢條件,如:length(f_user_id)<5
以及likeTo()的方法是不帶百分號%的,需要自己對傳入參數進行構建(加左like或者右like等)。
其余方法自行見源碼,不再贅述。
3、ConditionMapper<T>內方法使用說明:
所有方法均需要傳入tk.mybatis.mapper.entity.Condition,Condition實際上繼承自tk.mybatis.mapper.entity.Example,
源碼中只有三個方法:
-
public Condition(Class<?> entityClass) {
-
super(entityClass);
-
}
-
-
public Condition(Class<?> entityClass, boolean exists) {
-
super(entityClass, exists);
-
}
-
-
public Condition(Class<?> entityClass, boolean exists, boolean notNull) {
-
super(entityClass, exists, notNull);
-
}
說實話我也不知道這樣做有什么意義,望哪位大神指教一下。
boolean exists, boolean notNull這兩個參數的含義為:
若exists為true時,如果字段不存在就拋出異常,false時,如果不存在就不使用該字段的條件,
若notNull為true時,如果值為空,就會拋出異常,false時,如果為空就不使用該字段的條件
其使用方法與Example類似:
-
Condition condition =
new Condition(UserRole.
class);
-
Criteria criteria = condition.createCriteria();
-
criteria.orEqualTo(
"fUserId",
"15693a6e509ee4819fcf0884ea4a7c9b");
-
criteria.orEqualTo(
"fUserId",
"15ccaf3e89376f7b109eec94d10b7988");
-
List<UserRole> userRoleList = userRoleService.selectByCondition(condition);
畢竟是繼承自Example。
4、Example.and()/or()和Condition.and()/or()方法說明:
兩個都一樣,我就挑一個說吧。
實例化方法跟上邊略有不同:
-
Condition condition = new Condition(UserRole.
class);
-
//Criteria criteria1 = condition.createCriteria();
-
Criteria criteria1 = condition.
and();
上邊說了,每個Criteria在最終結果中以括號形式展現,此時and()方法則表示 and (Criteria中的條件),or()方法則表示 or (Criteria中的條件),默認createCriteria()等同於and(),測試結果如下:
2018-08-12 18:23:11.805 DEBUG 13760 --- [ main] c.c.m.UserRoleMapper.selectByCondition : ==> Preparing: SELECT f_id,f_user_id,f_type,f_status,f_description,f_creator_id,f_create_time,f_last_updator_id,f_last_update_time FROM t_sys_user_role WHERE ( f_user_id = ? and f_user_id = ? ) or ( f_description = ? or f_description = ? )
原文地址:https://blog.csdn.net/q564495021/article/details/81607515