使用Gradle構建SpringBoot工程系列:第八篇:使用spring-data-jpa 實現資料持久化
本篇文章是SpringBoot 系列文章的第八篇文章,由於本人工作原因,中斷了一段時間,接下來的一段時間裡,將陸續更新本系列的其他文章,迴歸Spring Boot技術體系,記錄本人學習和使用Gradle構建spring Boot工程的過程、技術要點以及在過程中遇到的各種問題,歡迎廣大程式猿共同關注學習,也歡迎大家提出自己的寶貴意見,知識在交流中碰撞,技術在交流中提升!
Spring Data JPA
是Spring Data系列的一部分,可以輕鬆實現基於JPA的資料持久化操作,旨在通過提供通用介面減少持久層的編碼量,提高程式碼質量,降低程式碼和SQL的維護成本,避免SQL注入等安全風險。作為開發人員只需編寫Repostitory介面,Spring將自動提供實現資料庫讀寫
Repository的概念
在Spring中有Repository的概念,repository原意指的是倉庫,即資料倉庫的意思。Repository居於業務層和資料層之間,將兩者隔離開來,在它的內部封裝了資料查詢和儲存的邏輯。這樣設計的好處有兩個:
- 降低層級之間的耦合:更換、升級ORM引擎(Hibernate)並不會影響業務邏輯
- 提高測試效率:如果在測試時能用Mock資料物件代替實際的資料庫操作,執行速度會快很多
Repository和DAO的區別
DAO是傳統MVC中Model的關鍵角色,全稱是Data Access Object。DAO直接負責資料庫的存取工作,乍一看兩者非常類似,但從架構設計上講兩者有著本質的區別:
Repository蘊含著真正的OO概念,即一個數據倉庫角色,負責所有物件的持久化管理。DAO則沒有擺脫資料的影子,仍然停留在資料操作的層面上。Repository是相對物件而言,DAO則是相對資料庫而言,雖然可能是同一個東西 ,但側重點完全不同。
接下來本篇文章將針對使用CrudRepository實現Repository資料庫讀寫:
在Gradle 的build.gradle配置檔案中追加一下jpa依賴:'org.springframework.boot:spring-boot-starter-data-jpa'
dependencies { compile( 'org.springframework.boot:spring-boot-starter-actuator', 'org.springframework.boot:spring-boot-starter-web', 'org.springframework.boot:spring-boot-starter-data-jpa', 'org.springframework.boot:spring-boot-devtools', 'mysql:mysql-connector-java' ) testCompile('org.springframework.boot:spring-boot-starter-test') }
對於使用maven的朋友可以使用一下配置:
<!-- spring boot 父節點依賴,
引入這個之後相關的引入就不需要新增version配置,
spring boot會自動選擇最合適的版本進行新增。
-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- spring boot jpa支援:... -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
application.yml或propertites引入資料來源配置:
application.yml:
#本地環境
spring:
profiles: local
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/bootdb?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
username: root
password: root
jpa:
hibernate:
ddl-auto: update
show-sql: true
application.properties
########################################################
###datasource 配置MySQL資料來源;
########################################################
spring.datasource.url = jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf8
spring.datasource.username = root
spring.datasource.password = root
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.max-active=20
spring.datasource.max-idle=8
spring.datasource.min-idle=8
spring.datasource.initial-size=10
########################################################
### Java Persistence Api 自動進行建表
########################################################
# 指定資料來源型別
spring.jpa.database = MYSQL
# 指定是否在控制檯輸出SQL語句
spring.jpa.show-sql = true
# 支援自動建表 Hibernate ddl auto (create, create-drop, update)
spring.jpa.hibernate.ddl-auto = update
# 命名策略(Naming strategy):用於指定實體與表對映的命名規範,可以使用自定義策略
# 這裡使用自帶的策略
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
# 資料庫方言 stripped before adding them to the entity manager)
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
CrudRepository提供的基本的讀寫方法
<S extends T> S save(S entity);
<S extends T> Iterable<S> save(Iterable<S> entities);
T findOne(ID id);
boolean exists(ID id);
Iterable<T> findAll();
Iterable<T> findAll(Iterable<ID> ids);
long count();
void delete(ID id);
void delete(T entity);
void delete(Iterable<? extends T> entities);
void deleteAll();
CrudRepository類如其名,可以勝任最基本的CRUD操作。其中save方法在可兩用,引數中不存在主鍵時執行insert操作,存在主鍵則執行update操作,相當於是一個upsert操作。
建立實體類:此類即代表資料庫表實體,也代表資料庫表結構,可以通過註解指定實體關聯關係
@Entity
public class UserInfo implements Serializable{
private static final long serialVersionUID = 1L;
@[email protected]
private long uid;//使用者id;
@Column(unique=true)
private String username;//賬號.
private String name;//名稱(暱稱或者真實姓名,不同系統不同定義)
private String password; //密碼;
private String salt;//加密密碼的鹽
private byte state;//使用者狀態,0:建立未認證(比如沒有啟用,沒有輸入驗證碼等等)--等待驗證的使用者 , 1:正常狀態,2:使用者被鎖定.
@ManyToMany(fetch=FetchType.EAGER)//立即從資料庫中進行載入資料;
@JoinTable(name = "SysUserRole", joinColumns = { @JoinColumn(name = "uid") }, inverseJoinColumns ={@JoinColumn(name = "roleId") })
private List<SysRole> roleList;// 一個使用者具有多個角色
public List<SysRole> getRoleList() {
return roleList;
}
public void setRoleList(List<SysRole> roleList) {
this.roleList = roleList;
}
建立介面實現類:
/**
* UserInfo持久化類:實現CrudRepository,介面,並制定介面泛型,即與指定的實體表進行繫結;
* @author
* @version v.0.1
*/
public interface UserInfoRepository extends CrudRepository<UserInfo,Long>{
/**通過username查詢使用者資訊;此處無需寫出具體sql,但方法名稱必須符合命名策略
*
*/
public UserInfo findByUsername(String username);
}
建立Service層實現:此處service介面層可自行定義,此處僅代表示例
/**
* service層可直接注入 我們實現Repostitory介面
*/
@Service
public class UserInfoServiceImpl implements UserInfoService{
@Resource
private UserInfoRepository userInfoRepository;
@Override
public UserInfo findByUsername(String username) {
System.out.println("UserInfoServiceImpl.findByUsername()");
return userInfoRepository.findByUsername(username);
}
/**
* 這裡的save方法是CrudRepository預設提供的
*/
@Override
public void UserInfoSave(UserInfo userInfo) {
System.out.println("UserInfoServiceImpl.UserInfoSave()");
userInfoRepository.save(userInfo);
}
}
編寫Controller層實現:
@Controller
@RequestMapping("/userInfo")
public class UserInfoController {
@Autowired
UserInfoService userInfoService;
/**
* 使用者查詢.使用自定義方法
* @return
*/
@RequestMapping(value="/user",method=RequestMethod.GET)
public String userInfo(@RequestParam String username){
userInfoService.findByUsername(username);
return "userInfo";
}
/**
* 使用者新增 使用系統自帶方法;
* @return
*/
@RequestMapping(value="/user",method=RequestMethod.POST)
public String userInfoAdd(@RequestBody UserInfo userInfo){
userInfoService.userInfoSave(userInfo);
return "userInfoAdd";
}
}
以上是本篇文章的相關實戰程式碼,通過以上實現,啟動SpringBoot應用,會自動建立UserInfo表,
可以通過POSTMAN等軟體進行介面測試:
新增使用者資訊:
查詢我們新增的使用者資訊:'127.0.0.1:8080/userinfo?username=zhangsan',得到以下結果:
擴充套件:Spring Boot 也提供了其他Repository介面,例如:JpaRepository
JpaRepository繼承自CrudRepostitory,並提供的基本方法:
List<T> findAll();
List<T> findAll(Sort sort);
List<T> findAll(Iterable<ID> ids);
<S extends T> List<S> save(Iterable<S> entities);
void flush();
<S extends T> S saveAndFlush(S entity);
void deleteInBatch(Iterable<T> entities);
void deleteAllInBatch();
T getOne(ID id);
@Override
<S extends T> List<S> findAll(Example<S> example);
@Override
<S extends T> List<S> findAll(Example<S> example, Sort sort);
JpaRepository則進一步擴充套件了部分功能:
- 查詢列表(返回值為List)
- 批量刪除
- 強制同步
- Example查詢
在接下來的文章中將進行實踐,敬請期待