SpringBoot—訪問關係型資料庫—SpringData JPA
一、SpringData JPA是什麼
上一節學習瞭如何入門SpringBoot,本篇章介紹springboot對資料庫是如何進行訪問的。在介紹之前,有必要了解一下SpringDataJPA,這是SpringCore中的一個專案,致力於簡化對資料庫的訪問,增強了ORM的操作。對於JPA(Java persisten API),全稱為Java持久化API,是JAVAEE中的一套規範API。它推出的目的是對ORM框架進行大統一,它提供一套介面,讓廠商們(如hibernate)對JPA提供實現。JPA與hibernate的關係就像JDBC與Mysql驅動、Oracle驅動一樣的關係,只是它更加高度抽象,可以稱之為ORM框架的介面,它的層遞關係是這樣的:而SpringDataJPA是什麼樣子的呢?相信學過hibernate的同學一定也學過hibernate template,甚至自己實現過hibernate template。沒錯,SpringData JPA就很像這樣一款template,把該有的東西都給你封裝好,當然,其強大不止這一點點。相信學過mybatis的同學也知道,我們只需要一個mapper介面與一些mapper.xml,就可以讓其代理實現的持久層。SpringDataJPA在使用的時候,也只需要宣告一個介面,讓其Spring以代理的形式生成Dao。對於SpringDataJPA與hibernate等ORM框架、JPA的關係是這樣子的:
SpringDataJPA對類似hibernate這樣的框架又做了一層封裝,以便於我們程式設計的時候使用更方便。好了,說了那麼多理論,下面就開始實踐吧。
二、開始實踐
1.建立maven web專案,名稱為springboot-jpa,在pom.xml中匯入以下依賴:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.1.RELEASE</version> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> <springBoot.groupId>org.springframework.boot</springBoot.groupId> </properties> <dependencies> <!-- SpringBoot Start --> <dependency> <groupId>${springBoot.groupId}</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- jpa --> <dependency> <groupId>${springBoot.groupId}</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>${springBoot.groupId}</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <!-- mysql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies>
其中SpringDataJPA核心支援依賴是spring-boot-starter-data-jpa。
2.編輯配置
待maven構建導包完成後,請在mysql中建立好資料庫springboot_test,在src/main/resources中新增application.yml配置,程式碼如下所示:server:
port: 8080
tomcat:
uri-encoding: UTF-8
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/springboot_test?characterEncoding=utf8
username: root
password: root
jpa:
database: MYSQL
show-sql: true
#hibernate ddl auto(validate,create,update,create-drop)
hibernate:
ddl-auto: update
naming:
strategy: org.hibernate.cfg.ImprovedNamingStrategy
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL5Dialect
這些配置相信大家都能看得懂,最後一行是資料庫方言,如果是oracle,就有oracle的方言。
包結構組織如下圖:
在src/main/java中新建org.fage包,在其中建立一個Jpa的Java配置類:
package org.fage;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
*
* @author Caizhfy
* @email [email protected]
* @createTime 2017年10月30日
* @description JPA基礎配置類
*
*/
@Order(Ordered.HIGHEST_PRECEDENCE)
@Configuration
@EnableTransactionManagement(proxyTargetClass=true)
@EnableJpaRepositories(basePackages={"org.fage.**.repository"})
@EntityScan(basePackages={"org.fage.**.domain"})
public class JpaConfiguration {
@Bean
PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor(){
return new PersistenceExceptionTranslationPostProcessor();
}
}
@Order聲明瞭元件載入的順序,其中接受一個整形值,值越低約先載入;
@Configuration聲明瞭這是一個配置類,該註解中包含有@Component註解,可以讓SpringBoot自動掃描載入;@EnableTransactionManagement聲明瞭開啟事務管理器代理;
@EnableJpaRepositories宣告repository(也就是原來的dao,SpringData中稱其為Repository)所在位置,值中的兩個星號是萬用字元,代表org.fage.任何路徑下的.repository包中都是repository;
@EntityScan是對實體元件位置的宣告與掃描,兩個星號依舊是萬用字元。在根包中建立入口類App.java:
package org.fage;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
*
* @author Caizhfy
* @email [email protected]
* @createTime 2017年10月30日
* @description Springboot-jpa學習建立步驟:
* 1.建立專案
* 2.新增依賴,填寫配置類
* 3.配置application.yml
* 4.配置實體jpa關係
* 5.繼承jpaRepository
* 6.編寫測試用例
*/
@SpringBootApplication
@ImportAutoConfiguration(value=JpaConfiguration.class)
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
3.建立實體建模:
建模關係是有部門、使用者、角色三個實體;部門與使用者是一對多的關係,使用者與角色是多對多的關係,在org.fage.domain包中建立三個實體,建模程式碼如下 部門實體:@Entity
@Table(name = "department")
public class Department implements Serializable {
private static final long serialVersionUID = 159714803901985366L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy="department",fetch=FetchType.LAZY)
private List<User> users;
//getter and setter
...
}
使用者實體:
@Entity
@Table(name = "user")
public class User implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
@Column(name = "create_date")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Temporal(TemporalType.TIMESTAMP)
private Date createDate;
//一對多對映
@ManyToOne
@JoinColumn(name = "department_id")
@JsonBackReference // 防止物件的遞迴訪問
private Department department;
//多對多對映
@ManyToMany(fetch=FetchType.EAGER)
@JoinTable(name = "user_role",
joinColumns = {@JoinColumn(name="user_id")},
inverseJoinColumns = {@JoinColumn(name = "role_id")}
)
//getter and setter
}
角色實體:
@Entity
@Table(name="role")
public class Role implements Serializable{
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
private String name;
//getter and setter
}
實體對映關係建立完成,解釋一下其中的註解,這些註解其實大多數都是在學JPA與hibernate的時候學會的:@Entity宣告這是一個實體類;@Table宣告該實體在表中對應的表名是什麼;@Id宣告該屬性為實體對應表的主鍵;@GeneratedValue聲明瞭主鍵策略是什麼,這裡使用的是自動增長主鍵策略;@ManyToOne與@OneToMany聲明瞭該實體與對應屬性的實體是多對一或者一對多的關係,其中如果設立雙向關係記得設定mappedBy,fetch的值聲明瞭載入方式是懶載入還是立即載入;@ManyToMany是實體間多對多的關係,@JoinTable設定了兩個多對多的實體的中間表外來鍵。
4.建立持久層Dao
在SpringDataJPA中,我們不在稱其為mapper或者dao,而是稱為repository,我們來為三個實體分別建立自己的repository。在org.fage.repository中建立如下三個介面,繼承自JpaRepository,泛型左邊為實體型別,右邊為該實體的主鍵型別: 部門repository:package org.fage.repository;
import org.fage.domain.Department;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface DepartmentRepository extends JpaRepository<Department, Long>{}
使用者repository:
@Repository
public interface UserRepository extends JpaRepository<User, Long>{
//And用法
User findById(long id);
User findByIdAndUsername(long id, String username);
//Or用法
User findByIdOrUsername(long id, String name);
//Between用法
User findByCreateDateBetween(Date start, Date end);
//LessThan用法
List<User> findByCreateDateLessThan(Date start);
//GreaterThan用法
List<User> findByCreateDateGreaterThan(Date start);
//IsNull/IsNutNull用法
List<User> findByUsernameIsNull();
//Like/NotLike用法
List<User> findByUsernameLike(String username);
//OrderBy用法
List<User> findByUsernameOrderByIdAsc(String username);
//Not用法
List<User> findByUsernameNot(String username);
//In/NotIn用法
List<User> findByUsernameIn(Collection<String> nameList);
}
角色repository:
@Repository
public interface RoleRepository extends JpaRepository<Role, Long>{}
至此,我們可以建立Junit程式,測試使用這三個持久層介面了,在src/test/java中可以建立測試程式進行測試了,hibernate實現會自動幫我們生成表,SpringDataJPA提供了常用的CRUD操作:
@RunWith(SpringRunner.class)
@SpringBootTest
public class RepositoryTest {
private final Logger log = LoggerFactory.getLogger(RepositoryTest.class);
@Autowired
UserRepository userRepository;
@Autowired
RoleRepository roleRepository;
@Autowired
DepartmentRepository departmentRepository;
@Before
public void initData() {
departmentRepository.deleteAll();
roleRepository.deleteAll();
userRepository.deleteAll();
Department d = new Department();
d.setName("開發部");
departmentRepository.save(d);
Assert.assertNotNull(d.getId());
Role r = new Role();
r.setName("部門經理");
roleRepository.save(r);
Assert.assertNotNull(r.getId());
List<Role> roles = new ArrayList<Role>();
roles.add(r);
User u = new User();
u.setUsername("蔡智法");
u.setCreateDate(new Date());
u.setDepartment(d);
u.setRoles(roles);
userRepository.save(u);
Assert.assertNotNull(u.getId());
}
@Test
public void testGeneralMethod(){
System.out.println(userRepository.findByUsernameLike("蔡智法"));
}
@Test
public void testFindPage() {
//hibernate一對多分頁原理:先分頁,然後在將id作為引子查詢(效率低)
Pageable pageable = new PageRequest(0, 5, new Sort(Sort.Direction.ASC, "id"));
Page<Department> page = departmentRepository.findAll(pageable);
System.out.println(page.getNumberOfElements());
}
}
至此,執行成功。其實如果你也動手試一試,發現增刪改查都不需要實現程式碼就能擁有這些功能,這些Repository介面中還有很多方法可以嘗試,希望大家自行踴躍嘗試,太便捷了。沒搞錯吧?這些介面甚至一行業務程式碼都不用寫(UserRepository中的程式碼待會兒解釋),就能實現增刪改查、分頁操作??沒錯,確實就是這麼簡單。不難發現,我們獲得支援的最重要一點是繼承了JpaRepository(該介面提供了上層介面更多的查詢操作)介面,跟蹤原始碼發現JpaRepository介面繼承了上層的PageAndSortingRepository(該介面提供了分頁以及排序的支援),PageAndSortingRepository繼承自CrudRepository(該介面提供基礎的增刪改查操作),而CrudRepository又繼承自Repository。我們知道,他們都是介面,本身沒有實現方法,但是SpringDataJPA幫我們提供了一套實現,在執行的時候會以代理的形式給我們生成實現類,只要你繼承了Spring給你的這些Repository介面,那麼你就能獲得這些方法支援。
問題又來了,UserRepository介面中自定義宣告的方法我們也沒有實現,為什麼也能正常使用呢? 那是因為在SpringDataJPA中,自定義的方法一般有兩種,第一種就是這種“約定命名”法,這種方法一定要查詢命名規範,比如findByXXX,SpringData會根據字首、中間連線詞(Or、And、Like、NotNull等等類似Sql中的關鍵詞),詳情使用請看下錶,內部會自己轉換成JPQL使用:
內部幫我們拼接sql代理生成方法的實現,不得不感嘆,真的太方便了。 第二種方法就是使用@Query註解使用JPQL(類似SQL與EL的組合)語句查詢,這種查詢一般不使用代理,是直接內部轉化成SQL進行執行,這種方法比前一種靈活一些,後面章節會提到(還有一種方法,就是自定義增強Repository實現),使用原生SQL查詢,這樣方便優化SQL。自定義增強Repository與框架原理解析,在後續文章中會陸續更新。
以上原始碼在https://github.com/Phapha1996/springboot-jpa能檢出。 在本文中,最重要的詞就是代理了,如果不瞭解代理模式的同學,希望能惡補一波代理,這是一組非常值得學習而有用的模式。
相關推薦
SpringBoot—訪問關係型資料庫—SpringData JPA
一、SpringData JPA是什麼 上一節學習瞭如何入門SpringBoot,本篇章介紹springboot對資料庫是如何進行訪問的。在介紹之前,有必要了解一下SpringDataJPA,這是Sp
SpringBoot:SpringData JPA:訪問關係型資料庫
一、SpringData JPA是什麼 上一節學習瞭如何入門SpringBoot,本篇章介紹springboot對資料庫是如何進行訪問的。在介紹之前,有必要了解一下SpringDataJPA,這是SpringCore中的一個專案,致力於簡化對資料庫的訪問,增強了ORM的操作。對於JPA(Java
SpringBoot-訪問MySQL資料庫
1.開發工具:Intellij Idea, 通過JPA(Java Persistence API,Java 資料持久化介面)來操作資料庫 2.開始 2.1新建Spring Initializr 專案,勾選web,mysql,jpa依賴 專案結構如下:
十五、SpringBoot之資料訪問整合SpringData JPA
1.SpringData簡介 2.整合SpringData JPA JPA:ORM(Object Relational Mapping 物件關係對映); 1.編寫一個實體類(bean)和資料表
SpringBoot之使用Spring-data-jpa更加簡單優雅的訪問資料庫
@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(Application.class) public class ApplicationTests {@Autowiredprivate UserRepository
搭建 SpringBoot 2.0 專案 (三) 使用 JPA 訪問MySQL資料庫
SpringBoot 入門系列: 本博文主要講述使用 JPA 訪問 MySQL 資料庫,參考了官網的入門指南,連結如下: 執行環境: MySQL 5.6或更高版本。 Maven STS 1、首先登入Mysq
SpringBoot集成Spring-data-jpa訪問數據庫(四)
data inter 自動 繼承 users boot mea cte emp 相比使用JdbcTemplate,Spring-data-jpa使用起來更方便 1.首先UserService 繼承JpaRepository public interface UserSer
Springboot+SpringData+jpa+redis+postgresql後臺專案
https://github.com/MAXIAODONGS/Configure 主要做的是基於Springboot+SpringData+jpa+redis+postgresql後臺檔案管理服務、包括支援遠端連線伺服器讀寫伺服器檔案 程式碼下載後需要配置application.yml中的p
springboot(二) 和資料庫(jdbcTemplete,jpa,mybatis)連線 單元測試
建立資料庫 springboot-database 建立user表 CREATE TABLE `user` ( `id` int(11) DEFAULT NULL, `name` varchar(255) DEFAULT NULL, `pass
11-SpringBoot之資料庫(二)——JPA
SpringBoot之資料庫(二)——JPA 1. 新增pom依賴 2. JPA配置 3. 例項開發 3.1 建立實體類 3.2 DAO 3.3 Service 3.4 Controller 3.5 測試
SpringBoot(六) SpirngBoot與Mysql關係型資料庫
pom.xml檔案的配置 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifa
SpringBoot:SpringData JPA:進階查詢—JPQL/原生SQL查詢、分頁處理、部分欄位對映查詢
上一篇介紹了入門基礎篇SpringDataJPA訪問資料庫。本篇介紹SpringDataJPA進一步的定製化查詢,使用JPQL或者SQL進行查詢、部分欄位對映、分頁等。本文儘量以簡單的建模與程式碼進行展示操作,文章比較長,包含查詢的方方面面。如果能耐心看完這篇文章,你應該能使用SpringDataJ
SpringBoot整合SpringData-JPA
1、依賴新增 // 新增spring data jpa依賴 compile('org.springframework.boot:spring-boot-starter-data-jpa') //
Springboot集成SpringData JPA
-- div urn ner direction req builder findall pos 序 StringData JPA 是微服務框架下一款ORM框架,在微服務體系架構下,數據持久化框架,主要為SpringData JPA及Mybatis兩種,這兩者的具體比較,本
SpringBoot對非關係型資料庫NoSql的支援
NoSql是對於所有不使用關係作為資料管理的資料庫系統的總稱,NoSql的特點主要是不使用sql作為查詢語言。資料儲存也不是固定的表和欄位 NoSql資料庫主要有文件儲存型(MongoDB),圖形關係儲存型(Neo4j),鍵值對儲存型(Redis) Sp
SpringBoot-SpringData-JPA整合
資料庫訪問這一層 常用的方式有:JdbcTemplate ,SpringData-JPA, MyBatis 今天我們說一下SpringData-JPA, 使用上一篇SpringBoot-JUnit作為基礎程式碼 注:本文使用的例子來自DD程式設計師,旨在學習
29-SpringBoot——核心-非關係型資料庫NoSQL
SpringBoot核心-非關係型資料庫NoSQL MongoDB MongoDB 是一個基於文件( Document )的儲存型的資料瘁,使用面向物件的思想,每一條資料記錄都是文件的物件。Spring 對MongoDB
用IDEA搭建第一個SpringBoot+SpringData Jpa框架
本文純屬自己的一些摸索和實踐,如有寫的不好的地方歡迎大家一起討論。 首先我們來建立一個maven專案。 建立java目錄並將其變為Sources Root資料夾。 3.接下來配置pom.xml檔案裡的一些依賴 <
帶你搭一個SpringBoot+SpringData JPA的環境
開發十年,就只剩下這套架構體系了! >>>
【極簡版】SpringBoot+SpringData JPA 管理系統
開發十年,就只剩下這套架構體系了! >>>