boot jpa mysql postman spring_听说过spring-data-jdbc么?来个最佳实践
本文的完整示例代碼,見github倉庫。小q只在文中介紹最關鍵的代碼塊。
https://github.com/yuanluoji/purestart-springboot-data-jdbc很多人知道Mybatis,知道Jpa,但對2019年新誕生的一門技術知之甚少。那就是:spring-data-jdbc。這個標題起的很普通,但是內容絕對是最新的。
注意我們這里說的是data-jdbc,而不是普通的jdbc。它擁有了類似jpa的一些特性,比如能夠根據方法名推導出sql,基本的CRUD等,也擁有了寫原生sql的能力。
最為關鍵的是,它非常的清爽,不需要依賴hibernte或者jpa。
千呼萬喚始出來,使用了一下,真是驚艷。它們的關系可以看下面這張圖。
可以看到spring-data-jdbc是和spring-data-jpa一樣,同屬于spring-data系列的。下面我們就來實踐一把,來看一下它的最佳實踐。
1. 配置準備工作
創建好Springboot項目之后,需要加入spring-data-jdbc的依賴。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jdbc</artifactId> </dependency>為了方便演示,我這里使用的是h2數據庫。可以在springboot中配置開啟它的web配置端。
h2:console:enable: truepath: /h2-consolesettings:trace: trueweb-allow-others: true啟動之后,就可以通過下面的地址訪問h2的console。
可以看到里面有一張叫做goods_basic的表。它是怎么創建進去的呢?先來看一下我們的datasource配置。
spring:datasource:driver-class-name: org.h2.Driverurl: jdbc:h2:mem:test;MODE=MYSQL;CASE_INSENSITIVE_IDENTIFIERS=TRUE;schema: classpath:sql/h2/schema.sql#data: classpath:sql/h2/data.sql其中, spring.datasource.schema所指定的sql文件,將會在項目啟動的時候,自動執行,這當然也是有AutoConfigure來完成的。來看一下我們的建表語句。
CREATE TABLE `goods_basic` (`id` int unsigned NOT NULL AUTO_INCREMENT,`code` varchar(255) NOT NULL DEFAULT '' COMMENT '編碼,不可重復;',`barcode` varchar(255) NOT NULL COMMENT '69開頭的13位標準碼',`short_name` varchar(255) NOT NULL COMMENT '商品名稱',`photos` json DEFAULT NULL COMMENT '商品圖片',`properties` json NOT NULL COMMENT '商品屬性,或者規格',`unit` varchar(8) NOT NULL COMMENT '單位;最多8個字節',`state` tinyint NOT NULL DEFAULT '1',`created` datetime NOT NULL COMMENT '創建時間',`modified` datetime NOT NULL COMMENT '更新時間',`version` bigint NOT NULL DEFAULT '0' COMMENT '樂觀鎖版本號',PRIMARY KEY (`id`),UNIQUE KEY `idx_account_role` (`code`,`barcode`) USING BTREE ) ;可以看到是徹頭徹尾的mysql語法。通過在h2里面指定MODE=MYSQL屬性,就可以把h2切換到mysql的語法。雖然h2在項目實際運行中感覺總是差那么一點意思,但對于測試來說,不得不說是個好工具。
到此為止,我們的準備工作就完成了,可以看到就是普通的datasource配置,簡單的很。
2.如何啟用spring-data-jdbc?
由于我們在前面引入的是starter的jar包,那就代表一些配置某人就在后臺完成了。下面來看一下,創建一個Dao(Repository),是有多簡單。
沒錯,我們只需要繼承PagingAndSortingRepository或者CrudRepository,就可以了,和jpa的一樣。
看一下上面的路徑,和jpa和jdbc是沒什么關系的,這就是spring-data抽象層的強大之處。
看一下我下面定義的這個dao,它實際上表現了常見的四種書寫方式。
/*** Copyright (c) 2020. All Rights Reserved.* @author yuanluoji* @date 2020/10/16*/ public interface GoodsBasicRepository extends PagingAndSortingRepository<GoodsBasic, Integer>,Complex<GoodsBasic> {List<GoodsBasic> findByCode(String code);@Query("select * from goods_basic where code=:code")List<GoodsBasic> findByCode2(String code); }2.1 默認的CRUD
當你繼承了CrudRepository這個接口,就默認已經有了CRUD的能力,你可以調用save,findAll等方法,直接獲取對實體的讀寫,無需再做任何映射。
這比MyBatis還要簡單方便,因為MyBatis你要不的不上一個MyBatisPlus才能得到相同的功能。
當你繼承了PagingAndSortingRepository接口,除了擁有CRUD,還擁有了分頁的功能。
2.2 根據方法名直接查詢
有一段時間,使用jpa,可以直接根據規則寫方法名,不用寫任何SQL,就可以完成查詢功能。這個現在在jdbc中也有了。
代碼中的findByCode方法,意思就是根據code,來查詢當前實體。這個過程將被翻譯成:
select * from goods_basic where code = :code我們無需多些任何sql。下面,就是一張基本的映射表。 這可都是標準sql哦,都可以在方法名中完成。
2.3 使用Query注解
@Query("select * from goods_basic where code=:code")List<GoodsBasic> findByCode2(String code);如果條件很多,這個方法名將會變得很長很長。在service層調用的時候你會一直喊臥槽!
這種復雜查詢語句,你可能需要使用Query注解來完成。寫在接口里的方法,此時將失去語意表達的意義。你可以使用任意的方法名,只需要把你的sql寫在注解里就可以了。
2.4 靈活的自定義
但對于想要靈活的控制sql行為的應用來說,上面這幾種方式就不行了。
比如,根據輸入條件的有無,做一些邏輯判斷。做一些類似mybatis的動態sql,或者使用StringBuilder來拼接一些sql。
注意我們的基礎Dao,繼承了一個接口,叫做Complex。spring-data-jdbc約定,這個接口的實現,放在ComplexImpl中,否則就會報錯。所以,這又是一個約定所實現的魔法。
我們定定義了一個test方法,期望通過傳入的code獲取一個列表
為了支持這種自定義查詢,我做了一個基類。里面注入了一個jdbc的模版類,還注入了一個JdbcAggregateOperations。
public abstract class BaseRepository {/*** 高度封裝的JDBC操作,可直接保存實體*/@Getter@Autowiredprivate JdbcAggregateOperations operations;/*** 普通命名的JDBC查詢和操作,可使用 {@link org.springframework.jdbc.core.BeanPropertyRowMapper}* 完成高級自動裝配,可自動完成駝峰和下劃線的自動映射*/@Getter@Autowiredprivate NamedParameterJdbcTemplate template; }來看一下我們的實現類。
public class ComplexImpl<T> extends BaseRepository implements Complex<T> {@Overridepublic List<T> test(String code) {StringBuilder sb = new StringBuilder("select * from goods_basic");Map params = new HashMap();if (!StringUtils.isEmpty(code)) {sb.append(" where code=:code");params.put("code", code);}List x = getTemplate().query(sb.toString(), params, new BeanPropertyRowMapper<>(GoodsBasic.class));return x;} }使用BeanPropertyRowMapper,就可以避免繁瑣的屬性拷貝,代碼變的非常清爽。
3. 實體配置
很多時候,實體有許多的通用屬性。這就需要抽取出來,在外面進行自定義。下面是我定義的一個基本的實體。包含id、創建愛你更新時間以及一個樂觀鎖版本號。這里的Id注解是org.springframework.data.annotation.Id,而不是javax的。
里面的created和modified字段,如果忘了寫怎么辦?難道要寫一個過濾器么?
不需要那么麻煩,我們可以追加一個callback。
下面的代碼,就是一個自動添加更新時間的例子。非常的好用。
@Configuration public class DataJdbcConfiguration extends AbstractJdbcConfiguration {@Beanpublic BeforeSaveCallback<AbstractEntity> absEntityBeforeSet() {return (entity, aggregateChange) -> {entity.setModified(new Date());return entity;};} }4. 小結
spring-data-jdbc是一個比較新的技術,現在的實踐文章還是很少。小Q在這里嘗試了一個語句的四種寫法,對此還是深有感慨的。
現在的技術框架,背后做了很多工作,靠約定實現了很多功能。我來發表一下對于這些sql寫作方式的見解。
1.CRUD方式
這個很簡單,在不同的ORM框架下遷移也很方便,如果沒有其他必要,建議只需要繼承一個接口類就可以了。2.根據方法名查詢
這個在參數比較少的時候,比較推薦,因為很清晰,也能在jpa之間進行切換。3.使用Query
對于稍微復雜的sql,建議使用這種方式。和jpa的寫法一樣,jpa中開啟nativeSQL,和它的效果是一樣的。4.靈活自定義
這個約定方式不錯,適合非常復雜的業務邏輯場景。5.QueryDSL
querydsl作為一門通用的查詢語言,用在Spring data jdbc上,也是可以的。但它要生成一些額外的代碼,個人比較有潔癖,暫未使用。
可以說,有了sping-data-jdbc,又不需要ORM去給你做什么緩存,用起來真是爽呆了。
作者:小姐姐味道
鏈接:https://juejin.im/post/6887110115959242759
來源:掘金
總結
以上是生活随笔為你收集整理的boot jpa mysql postman spring_听说过spring-data-jdbc么?来个最佳实践的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ad20如何导入库_一文看懂如何使用(P
- 下一篇: 5地图组件 uni_uni-app学习笔