Spring Data JDBC全解析
一、JPA背景
早期的JPA的特性是懶加載和關(guān)聯(lián)查詢,一下能查出所有的關(guān)聯(lián)信息,但我們開發(fā)者在查詢SQL的時(shí)候往往只需要某幾個(gè)字段,而JPA甚至關(guān)聯(lián)表的所有字段查詢出來,如果不需要那么多message,那么查詢的性能會大大降低。
Spring官網(wǎng)為此提供了另一個(gè)解決方案——spring-data-jdbc, 另一種形式的Java持久化的API工具集,相比JPA來講,更簡單,更高效,沒有session, 一次查詢查詢出指定的結(jié)果,沒有多余數(shù)據(jù),Spring 官網(wǎng)提供了為什么使用它的理由:
1. If you load an entity, SQL statements get run. Once this is done, you have a completely loaded entity. No lazy loading or caching is done.
2. If you save an entity, it gets saved. If you do not, it does not. There is no dirty tracking and no session.
3. There is a simple model of how to map entities to tables. It probably only works for rather simple cases. If you do not like that, you should code your own strategy. Spring Data JDBC offers only very limited support for customizing the strategy with annotations.
簡單總結(jié)就是: 沒有攔截在和緩存,每次執(zhí)行完的SQL得到的就是一個(gè)指定想要的完整實(shí)體,沒有關(guān)聯(lián)的查詢或更新操作,沒有session, 更簡單、高效。
spring-data-jdbc相比mybatis有哪些好處
其實(shí)現(xiàn)在有更好的中間件mybatis和相關(guān)插件能夠幫助我們更好的執(zhí)行sql,spring-data-jdbc和mybatis同樣是基于spring開發(fā)出來的框架,那么他們優(yōu)勢和差別分別是什么
- mybatis: sql與mapper層分離,開發(fā)者可以編寫復(fù)雜的SQL以及動態(tài)SQL,適合查詢復(fù)雜的場景,能夠在xml文件里統(tǒng)一管理SQL文件,缺點(diǎn)是有些場景下需要編寫復(fù)雜的SQL。
- spring-data-jdbc: 無須配置和加載xml映射文件, 簡化開發(fā),對于單表查詢多的場景下,使用spring-boot-data-jdbc會比mybatis更加簡單,另外spring-boot-data-jdbc能夠與mybatis做集成,使用更加靈活,支持配置SqlSessionFactoryBean。缺點(diǎn)是: 復(fù)雜的業(yè)務(wù)系統(tǒng)和場景下,復(fù)雜的SQL難以維護(hù)。
Spring-data-jdbc在簡單業(yè)務(wù)場景下的表現(xiàn)會比myabtis更加方便、好用。
二、Spring Boot 整合Spring data JDBC
先看一下目錄結(jié)構(gòu):
jdbc ├─ JdbcApplication.java // main方法 ├─ config │ └─ DataSourceConfig.java // 配置數(shù)據(jù)源,采用druid ├─ controller │ └─ UserController.java // controler ├─ model │ └─ User.java // 實(shí)體類 ├─ repository // dao層,與數(shù)據(jù)庫連接層 │ ├─ UserCrudRepository.java │ └─ UserPageRepository.java ├─ service // 服務(wù)層 │ └─ UserService.java └─ util
啟動類的@EnableJdbcRepositories(basePackages = “org.spring.data.jdbc”) 注解也可以放在配置類上。

1. 配置數(shù)據(jù)源
數(shù)據(jù)庫使用mysql,那么首推alibaba的druid數(shù)據(jù)源,druid是國內(nèi)數(shù)據(jù)庫連接性能表現(xiàn)最好且功能強(qiáng)大數(shù)據(jù)庫中間件,druid還有自帶的數(shù)據(jù)庫監(jiān)控工具,能夠監(jiān)控慢sql,sql執(zhí)行的動態(tài)還有預(yù)防sql注入攻擊等功能。
添加pom依賴:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- alibaba druid數(shù)據(jù)源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.18</version>
</dependency>
<!--spring-data-jdbc-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>添加數(shù)據(jù)源配置:
server.port=8002 spring.datasource.url=jdbc:mysql://192.168.31.166:3306/my_shop?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai spring.datasource.username=root spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.jdbc.Driver
下載好jar包后,新建一個(gè)配置類DataSourceConfig:
package org.spring.data.jdbc.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jdbc.repository.config.AbstractJdbcConfiguration;
import org.springframework.data.jdbc.repository.config.EnableJdbcRepositories;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionManager;
import javax.sql.DataSource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@Configuration
@EnableJdbcRepositories(basePackages = "org.spring.data.jdbc")
public class DataSourceConfig extends AbstractJdbcConfiguration {
/**
* 采用阿里數(shù)據(jù)源druid
*
* @return
*/
@ConfigurationProperties("spring.datasource")
@Bean
DataSource dataSource() {
return new DruidDataSource();
}
/**
* Jdbc Template
* @param dataSource
* @return
*/
@Bean
NamedParameterJdbcOperations namedParameterJdbcOperations(DataSource dataSource) {
return new NamedParameterJdbcTemplate(dataSource);
}
/**
* 事務(wù)管理器
* @param dataSource
* @return
*/
@Bean
TransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}2. 配置Druid的admin后臺
Druid提供了一種直接重寫ServletRegistrationBean和FilterRegistrationBean的方式來生成admin后臺管理頁面和過濾器。
//配置Druid監(jiān)控
//admin后臺, 訪問地址: localhost:8002/druid/
@Bean
public ServletRegistrationBean statViewServlet() {
ServletRegistrationBean bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
Map<String, String> initParams = new HashMap<>();
initParams.put("loginUsername", "admin");
initParams.put("loginPassword", "admin");
initParams.put("allow", "localhost");
initParams.put("deny", "0.0.0.0");
bean.setInitParameters(initParams);
return bean;
}
//filter
@Bean
public FilterRegistrationBean webStatFilter() {
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
Map<String, String> initParams = new HashMap<>();
initParams.put("exclusions", "*.js,*.css,/druid/*");
bean.setInitParameters(initParams);
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}訪問地址: localhost:8002/druid, 即可進(jìn)入到admin后臺管理頁面,如下:

輸入配置的賬號admin,密碼admin即可進(jìn)入到首頁, 如下圖:

3. Spring-data-jdbc常用接口查詢策略
1)CrudRepository 增刪改查
我們可以通過繼承CrudRepository來定義基于Model的增刪改查操作, 也可以使用CrudRepository里提供對數(shù)據(jù)庫增、刪、改查操作的基本API。
@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {S save(S entity);
<S extends T> Iterable<S> saveAll(Iterable<S> entities); Optional<T> findById(ID id); boolean existsById(ID id); Iterable<T> findAll(); Iterable<T> findAllById(Iterable<ID> ids); long count(); void deleteById(ID id); void delete(T entity); void deleteAllById(Iterable< extends ID> ids); void deleteAll(Iterable< extends T> entities); void deleteAll();
}
自定義接口方法:
@Repository
public interface UserCrudRepository extends CrudRepository<User, String> {
User findUserById(Integer id);
@Query("select user_name as userName from sys_user where id = :id")
String findUserNameById(@Param("id") Integer id);
}spring-data-jdbc的方便好用、可擴(kuò)展性進(jìn)一步顯現(xiàn)出來了,如果想分頁查詢的話,Spring-data-jdbc提供了另外一個(gè)接口PagingAndSortingRepository,也可以使用@Query()注解支持原生的sql寫入,參數(shù)使用過@Param()注入,接收的時(shí)候按照順序接收,但要用 :id來標(biāo)記接收對應(yīng)的參數(shù)。
2) PagingAndSortingRepository 分頁排序
@NoRepositoryBean
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {
Iterable findAll(Sort sort);Page<T> findAll(Pageable pageable);}
同樣的該接口類似于CrudRepository接口的用法,可以使用自帶的api,也可以擴(kuò)展。
package org.spring.data.jdbc.repository;
import org.spring.data.jdbc.model.User;
import org.springframework.data.repository.PagingAndSortingRepository;
public interface UserPageRepository extends PagingAndSortingRepository<User,String> {
//按照id排序
}排序:提供了findAll()方法,Sort.Direction.ASC表示升序,Sort.Direction.DESC表示降序。
/**
* 按照指定字段排序,可以指定升序、降,0升序,1降序
*
* @param sortField 按照指定字段排序
* @param sortRule 排序規(guī)則
* @return
*/
public List<User> findUserBySort(String sortField, Integer sortRule) {
List<User> results = new ArrayList<>();
Iterable<User> userIterable = userPageRepository.findAll(Sort.by(sortRule == 0 ? Sort.Direction.ASC : Sort.Direction.DESC, sortField));
Iterator<User> userIterator = userIterable.iterator();
while (userIterator.hasNext()) {
results.add(userIterator.next());
}
return results;
}分頁:直接使用import org.springframework.data.domain.Pageable 類作為參數(shù)解析分頁的page和size就能實(shí)現(xiàn)一個(gè)簡單的分頁查詢。
public List<User> findUserByPage(Pageable page) {
return userPageRepository.findAll(page).getContent();
}
controller:
/**
* find all user by page
*/
@GetMapping("/findAllUser/by/page")
@ResponseBody
public List<User> findAllUserBySort(Pageable pageable) {
return userService.findUserByPage(pageable);
}
按照id降序排序查詢, 訪問:localhost:8002/api/user/findAllUser/by/sortsortRule=0&sortField=id,打印結(jié)果:
[
{
“id”:3,
“userName”:“zhangsan”
},
{
“id”:2,
“userName”:“zhangsan”
},
{
“id”:1,
“userName”:“bingbing”
}
]
到此這篇關(guān)于Spring Data JDBC全解析的文章就介紹到這了,更多相關(guān)spring data jdbc內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatis結(jié)果集映射與生命周期詳細(xì)介紹
Java程序結(jié)構(gòu)與常量變量難點(diǎn)解析
MyBatis-Plus雪花算法實(shí)現(xiàn)源碼解讀
老生常談Java虛擬機(jī)垃圾回收機(jī)制(必看篇)
基于EasyExcel實(shí)現(xiàn)百萬級數(shù)據(jù)導(dǎo)入導(dǎo)出詳解
Java為何需要平衡方法調(diào)用與內(nèi)聯(lián)
Spring?Security密碼解析器PasswordEncoder自定義登錄邏輯

