Spring data jpa是Spring使用jpa的組件。采用Hibernate實(shí)現(xiàn)jpa能力。但是比自行Spring和Hibernate整合使用方便很多。
引入組件
在pom.xml中加入組件,這里連接MySQL數(shù)據(jù)庫(kù),所以引入mysql-connector-java
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
創(chuàng)建模型
jpa講究的是面向?qū)ο蟮乃季S,降低了數(shù)據(jù)庫(kù)的可見(jiàn)性。它可以完全不去寫(xiě)SQL語(yǔ)句完成對(duì)數(shù)據(jù)庫(kù)中數(shù)據(jù)的增刪改查操作。一個(gè)數(shù)據(jù)模型對(duì)應(yīng)一個(gè)數(shù)據(jù)表。我們對(duì)數(shù)據(jù)的操作關(guān)心對(duì)這個(gè)對(duì)象的業(yè)務(wù)過(guò)程。
創(chuàng)建一個(gè)模型,名稱為Account。這個(gè)對(duì)象是用于描述系統(tǒng)中的賬戶。創(chuàng)建名稱為com.biboheart.demos.domain的package,在此package中新建類Account。如下:
package com.biboheart.demos.domain;
import lombok.Data;
import javax.persistence.*;
@Data
@Entity // 表示這是一個(gè)jpa模型
@Table(name = "bh_account") // 表示對(duì)應(yīng)數(shù)據(jù)表bh_account
public class Account {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id; // ID
private String sn; // 賬戶編號(hào)
private String username; // 用戶名
private String mobile; // 手機(jī)號(hào)
private String password; // 密碼
private Long createTime; // 創(chuàng)建時(shí)間
}
創(chuàng)建接口
創(chuàng)建模型后,執(zhí)行數(shù)據(jù)增刪查改操作。spring data jpa提供了約定的方式來(lái)簡(jiǎn)化使用。它約定,繼承JpaRepository的接口,在接口中定義的函數(shù)名稱就可以執(zhí)行不同的數(shù)據(jù)操作。復(fù)雜的可以用注解來(lái)完成。如findBySn函數(shù),就可以實(shí)現(xiàn)用戶sn匹配查找賬戶。通過(guò)這樣約定的情況下使用spring data jpa,不需要實(shí)現(xiàn)這個(gè)接口。寫(xiě)了這個(gè)接口,就可以將這個(gè)接口注入到業(yè)務(wù)中使用。
在com.biboheart.demos.repository中創(chuàng)建AccountRepository。如下代碼:
package com.biboheart.demos.repository;
import com.biboheart.demos.domain.Account;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface AccountRepository extends JpaRepository<Account, Integer>, JpaSpecificationExecutor<Account> {
Account findBySn(String sn);
}
在業(yè)務(wù)代碼中如下方法注入,就可以通過(guò)accountRepository.findBySn(sn)查找匹配到sn的用戶。
@Autowired
private AccountRepository accountRepository;
配置連接
這時(shí)候,jpa并不知道Account對(duì)應(yīng)的是哪個(gè)數(shù)據(jù)庫(kù)的表。要配置數(shù)據(jù)庫(kù)連接。在application.yml中配置spring.datasource,spring boot中項(xiàng)目中許多框架就可以自動(dòng)得到數(shù)據(jù)庫(kù)的連接參數(shù)。配置spring.jpa設(shè)置spring data jpa的屬性。
server:
port: 80
spring:
profiles:
active: dev
resources:
static-locations: file:/usr/local/bhhello/static, classpath:/static/
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/bh_springbootdemo?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false&autoReconnect=true
username: root
password: root
jpa:
database: MYSQL
database-platform: org.hibernate.dialect.MySQL5Dialect
show-sql: false
hibernate:
ddl-auto: update
properties:
hibernate:
format_sql: false
custom:
name: bhhello-app
測(cè)試連接
在com.biboheart.demos.service中創(chuàng)建接口AccountService,在com.biboheart.demos.service.impl中創(chuàng)建實(shí)現(xiàn)AccountServiceImpl。代碼如下:
package com.biboheart.demos.service;
import com.biboheart.demos.domain.Account;
public interface AccountService {
/**
* 保存賬戶
* @param account 賬戶對(duì)像
* @return 保存后的賬戶對(duì)像,如果保存失敗返回null
*/
Account save(Account account);
/**
* 查詢賬戶
* @param sn 賬戶編號(hào)
* @return 查詢結(jié)果,賬戶對(duì)像
*/
Account load(String sn);
}
實(shí)現(xiàn)(這里未做容錯(cuò)處理):
package com.biboheart.demos.service.impl;
import com.biboheart.brick.utils.CheckUtils;
import com.biboheart.demos.domain.Account;
import com.biboheart.demos.repository.AccountRepository;
import com.biboheart.demos.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.UUID;
@Service
public class AccountServiceImpl implements AccountService {
// 注入account數(shù)據(jù)庫(kù)訪問(wèn)對(duì)象
@Autowired
private AccountRepository accountRepository;
@Override
public Account save(Account account) {
if (CheckUtils.isEmpty(account.getSn())) {
// 生成賬戶編號(hào)
String sn = UUID.randomUUID().toString().replace("-", "").toUpperCase();
while (null != accountRepository.findBySn(sn)) {
sn = UUID.randomUUID().toString().replace("-", "").toUpperCase();
}
account.setSn(sn);
}
account = accountRepository.save(account);
return account;
}
@Override
public Account load(String sn) {
Account account = accountRepository.findBySn(sn);
return account;
}
}
開(kāi)放兩個(gè)API,實(shí)現(xiàn)創(chuàng)建賬戶與查詢賬戶的功能。在com.biboheart.demos.controller中創(chuàng)建AccountController類。
package com.biboheart.demos.controller;
import com.biboheart.brick.model.BhResponseResult;
import com.biboheart.demos.domain.Account;
import com.biboheart.demos.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AccountController {
@Autowired
private AccountService accountService;
@RequestMapping(value = "/public/userapi/account/save", method = {RequestMethod.POST, RequestMethod.GET})
public BhResponseResult<?> save(Account account) {
account = accountService.save(account);
return new BhResponseResult<>(0, "success", account);
}
@RequestMapping(value = "/public/userapi/account/load", method = {RequestMethod.POST, RequestMethod.GET})
public BhResponseResult<?> load(String sn) {
Account account = accountService.load(sn);
return new BhResponseResult<>(0, "success", account);
}
}
為了方便測(cè)試,配置SecurityConfiguration,使"/public"開(kāi)頭的api不需要安全認(rèn)證。
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests()
.antMatchers("/", "/home", "/mobileCodeLogin", "/public/**").permitAll() // 這三個(gè)目錄不做安全控制
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")// 自定義的登錄頁(yè)面
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/");
http.addFilterBefore(mobileCodeAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
// @formatter:on
}



結(jié)尾
這章中,通過(guò)spring data jpa對(duì)數(shù)據(jù)庫(kù)進(jìn)行創(chuàng)建表,增加數(shù)據(jù),查詢數(shù)據(jù)的操作。從頭到尾沒(méi)有使用SQL語(yǔ)句。除了配置文件中配置了數(shù)據(jù)庫(kù)連接參數(shù),業(yè)務(wù)過(guò)程與java程序的面向?qū)ο蟛僮鳠o(wú)異。