一、使用Mapper
BeetlSql支持Mapper,它可以將sql文件映射到一個interface接口。接口的方法名與sql文件的sqlid一一對應。接口必須實現BaseMapper接口(后面可以自定義一個Base接口),它提供內置的CRUD方法,如insert,unique,template,templateOne,updateById等。BaseMapper 具備數據庫常見的操作,接口只需要定義額外的方法與sqlid同名即可。例如:
public interface UserDao extends BaseMapper<User> {
List<User> select(String name);
}
上例中的select方法將會對應下面的md文件:
select
===
select * from user where name = #name#
如果使用的是JDK8,不必為參數提供名稱,自動對應。但必須保證java編譯的時候開啟-parameters選項。如果使用JDK8以下的版本,則可以使用@Param注解():
List<User> select(@Param("name") String name);
BeetlSql的mapper方法總會根據調用方法名字,返回值,以及參數映射到SQLManager相應的查詢接口,比如返回類型是List,意味著發起SQLManager.select 查詢,如果返回是一個Map或者Pojo,則發起一次selectSingle查詢,如果返回定義為List,則表示查詢實體,如果定義為List ,則對應的查詢結果映射為Long。定義好接口后,可以通過SQLManager.getMapper來獲取一個Dao的真正實現。
UserDao dao = sqlManager.getMapper(UserDao.class);
Mapper 對應的sql文件默認根據實體來確定,如實體是UserInfo對象,則對應的sql文件是userInfo.md(sql),可以通過@SqlResource 注解來指定Mapper對應的sql文件。例如:
@SqlResource("core.user")
public interface UserCoreDao extends BaseMapper<User> {
List<User> select(String name);
}
@SqlResource("console.user")
public interface UserConsoleDao extends BaseMapper<User> {
List<User> select(String name);
}
這樣,這倆個mapper分別訪問sql/core/user.md 和 sql/console/user.md
二、內置的CRUD
BaseMapper包含了內置的常用查詢,如下:
public interface BaseMapper<T> {
/**
* 通用插入,插入一個實體對象到數據庫,所有字段將參與操作,除非使用ColumnIgnore注解
* @param entity
*/
void insert(T entity);
/**
* (數據庫表有自增主鍵調用此方法)如果實體對應的有自增主鍵,插入一個實體到數據庫,設置assignKey為true的時候,將會獲取此主鍵
* @param entity
* @param autDbAssignKey 是否獲取自增主鍵
*/
void insert(T entity, boolean autDbAssignKey);
/**
* 插入實體到數據庫,對于null值不做處理
* @param entity
*/
void insertTemplate(T entity);
/**
* 如果實體對應的有自增主鍵,插入實體到數據庫,對于null值不做處理,設置assignKey為true的時候,將會獲取此主鍵
* @param entity
* @param autDbAssignKey
*/
void insertTemplate(T entity,boolean autDbAssignKey);
/**
* 批量插入實體。此方法不會獲取自增主鍵的值,如果需要,建議不適用批量插入,適用
* <pre>
* insert(T entity,true);
* </pre>
* @param list
*/
void insertBatch(List<T> list);
/**
* (數據庫表有自增主鍵調用此方法)如果實體對應的有自增主鍵,插入實體到數據庫,自增主鍵值放到keyHolder里處理
* @param entity
* @return
*/
KeyHolder insertReturnKey(T entity);
/**
* 根據主鍵更新對象,所以屬性都參與更新。也可以使用主鍵ColumnIgnore來控制更新的時候忽略此字段
* @param entity
* @return
*/
int updateById(T entity);
/**
* 根據主鍵更新對象,只有不為null的屬性參與更新
* @param entity
* @return
*/
int updateTemplateById(T entity);
/**
* 根據主鍵刪除對象,如果對象是復合主鍵,傳入對象本生即可
* @param key
* @return
*/
int deleteById(Object key);
/**
* 根據主鍵獲取對象,如果對象不存在,則會拋出一個Runtime異常
* @param key
* @return
*/
T unique(Object key);
/**
* 根據主鍵獲取對象,如果對象不存在,返回null
* @param key
* @return
*/
T single(Object key);
/**
* 根據主鍵獲取對象,如果在事物中執行會添加數據庫行級鎖(select * from table where id = ? for update),如果對象不存在,返回null
* @param key
* @return
*/
T lock(Object key);
/**
* 返回實體對應的所有數據庫記錄
* @return
*/
List<T> all();
/**
* 返回實體對應的一個范圍的記錄
* @param start
* @param size
* @return
*/
List<T> all(int start,int size);
/**
* 返回實體在數據庫里的總數
* @return
*/
long allCount();
/**
* 模板查詢,返回符合模板得所有結果。beetlsql將取出非null值(日期類型排除在外),從數據庫找出完全匹配的結果集
* @param entity
* @return
*/
List<T> template(T entity);
/**
* 模板查詢,返回一條結果,如果沒有,返回null
* @param entity
* @return
*/
<T> T templateOne(T entity);
List<T> template(T entity,int start,int size);
/**
* 符合模板得個數
* @param entity
* @return
*/
long templateCount(T entity);
/**
* 單表的基于模板查詢的翻頁
* @param query
* @return
*/
void templatePage(PageQuery<T> query);
/**
* 執行一個jdbc sql模板查詢
* @param sql
* @param args
* @return
*/
List<T> execute(String sql,Object... args);
/**
* 執行一個更新的jdbc sql
* @param sql
* @param args
* @return
*/
int executeUpdate(String sql,Object... args );
SQLManager getSQLManager();
/**
* 返回一個Query對象
* @return
*/
Query<T> createQuery();
/**
* 返回一個LambdaQuery對象
* @return
*/
LambdaQuery<T> createLambdaQuery();
}
三、sqlid查詢
對于sqlId 是查詢語句,返回值可以是任何類型,Mapper將視圖將查詢結果映射到定義的類型上,如下是一些常見例子:
public interface UserDao extends BaseMapper<User> {
// 使用"user.getCount"語句,無參數
public int getCount();
//使用"user.findById"語句,參數是id,返回User對象
public User findById(@Param("id") Integer id);
//使用"user.findById"語句,參數是id,返回User對象
public List<User> findByName(@Param("name") String name);
//使用user.findTop10OfIds語句, 查詢結果映射為Long,比如“select id from user limit 10
public List<Long> findTop10OfIds();
//返回一個Map,不建議這么做,最好返回一個實體,或者實體+Map的混合模型(參考BeetlSql模型)
public List<Map<String,Object> findUsers(@Param("name") String name,@Param("departmentId") departmentId)
}
Mapper 查詢有一個例外,如果第一個參數是一個JavaBean(即非java內置對象),則默認為是_root對象,因此如下倆個接口定義是等價的:
public List query(User template);
public List query2(@Param("_root") User template)
如果需要查詢指定范圍內的結果集,可以使用@RowStart,@RowSize,將指示Mapper發起一次范圍查詢:
pulic List<User> selectRange(User data,Date maxTime,@RowStart int start,@RowSize int size)
如上查詢語句,類似這樣調用了SQLManager:
Map paras = new HashMap();
paras.put("_root",data);
paras.put("maxTime",maxTime);
List<User> list = sqlManager.select("user.selectRanage",User.class,paras,start,size);
四、PageQuery查詢
PageQuery查詢需要提供PageQuery參數以讓Mapper理解為PageQuery查詢,如下倆個是等價的:
public void queryByCondtion(PageQuery query);
public PageQuery queryByCondtion(PageQuery query);
可以添加額外參數,但PageQuery 必須是第一個參數,如:
public void queryByCondtion(PageQuery query,Date maxTime);
這類似如下SQLManager調用:
query.setPara("maxTime",maxTime);
sqlManager.pageQuery("user.queryByCondtion",User.class,query)
也可以在方法中提供翻頁參數來實現翻頁查詢,這時候返回值必須是PageQuery,如下:
public PageQuery queryByCondtion(int pageNumber,int pageSize,String name);
五、更新語句
更新語句返回的結果可以是void,或者int,如果是批量更新,則可以返回int[]:
public int updaetUser(int id,String name);
public int updateUser(User user);
public int[] updateAll(List<User> list);
BeetlSql通常根據返回值是int或者int[] 來判斷是否是更新還是批量更新,如果沒有返回值,會進一步判斷第一個參數是否是集合或者數組,比如:
public void updateAllByUser(List<User> list);
public void updateAllByIds(List<Integer> list);
六、插入語句
插入語句同更新語句,唯一不同的是插入語句有時候需要獲取自增序列值,這時候使用KeyHolder作為返回參數:
public KeyHolder insertSql(User user);
使用JDBC SQL 可以通過@Sql注解直接在java中使用較為簡單的sql語句,如下:
@Sql(value=" update user set age = ? where id = ? ")
public void updateAge(int age,int id);
@Sql(value="select id from user where create_time<?")
public List<Long> selectIds(Date date)
此時方法參數與"?" 一一對應 也可以使用@Sql翻頁,這要求方法參數前倆個必須是int或者long,返回結果使用PageQuery定義:
@Sql(value="select * from user where create_time<?")
public PageQuery selectUser(int pageNumber,int pageSize,Date date)
七、Mapper中的注解
上面已經了解了@Param注解,用于申明參數名字,如果使用jdk8,且打開了編譯選項parameters,則可以去掉@Param注解。@RowStart和 @RowSize,用于查詢中的范圍查詢。 @Sql 注解則用于在java中構造一個簡短的jdbc sql語句。@SqlStatment注解可以對接口參數進一步說明,他有如下屬性:
1、type,用于說明sqlid是何種類型的語句,默認為auto,BeetlSql將會根據sqlId對應的Sql語句判斷是否是查詢,還是修改語句等,通常是根據sql語句的第一個詞來判斷,如果是select,表示查詢,如果是insert,表示新增,如果update,drop,則是更新。如果Sql模板語句第一個詞不包含這些,則需要用type做說明。如下是一個需要用到type的情況:
selectUsers
===
#use("otherSelect")# and status=1;
因為beetlsql無法根據第一個單詞確定操作類型,因此必須使用type=SqlStatementType.SELECT,來說明。
2、params ,可以不用在接口參數上使用@Param,而直接使用params屬性,如下是等價的:
@SqlStatement(params="name,age,_st,_sz")
public List<User> queryUser( String name, Integer age,int start, int size);
public List<User> queryUser( @Param(name) String name, @Param(age) @RowStart Integer age,int start, @RowSize int size);
_st,_sz 同@RowStart和@RowSize。
八、使用接口默認方法
如果使用JDK8,則可以在mapper中添加默認方法,有利于重用:
public interface SysResourceDao extends BaseMapper<SysResource> {
void page(PageQuery<SysResource> query);
default List<SysResource> listChildren(Integer resourceId) {
return createLambdaQuery()
.andNotEq(SysResource::getStatus, 1)
.andEq(SysResource::getPid, resourceId)
.select();
}
}
本站文章版權歸原作者及原出處所有 。內容為作者個人觀點, 并不代表本站贊同其觀點和對其真實性負責,本站只提供參考并不構成任何投資及應用建議。本站是一個個人學習交流的平臺,網站上部分文章為轉載,并不用于任何商業目的,我們已經盡可能的對作者和來源進行了通告,但是能力有限或疏忽,造成漏登,請及時聯系我們,我們將根據著作權人的要求,立即更正或者刪除有關內容。本站擁有對此聲明的最終解釋權。